InterpAsm-x86.S revision 291758c5c4902900c6f86794ba8ab9cad9b26197
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_RETURN_VOID_BARRIER: /* 0xf1 */ 5959 /* (stub) */ 5960 GET_GLUE(%ecx) 5961 SAVE_PC_TO_GLUE(%ecx) # only need to export these two 5962 SAVE_FP_TO_GLUE(%ecx) # only need to export these two 5963 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 5964 call dvmMterp_OP_RETURN_VOID_BARRIER # do the real work 5965 GET_GLUE(%ecx) 5966 LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values 5967 LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values 5968 FETCH_INST() 5969 GOTO_NEXT 5970/* ------------------------------ */ 5971 .balign 64 5972.L_OP_IGET_QUICK: /* 0xf2 */ 5973/* File: x86/OP_IGET_QUICK.S */ 5974 /* For: iget-quick, iget-object-quick */ 5975 /* op vA, vB, offset@CCCC */ 5976 movzbl rINST_HI,%ecx # ecx<- BA 5977 sarl $4,%ecx # ecx<- B 5978 GET_VREG(%ecx,%ecx) # vB (object we're operating on) 5979 movzwl 2(rPC),%eax # eax<- field byte offset 5980 cmpl $0,%ecx # is object null? 5981 je common_errNullObject 5982 movl (%ecx,%eax,1),%eax 5983 movzbl rINST_HI,%ecx 5984 FETCH_INST_WORD(2) 5985 ADVANCE_PC(2) 5986 andb $0xf,%cl # rINST_FULL<- A 5987 SET_VREG (%eax,%ecx) # fp[A]<- result 5988 GOTO_NEXT 5989 5990/* ------------------------------ */ 5991 .balign 64 5992.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 5993/* File: x86/OP_IGET_WIDE_QUICK.S */ 5994 /* For: iget-wide-quick */ 5995 /* op vA, vB, offset@CCCC */ 5996 movzbl rINST_HI,%ecx # ecx<- BA 5997 sarl $4,%ecx # ecx<- B 5998 GET_VREG(%ecx,%ecx) # vB (object we're operating on) 5999 movzwl 2(rPC),%eax # eax<- field byte offset 6000 cmpl $0,%ecx # is object null? 6001 je common_errNullObject 6002 leal (%ecx,%eax,1),%eax # eax<- address of 64-bit source 6003 movl (%eax),%ecx # ecx<- lsw 6004 movl 4(%eax),%eax # eax<- msw 6005 movzbl rINST_HI,rINST_FULL 6006 andb $0xf,rINST_LO # rINST_FULL<- A 6007 SET_VREG_WORD(%ecx,rINST_FULL,0) # v[A+0]<- lsw 6008 SET_VREG_WORD(%eax,rINST_FULL,1) # v[A+1]<- msw 6009 FETCH_INST_WORD(2) 6010 ADVANCE_PC(2) 6011 GOTO_NEXT 6012 6013/* ------------------------------ */ 6014 .balign 64 6015.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 6016/* File: x86/OP_IGET_OBJECT_QUICK.S */ 6017/* File: x86/OP_IGET_QUICK.S */ 6018 /* For: iget-quick, iget-object-quick */ 6019 /* op vA, vB, offset@CCCC */ 6020 movzbl rINST_HI,%ecx # ecx<- BA 6021 sarl $4,%ecx # ecx<- B 6022 GET_VREG(%ecx,%ecx) # vB (object we're operating on) 6023 movzwl 2(rPC),%eax # eax<- field byte offset 6024 cmpl $0,%ecx # is object null? 6025 je common_errNullObject 6026 movl (%ecx,%eax,1),%eax 6027 movzbl rINST_HI,%ecx 6028 FETCH_INST_WORD(2) 6029 ADVANCE_PC(2) 6030 andb $0xf,%cl # rINST_FULL<- A 6031 SET_VREG (%eax,%ecx) # fp[A]<- result 6032 GOTO_NEXT 6033 6034 6035/* ------------------------------ */ 6036 .balign 64 6037.L_OP_IPUT_QUICK: /* 0xf5 */ 6038/* File: x86/OP_IPUT_QUICK.S */ 6039 /* For: iput-quick */ 6040 /* op vA, vB, offset@CCCC */ 6041 movzbl rINST_HI,%ecx # ecx<- BA 6042 sarl $4,%ecx # ecx<- B 6043 GET_VREG(%ecx,%ecx) # vB (object we're operating on) 6044 movzbl rINST_HI,rINST_FULL 6045 andb $0xf,rINST_LO # rINST_FULL<- A 6046 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 6047 movzwl 2(rPC),%eax # eax<- field byte offset 6048 testl %ecx,%ecx # is object null? 6049 je common_errNullObject 6050 movl rINST_FULL,(%ecx,%eax,1) 6051 FETCH_INST_WORD(2) 6052 ADVANCE_PC(2) 6053 GOTO_NEXT 6054 6055/* ------------------------------ */ 6056 .balign 64 6057.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 6058/* File: x86/OP_IPUT_WIDE_QUICK.S */ 6059 /* For: iput-wide-quick */ 6060 /* op vA, vB, offset@CCCC */ 6061 movzbl rINST_HI,%ecx # ecx<- BA 6062 sarl $4,%ecx # ecx<- B 6063 GET_VREG(%ecx,%ecx) # vB (object we're operating on) 6064 movzwl 2(rPC),%eax # eax<- field byte offset 6065 testl %ecx,%ecx # is object null? 6066 je common_errNullObject 6067 leal (%ecx,%eax,1),%ecx # ecx<- Address of 64-bit target 6068 movzbl rINST_HI,rINST_FULL 6069 andb $0xf,rINST_LO # rINST_FULL<- A 6070 GET_VREG_WORD(%eax,rINST_FULL,0) # eax<- lsw 6071 GET_VREG_WORD(rINST_FULL,rINST_FULL,1) # rINST_FULL<- msw 6072 movl %eax,(%ecx) 6073 movl rINST_FULL,4(%ecx) 6074 FETCH_INST_WORD(2) 6075 ADVANCE_PC(2) 6076 GOTO_NEXT 6077 6078/* ------------------------------ */ 6079 .balign 64 6080.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 6081/* File: x86/OP_IPUT_OBJECT_QUICK.S */ 6082 /* For: iput-object-quick */ 6083 /* op vA, vB, offset@CCCC */ 6084 movzbl rINST_HI,%ecx # ecx<- BA 6085 sarl $4,%ecx # ecx<- B 6086 GET_VREG(%ecx,%ecx) # vB (object we're operating on) 6087 movzbl rINST_HI,rINST_FULL 6088 andb $0xf,rINST_LO # rINST_FULL<- A 6089 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 6090 movzwl 2(rPC),%eax # eax<- field byte offset 6091 testl %ecx,%ecx # is object null? 6092 je common_errNullObject 6093 movl rINST_FULL,(%ecx,%eax,1) 6094 GET_GLUE(%eax) 6095 jmp .LOP_IPUT_OBJECT_QUICK_finish 6096 6097/* ------------------------------ */ 6098 .balign 64 6099.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 6100/* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */ 6101 /* 6102 * Handle an optimized virtual method call. 6103 * 6104 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 6105 */ 6106 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 6107 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 6108 movzwl 4(rPC),%eax # eax<- FEDC or CCCC 6109 movzwl 2(rPC),%ecx # ecx<- BBBB 6110 .if (!0) 6111 andl $0xf,%eax # eax<- C (or stays CCCC) 6112 .endif 6113 GET_VREG(%eax,%eax) # eax<- vC ("this" ptr) 6114 testl %eax,%eax # null? 6115 je common_errNullObject # yep, throw exception 6116 movl offObject_clazz(%eax),%eax # eax<- thisPtr->clazz 6117 movl offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable 6118 EXPORT_PC() # might throw later - get ready 6119 movl (%eax,%ecx,4),%eax # eax<- vtable[BBBB] 6120 jmp common_invokeMethodNoRange 6121 6122/* ------------------------------ */ 6123 .balign 64 6124.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 6125/* File: x86/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 6126/* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */ 6127 /* 6128 * Handle an optimized virtual method call. 6129 * 6130 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 6131 */ 6132 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 6133 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 6134 movzwl 4(rPC),%eax # eax<- FEDC or CCCC 6135 movzwl 2(rPC),%ecx # ecx<- BBBB 6136 .if (!1) 6137 andl $0xf,%eax # eax<- C (or stays CCCC) 6138 .endif 6139 GET_VREG(%eax,%eax) # eax<- vC ("this" ptr) 6140 testl %eax,%eax # null? 6141 je common_errNullObject # yep, throw exception 6142 movl offObject_clazz(%eax),%eax # eax<- thisPtr->clazz 6143 movl offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable 6144 EXPORT_PC() # might throw later - get ready 6145 movl (%eax,%ecx,4),%eax # eax<- vtable[BBBB] 6146 jmp common_invokeMethodRange 6147 6148 6149/* ------------------------------ */ 6150 .balign 64 6151.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 6152/* File: x86/OP_INVOKE_SUPER_QUICK.S */ 6153 /* 6154 * Handle an optimized "super" method call. 6155 * 6156 * for: [opt] invoke-super-quick, invoke-super-quick/range 6157 */ 6158 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 6159 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 6160 GET_GLUE(%ecx) 6161 movzwl 4(rPC),%eax # eax<- GFED or CCCC 6162 movl offGlue_method(%ecx),%ecx # ecx<- current method 6163 .if (!0) 6164 andl $0xf,%eax # eax<- D (or stays CCCC) 6165 .endif 6166 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6167 GET_VREG(%eax,%eax) # eax<- "this" 6168 movl offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super 6169 testl %eax,%eax # null "this"? 6170 je common_errNullObject # "this" is null, throw exception 6171 movzwl 2(rPC),%eax # eax<- BBBB 6172 movl offClassObject_vtable(%ecx),%ecx # ecx<- vtable 6173 EXPORT_PC() 6174 movl (%ecx,%eax,4),%eax # eax<- super->vtable[BBBB] 6175 jmp common_invokeMethodNoRange 6176 6177/* ------------------------------ */ 6178 .balign 64 6179.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 6180/* File: x86/OP_INVOKE_SUPER_QUICK_RANGE.S */ 6181/* File: x86/OP_INVOKE_SUPER_QUICK.S */ 6182 /* 6183 * Handle an optimized "super" method call. 6184 * 6185 * for: [opt] invoke-super-quick, invoke-super-quick/range 6186 */ 6187 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 6188 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 6189 GET_GLUE(%ecx) 6190 movzwl 4(rPC),%eax # eax<- GFED or CCCC 6191 movl offGlue_method(%ecx),%ecx # ecx<- current method 6192 .if (!1) 6193 andl $0xf,%eax # eax<- D (or stays CCCC) 6194 .endif 6195 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6196 GET_VREG(%eax,%eax) # eax<- "this" 6197 movl offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super 6198 testl %eax,%eax # null "this"? 6199 je common_errNullObject # "this" is null, throw exception 6200 movzwl 2(rPC),%eax # eax<- BBBB 6201 movl offClassObject_vtable(%ecx),%ecx # ecx<- vtable 6202 EXPORT_PC() 6203 movl (%ecx,%eax,4),%eax # eax<- super->vtable[BBBB] 6204 jmp common_invokeMethodRange 6205 6206 6207/* ------------------------------ */ 6208 .balign 64 6209.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ 6210/* File: x86/OP_IPUT_OBJECT_VOLATILE.S */ 6211/* File: x86/OP_IPUT_OBJECT.S */ 6212 /* 6213 * Object field put. 6214 * 6215 * for: iput-object 6216 */ 6217 /* op vA, vB, field@CCCC */ 6218 GET_GLUE(%ecx) 6219 SPILL(rIBASE) # need another reg 6220 movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC 6221 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 6222 movzbl rINST_HI,%ecx # ecx<- BA 6223 sarl $4,%ecx # ecx<- B 6224 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 6225 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 6226 andb $0xf,rINST_LO # rINST_FULL<- A 6227 GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr 6228 movl (%eax,rIBASE,4),%eax # resolved entry 6229 testl %eax,%eax # is resolved entry null? 6230 jne .LOP_IPUT_OBJECT_VOLATILE_finish # no, already resolved 6231 movl rIBASE,OUT_ARG1(%esp) 6232 GET_GLUE(rIBASE) 6233 jmp .LOP_IPUT_OBJECT_VOLATILE_resolve 6234 6235 6236/* ------------------------------ */ 6237 .balign 64 6238.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ 6239/* File: x86/OP_SGET_OBJECT_VOLATILE.S */ 6240/* File: x86/OP_SGET.S */ 6241 /* 6242 * General 32-bit SGET handler. 6243 * 6244 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 6245 */ 6246 /* op vAA, field@BBBB */ 6247 GET_GLUE(%ecx) 6248 movzwl 2(rPC),%eax # eax<- field ref BBBB 6249 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 6250 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 6251 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 6252 testl %eax,%eax # resolved entry null? 6253 je .LOP_SGET_OBJECT_VOLATILE_resolve # if not, make it so 6254.LOP_SGET_OBJECT_VOLATILE_finish: # field ptr in eax 6255 movl offStaticField_value(%eax),%eax 6256 movzbl rINST_HI,%ecx # ecx<- AA 6257 FETCH_INST_WORD(2) 6258 ADVANCE_PC(2) 6259 SET_VREG(%eax,%ecx) 6260 GOTO_NEXT 6261 6262 6263/* ------------------------------ */ 6264 .balign 64 6265.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ 6266/* File: x86/OP_SPUT_OBJECT_VOLATILE.S */ 6267/* File: x86/OP_SPUT_OBJECT.S */ 6268 /* 6269 * SPUT object handler. 6270 */ 6271 /* op vAA, field@BBBB */ 6272 GET_GLUE(%ecx) 6273 movzwl 2(rPC),%eax # eax<- field ref BBBB 6274 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 6275 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 6276 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField 6277 testl %eax,%eax # resolved entry null? 6278 je .LOP_SPUT_OBJECT_VOLATILE_resolve # if not, make it so 6279.LOP_SPUT_OBJECT_VOLATILE_finish: # field ptr in eax 6280 movzbl rINST_HI,%ecx # ecx<- AA 6281 GET_VREG(%ecx,%ecx) 6282 jmp .LOP_SPUT_OBJECT_VOLATILE_continue 6283 6284 6285/* ------------------------------ */ 6286 .balign 64 6287.L_OP_UNUSED_FF: /* 0xff */ 6288/* File: x86/OP_UNUSED_FF.S */ 6289/* File: x86/unused.S */ 6290 jmp common_abort 6291 6292 6293 6294 .balign 64 6295 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 6296 .global dvmAsmInstructionEnd 6297dvmAsmInstructionEnd: 6298 6299/* 6300 * =========================================================================== 6301 * Sister implementations 6302 * =========================================================================== 6303 */ 6304 .global dvmAsmSisterStart 6305 .type dvmAsmSisterStart, %function 6306 .text 6307 .balign 4 6308dvmAsmSisterStart: 6309 6310/* continuation for OP_CONST_STRING */ 6311 6312/* This is the less common path, so we'll redo some work 6313 here rather than force spills on the common path */ 6314.LOP_CONST_STRING_resolve: 6315 GET_GLUE(%eax) 6316 movl %ecx,rINST_FULL # rINST_FULL<- AA 6317 EXPORT_PC() 6318 movl offGlue_method(%eax),%eax # eax<- glue->method 6319 movzwl 2(rPC),%ecx # ecx<- BBBB 6320 movl offMethod_clazz(%eax),%eax 6321 SPILL(rPC) 6322 movl %ecx,OUT_ARG1(%esp) 6323 movl %eax,OUT_ARG0(%esp) 6324 call dvmResolveString # go resolve 6325 UNSPILL(rPC) 6326 testl %eax,%eax # failed? 6327 je common_exceptionThrown 6328 SET_VREG(%eax,rINST_FULL) 6329 FETCH_INST_WORD(2) 6330 ADVANCE_PC(2) 6331 GOTO_NEXT 6332 6333/* continuation for OP_CONST_STRING_JUMBO */ 6334 6335/* This is the less common path, so we'll redo some work 6336 here rather than force spills on the common path */ 6337.LOP_CONST_STRING_JUMBO_resolve: 6338 GET_GLUE(%eax) 6339 movl %ecx,rINST_FULL # rINST_FULL<- AA 6340 EXPORT_PC() 6341 movl offGlue_method(%eax),%eax # eax<- glue->method 6342 movl 2(rPC),%ecx # ecx<- BBBBBBBB 6343 movl offMethod_clazz(%eax),%eax 6344 SPILL(rPC) 6345 movl %ecx,OUT_ARG1(%esp) 6346 movl %eax,OUT_ARG0(%esp) 6347 call dvmResolveString # go resolve 6348 UNSPILL(rPC) 6349 testl %eax,%eax # failed? 6350 je common_exceptionThrown 6351 SET_VREG(%eax,rINST_FULL) 6352 FETCH_INST_WORD(3) 6353 ADVANCE_PC(3) 6354 GOTO_NEXT 6355 6356/* continuation for OP_CONST_CLASS */ 6357 6358/* This is the less common path, so we'll redo some work 6359 here rather than force spills on the common path */ 6360.LOP_CONST_CLASS_resolve: 6361 GET_GLUE(%eax) 6362 movl %ecx,rINST_FULL # rINST_FULL<- AA 6363 EXPORT_PC() 6364 movl offGlue_method(%eax),%eax # eax<- glue->method 6365 movl $1,OUT_ARG2(%esp) # true 6366 movzwl 2(rPC),%ecx # ecx<- BBBB 6367 movl offMethod_clazz(%eax),%eax 6368 SPILL(rPC) 6369 movl %ecx,OUT_ARG1(%esp) 6370 movl %eax,OUT_ARG0(%esp) 6371 call dvmResolveClass # go resolve 6372 UNSPILL(rPC) 6373 testl %eax,%eax # failed? 6374 je common_exceptionThrown 6375 SET_VREG(%eax,rINST_FULL) 6376 FETCH_INST_WORD(2) 6377 ADVANCE_PC(2) 6378 GOTO_NEXT 6379 6380/* continuation for OP_MONITOR_ENTER */ 6381 6382.LOP_MONITOR_ENTER_continue: 6383 SPILL(rPC) # have to - caller save 6384 movl %ecx,OUT_ARG0(%esp) 6385 movl %eax,OUT_ARG1(%esp) 6386 call dvmLockObject # dvmLockObject(self,object) 6387 UNSPILL(rPC) 6388#ifdef WITH_DEADLOCK_PREDICTION 6389 GET_GLUE(%ecx) 6390 movl offGlueSelf(%ecx),%ecx # ecx<- glue->self 6391 movl offThread_exception(%ecx),%eax 6392 testl %eax,%eax 6393 jne common_exceptionThrown 6394#endif 6395 ADVANCE_PC(1) 6396 GOTO_NEXT 6397 6398/* continuation for OP_MONITOR_EXIT */ 6399 6400.LOP_MONITOR_EXIT_continue: 6401 call dvmUnlockObject # unlock(self,obj) 6402 UNSPILL(rPC) 6403 FETCH_INST_WORD(1) 6404 testl %eax,%eax # success? 6405 ADVANCE_PC(1) 6406 je common_exceptionThrown # no, exception pending 6407 GOTO_NEXT 6408.LOP_MONITOR_EXIT_errNullObject: 6409 ADVANCE_PC(1) # advance before throw 6410 jmp common_errNullObject 6411 6412/* continuation for OP_CHECK_CAST */ 6413 6414 /* 6415 * Trivial test failed, need to perform full check. This is common. 6416 * ecx holds obj->clazz 6417 * eax holds class resolved from BBBB 6418 * rINST_FULL holds object 6419 */ 6420.LOP_CHECK_CAST_fullcheck: 6421 movl %eax,OUT_ARG1(%esp) 6422 movl %ecx,OUT_ARG0(%esp) 6423 SPILL(rPC) 6424 call dvmInstanceofNonTrivial # eax<- boolean result 6425 UNSPILL(rPC) 6426 testl %eax,%eax # failed? 6427 jne .LOP_CHECK_CAST_okay # no, success 6428 6429 # A cast has failed. We need to throw a ClassCastException with the 6430 # class of the object that failed to be cast. 6431 EXPORT_PC() 6432 movl offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz 6433 movl $.LstrClassCastException,%eax 6434 movl offClassObject_descriptor(%ecx),%ecx 6435 movl %eax,OUT_ARG0(%esp) # arg0<- message 6436 movl %ecx,OUT_ARG1(%esp) # arg1<- obj->clazz->descriptor 6437 SPILL(rPC) 6438 call dvmThrowExceptionWithClassMessage 6439 UNSPILL(rPC) 6440 jmp common_exceptionThrown 6441 6442 /* 6443 * Resolution required. This is the least-likely path, and we're 6444 * going to have to recreate some data. 6445 * 6446 * rINST_FULL holds object 6447 */ 6448.LOP_CHECK_CAST_resolve: 6449 GET_GLUE(%ecx) 6450 EXPORT_PC() 6451 movzwl 2(rPC),%eax # eax<- BBBB 6452 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 6453 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB 6454 movl offMethod_clazz(%ecx),%ecx # ecx<- metho->clazz 6455 movl $0,OUT_ARG2(%esp) # arg2<- false 6456 movl %ecx,OUT_ARG0(%esp) # arg0<- method->clazz 6457 SPILL(rPC) 6458 call dvmResolveClass # eax<- resolved ClassObject ptr 6459 UNSPILL(rPC) 6460 testl %eax,%eax # got null? 6461 je common_exceptionThrown # yes, handle exception 6462 movl offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz 6463 jmp .LOP_CHECK_CAST_resolved # pick up where we left off 6464 6465/* continuation for OP_INSTANCE_OF */ 6466 6467 /* 6468 * Trivial test failed, need to perform full check. This is common. 6469 * eax holds obj->clazz 6470 * ecx holds class resolved from BBBB 6471 * rINST_HI has BA 6472 * rPC already spilled 6473 */ 6474.LOP_INSTANCE_OF_fullcheck: 6475 movl %eax,OUT_ARG0(%esp) 6476 movl %ecx,OUT_ARG1(%esp) 6477 call dvmInstanceofNonTrivial # eax<- boolean result 6478 # fall through to OP_INSTANCE_OF_store 6479 6480 /* 6481 * eax holds boolean result 6482 * rINST_HI holds BA 6483 */ 6484.LOP_INSTANCE_OF_store: 6485 UNSPILL(rPC) 6486 movzbl rINST_HI,%ecx # ecx<- BA 6487 FETCH_INST_WORD(2) 6488 andb $0xf,%cl # ecl<- A 6489 ADVANCE_PC(2) 6490 SET_VREG(%eax,%ecx) # vA<- eax 6491 GOTO_NEXT 6492 6493 /* 6494 * Trivial test succeeded, save and bail. 6495 * r9 holds A 6496 */ 6497.LOP_INSTANCE_OF_trivial: 6498 UNSPILL(rPC) 6499 movzbl rINST_HI,%ecx # ecx<- BA 6500 FETCH_INST_WORD(2) 6501 andb $0xf,%cl # ecl<- A 6502 ADVANCE_PC(2) 6503 movl $1,%eax 6504 SET_VREG(%eax,%ecx) # vA<- true 6505 GOTO_NEXT 6506 6507 /* 6508 * Resolution required. This is the least-likely path. 6509 * 6510 * rPC holds BBBB 6511 * rINST_HI holds BA 6512 */ 6513.LOP_INSTANCE_OF_resolve: 6514 movl rPC,OUT_ARG1(%esp) # arg1<- BBBB 6515 GET_GLUE(%ecx) 6516 UNSPILL(rPC) 6517 movl offGlue_method(%ecx),%ecx 6518 movl $1,OUT_ARG2(%esp) # arg2<- true 6519 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6520 EXPORT_PC() 6521 movl %ecx,OUT_ARG0(%esp) # arg0<- method->clazz 6522 call dvmResolveClass # eax<- resolved ClassObject ptr 6523 UNSPILL(rPC) 6524 testl %eax,%eax # success? 6525 je common_exceptionThrown # no, handle exception 6526/* Now, we need to sync up with fast path. We need eax to 6527 * hold the obj->clazz, and ecx to hold the resolved class 6528 */ 6529 movl %eax,%ecx # ecx<- resolved class 6530 movzbl rINST_HI,%eax # eax<- BA 6531 sarl $4,%eax # eax<- B 6532 GET_VREG(%eax,%eax) # eax<- vB (obj) 6533 movl offObject_clazz(%eax),%eax # eax<- obj->clazz 6534 jmp .LOP_INSTANCE_OF_resolved 6535 6536/* continuation for OP_NEW_INSTANCE */ 6537 6538.LOP_NEW_INSTANCE_initialized: # on entry, ecx<- class 6539 /* TODO: remove test for interface/abstract, now done in verifier */ 6540 testl $(ACC_INTERFACE|ACC_ABSTRACT),offClassObject_accessFlags(%ecx) 6541 movl $ALLOC_DONT_TRACK,OUT_ARG1(%esp) 6542 jne .LOP_NEW_INSTANCE_abstract 6543.LOP_NEW_INSTANCE_finish: # ecx=class 6544 movl %ecx,OUT_ARG0(%esp) 6545 call dvmAllocObject # eax<- new object 6546 UNSPILL(rPC) 6547 movl rINST_FULL,%ecx 6548 FETCH_INST_WORD(2) 6549 testl %eax,%eax # success? 6550 je common_exceptionThrown # no, bail out 6551 SET_VREG(%eax,%ecx) 6552 ADVANCE_PC(2) 6553 GOTO_NEXT 6554 6555 /* 6556 * Class initialization required. 6557 * 6558 * ecx holds class object 6559 */ 6560.LOP_NEW_INSTANCE_needinit: 6561 SPILL_TMP(%ecx) # save object 6562 movl %ecx,OUT_ARG0(%esp) 6563 call dvmInitClass # initialize class 6564 UNSPILL_TMP(%ecx) # restore object 6565 testl %eax,%eax # success? 6566 jne .LOP_NEW_INSTANCE_initialized # success, continue 6567 UNSPILL(rPC) # failed, restore PC 6568 jmp common_exceptionThrown # go deal with init exception 6569 6570 /* 6571 * Resolution required. This is the least-likely path. 6572 * 6573 */ 6574.LOP_NEW_INSTANCE_resolve: 6575 GET_GLUE(%ecx) 6576 movzwl 2(rPC),%eax 6577 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 6578 movl %eax,OUT_ARG1(%esp) 6579 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6580 movl $0,OUT_ARG2(%esp) 6581 movl %ecx,OUT_ARG0(%esp) 6582 call dvmResolveClass # call(clazz,off,flags) 6583 movl %eax,%ecx # ecx<- resolved ClassObject ptr 6584 testl %ecx,%ecx # success? 6585 jne .LOP_NEW_INSTANCE_resolved # good to go 6586 UNSPILL(rPC) 6587 jmp common_exceptionThrown # no, handle exception 6588 6589 /* 6590 * TODO: remove this 6591 * We can't instantiate an abstract class or interface, so throw an 6592 * InstantiationError with the class descriptor as the message. 6593 * 6594 * ecx holds class object 6595 */ 6596.LOP_NEW_INSTANCE_abstract: 6597 movl offClassObject_descriptor(%ecx),%eax 6598 movl $.LstrInstantiationError,OUT_ARG0(%esp) 6599 movl %eax,OUT_ARG1(%esp) 6600 call dvmThrowExceptionWithClassMessage 6601 UNSPILL(rPC) 6602 jmp common_exceptionThrown 6603 6604/* continuation for OP_NEW_ARRAY */ 6605 6606 /* 6607 * Resolve class. (This is an uncommon case.) 6608 * ecx holds class (null here) 6609 * eax holds array length (vB) 6610 */ 6611.LOP_NEW_ARRAY_resolve: 6612 GET_GLUE(%ecx) 6613 SPILL_TMP(%eax) # save array length 6614 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 6615 movzwl 2(rPC),%eax # eax<- CCCC 6616 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6617 movl %eax,OUT_ARG1(%esp) 6618 movl $0,OUT_ARG2(%esp) 6619 movl %ecx,OUT_ARG0(%esp) 6620 SPILL(rPC) 6621 call dvmResolveClass # eax<- call(clazz,ref,flag) 6622 UNSPILL(rPC) 6623 movl %eax,%ecx 6624 UNSPILL_TMP(%eax) 6625 testl %ecx,%ecx # successful resolution? 6626 je common_exceptionThrown # no, bail. 6627# fall through to OP_NEW_ARRAY_finish 6628 6629 /* 6630 * Finish allocation 6631 * 6632 * ecx holds class 6633 * eax holds array length (vB) 6634 */ 6635.LOP_NEW_ARRAY_finish: 6636 movl %ecx,OUT_ARG0(%esp) 6637 movl %eax,OUT_ARG1(%esp) 6638 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) 6639 SPILL(rPC) 6640 call dvmAllocArrayByClass # eax<- call(clazz,length,flags) 6641 UNSPILL(rPC) 6642 testl %eax,%eax # failed? 6643 je common_exceptionThrown # yup - go handle 6644 movl rINST_FULL,%ecx 6645 FETCH_INST_WORD(2) 6646 SET_VREG(%eax,%ecx) 6647 ADVANCE_PC(2) 6648 GOTO_NEXT 6649 6650/* continuation for OP_FILLED_NEW_ARRAY */ 6651 6652.LOP_FILLED_NEW_ARRAY_more: 6653 movl offMethod_clazz(%eax),%eax # eax<- method->clazz 6654 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 6655 call dvmResolveClass # eax<- call(clazz,ref,flag) 6656 UNSPILL(rPC) 6657 testl %eax,%eax # null? 6658 je common_exceptionThrown # yes, handle it 6659 6660 # note: fall through to .LOP_FILLED_NEW_ARRAY_continue 6661 6662 /* 6663 * On entry: 6664 * eax holds array class [r0] 6665 * rINST_FULL holds AA or BB [r10] 6666 * ecx is scratch 6667 * rPC is valid, but has been spilled 6668 */ 6669.LOP_FILLED_NEW_ARRAY_continue: 6670 movl offClassObject_descriptor(%eax),%ecx # ecx<- arrayClass->descriptor 6671 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags 6672 movzbl 1(%ecx),%ecx # ecx<- descriptor[1] 6673 movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass 6674 GET_GLUE(%eax) 6675 cmpb $'I',%cl # supported? 6676 je 1f 6677 cmpb $'L',%cl 6678 je 1f 6679 cmpb $'[',%cl 6680 jne .LOP_FILLED_NEW_ARRAY_notimpl # no, not handled yet 66811: 6682 movl %ecx,offGlue_retval+4(%eax) # save type 6683 .if (!0) 6684 SPILL_TMP(rINST_FULL) # save copy, need "B" later 6685 sarl $4,rINST_FULL 6686 .endif 6687 movl rINST_FULL,OUT_ARG1(%esp) # arg1<- A or AA (length) 6688 call dvmAllocArrayByClass # eax<- call(arrayClass, length, flags) 6689 UNSPILL(rPC) 6690 GET_GLUE(%ecx) 6691 testl %eax,%eax # alloc successful? 6692 je common_exceptionThrown # no, handle exception 6693 movl %eax,offGlue_retval(%ecx) # retval.l<- new array 6694 movzwl 4(rPC),%ecx # ecx<- FEDC or CCCC 6695 leal offArrayObject_contents(%eax),%eax # eax<- newArray->contents 6696 6697/* at this point: 6698 * eax is pointer to tgt 6699 * rINST_FULL is length 6700 * ecx is FEDC or CCCC 6701 * TMP_SPILL is BA 6702 * rPC is valid, but spilled 6703 * We now need to copy values from registers into the array 6704 */ 6705 6706 .if 0 6707 # set up src pointer 6708 SPILL(rFP) # esi 6709 SPILL(rIBASE) # edi 6710 movl %eax,%edi # set up dst ptr 6711 leal (rFP,%ecx,4),%esi # set up src ptr 6712 movl rINST_FULL,%ecx # load count register 6713 FETCH_INST_WORD(3) 6714 rep 6715 movsd 6716 GET_GLUE(%ecx) 6717 UNSPILL(rIBASE) 6718 movl offGlue_retval+4(%ecx),%eax # eax<- type 6719 UNSPILL(rFP) 6720 .else 6721 testl rINST_FULL,rINST_FULL 6722 je 4f 6723 UNSPILL_TMP(rPC) 6724 andl $0x0f,rPC # rPC<- 0000000A 6725 sall $16,rPC # rPC<- 000A0000 6726 orl %ecx,rPC # rpc<- 000AFEDC 67273: 6728 movl $0xf,%ecx 6729 andl rPC,%ecx # ecx<- next reg to load 6730 GET_VREG(%ecx,%ecx) 6731 shrl $4,rPC 6732 leal 4(%eax),%eax 6733 movl %ecx,-4(%eax) 6734 sub $1,rINST_FULL 6735 jne 3b 67364: 6737 GET_GLUE(%ecx) 6738 UNSPILL(rPC) 6739 movl offGlue_retval+4(%ecx),%eax # eax<- type 6740 FETCH_INST_WORD(3) 6741 .endif 6742 6743 cmpb $'I',%al # Int array? 6744 je 5f # skip card mark if so 6745 movl offGlue_retval(%ecx),%eax # eax<- object head 6746 movl offGlue_cardTable(%ecx),%ecx # card table base 6747 shrl $GC_CARD_SHIFT,%eax # convert to card num 6748 movb %cl,(%ecx,%eax) # mark card 67495: 6750 ADVANCE_PC(3) 6751 GOTO_NEXT 6752 6753 6754 /* 6755 * Throw an exception indicating that we have not implemented this 6756 * mode of filled-new-array. 6757 */ 6758.LOP_FILLED_NEW_ARRAY_notimpl: 6759 movl $.LstrInternalError,%eax 6760 movl %eax,OUT_ARG0(%esp) 6761 movl $.LstrFilledNewArrayNotImpl,%eax 6762 movl %eax,OUT_ARG1(%esp) 6763 call dvmThrowException 6764 UNSPILL(rPC) 6765 jmp common_exceptionThrown 6766 6767/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 6768 6769.LOP_FILLED_NEW_ARRAY_RANGE_more: 6770 movl offMethod_clazz(%eax),%eax # eax<- method->clazz 6771 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 6772 call dvmResolveClass # eax<- call(clazz,ref,flag) 6773 UNSPILL(rPC) 6774 testl %eax,%eax # null? 6775 je common_exceptionThrown # yes, handle it 6776 6777 # note: fall through to .LOP_FILLED_NEW_ARRAY_RANGE_continue 6778 6779 /* 6780 * On entry: 6781 * eax holds array class [r0] 6782 * rINST_FULL holds AA or BB [r10] 6783 * ecx is scratch 6784 * rPC is valid, but has been spilled 6785 */ 6786.LOP_FILLED_NEW_ARRAY_RANGE_continue: 6787 movl offClassObject_descriptor(%eax),%ecx # ecx<- arrayClass->descriptor 6788 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags 6789 movzbl 1(%ecx),%ecx # ecx<- descriptor[1] 6790 movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass 6791 GET_GLUE(%eax) 6792 cmpb $'I',%cl # supported? 6793 je 1f 6794 cmpb $'L',%cl 6795 je 1f 6796 cmpb $'[',%cl 6797 jne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl # no, not handled yet 67981: 6799 movl %ecx,offGlue_retval+4(%eax) # save type 6800 .if (!1) 6801 SPILL_TMP(rINST_FULL) # save copy, need "B" later 6802 sarl $4,rINST_FULL 6803 .endif 6804 movl rINST_FULL,OUT_ARG1(%esp) # arg1<- A or AA (length) 6805 call dvmAllocArrayByClass # eax<- call(arrayClass, length, flags) 6806 UNSPILL(rPC) 6807 GET_GLUE(%ecx) 6808 testl %eax,%eax # alloc successful? 6809 je common_exceptionThrown # no, handle exception 6810 movl %eax,offGlue_retval(%ecx) # retval.l<- new array 6811 movzwl 4(rPC),%ecx # ecx<- FEDC or CCCC 6812 leal offArrayObject_contents(%eax),%eax # eax<- newArray->contents 6813 6814/* at this point: 6815 * eax is pointer to tgt 6816 * rINST_FULL is length 6817 * ecx is FEDC or CCCC 6818 * TMP_SPILL is BA 6819 * rPC is valid, but spilled 6820 * We now need to copy values from registers into the array 6821 */ 6822 6823 .if 1 6824 # set up src pointer 6825 SPILL(rFP) # esi 6826 SPILL(rIBASE) # edi 6827 movl %eax,%edi # set up dst ptr 6828 leal (rFP,%ecx,4),%esi # set up src ptr 6829 movl rINST_FULL,%ecx # load count register 6830 FETCH_INST_WORD(3) 6831 rep 6832 movsd 6833 GET_GLUE(%ecx) 6834 UNSPILL(rIBASE) 6835 movl offGlue_retval+4(%ecx),%eax # eax<- type 6836 UNSPILL(rFP) 6837 .else 6838 testl rINST_FULL,rINST_FULL 6839 je 4f 6840 UNSPILL_TMP(rPC) 6841 andl $0x0f,rPC # rPC<- 0000000A 6842 sall $16,rPC # rPC<- 000A0000 6843 orl %ecx,rPC # rpc<- 000AFEDC 68443: 6845 movl $0xf,%ecx 6846 andl rPC,%ecx # ecx<- next reg to load 6847 GET_VREG(%ecx,%ecx) 6848 shrl $4,rPC 6849 leal 4(%eax),%eax 6850 movl %ecx,-4(%eax) 6851 sub $1,rINST_FULL 6852 jne 3b 68534: 6854 GET_GLUE(%ecx) 6855 UNSPILL(rPC) 6856 movl offGlue_retval+4(%ecx),%eax # eax<- type 6857 FETCH_INST_WORD(3) 6858 .endif 6859 6860 cmpb $'I',%al # Int array? 6861 je 5f # skip card mark if so 6862 movl offGlue_retval(%ecx),%eax # eax<- object head 6863 movl offGlue_cardTable(%ecx),%ecx # card table base 6864 shrl $GC_CARD_SHIFT,%eax # convert to card num 6865 movb %cl,(%ecx,%eax) # mark card 68665: 6867 ADVANCE_PC(3) 6868 GOTO_NEXT 6869 6870 6871 /* 6872 * Throw an exception indicating that we have not implemented this 6873 * mode of filled-new-array. 6874 */ 6875.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 6876 movl $.LstrInternalError,%eax 6877 movl %eax,OUT_ARG0(%esp) 6878 movl $.LstrFilledNewArrayNotImpl,%eax 6879 movl %eax,OUT_ARG1(%esp) 6880 call dvmThrowException 6881 UNSPILL(rPC) 6882 jmp common_exceptionThrown 6883 6884/* continuation for OP_CMPL_FLOAT */ 6885 6886.LOP_CMPL_FLOAT_isNaN: 6887 movl $-1,%ecx 6888 jmp .LOP_CMPL_FLOAT_finish 6889 6890/* continuation for OP_CMPG_FLOAT */ 6891 6892.LOP_CMPG_FLOAT_isNaN: 6893 movl $1,%ecx 6894 jmp .LOP_CMPG_FLOAT_finish 6895 6896/* continuation for OP_CMPL_DOUBLE */ 6897 6898.LOP_CMPL_DOUBLE_isNaN: 6899 movl $-1,%ecx 6900 jmp .LOP_CMPL_DOUBLE_finish 6901 6902/* continuation for OP_CMPG_DOUBLE */ 6903 6904.LOP_CMPG_DOUBLE_isNaN: 6905 movl $1,%ecx 6906 jmp .LOP_CMPG_DOUBLE_finish 6907 6908/* continuation for OP_CMP_LONG */ 6909 6910.LOP_CMP_LONG_bigger: 6911 UNSPILL(rPC) 6912 movl $1,%ecx 6913 jmp .LOP_CMP_LONG_finish 6914.LOP_CMP_LONG_smaller: 6915 UNSPILL(rPC) 6916 movl $-1,%ecx 6917.LOP_CMP_LONG_finish: 6918 SET_VREG(%ecx,rINST_FULL) 6919 FETCH_INST_WORD(2) 6920 ADVANCE_PC(2) 6921 GOTO_NEXT 6922 6923/* continuation for OP_AGET_WIDE */ 6924 6925.LOP_AGET_WIDE_finish: 6926 leal offArrayObject_contents(%eax,%ecx,8),%eax 6927 movl (%eax),%ecx 6928 movl 4(%eax),%eax 6929 SET_VREG_WORD(%ecx,rINST_FULL,0) 6930 SET_VREG_WORD(%eax,rINST_FULL,1) 6931 FETCH_INST_WORD(2) 6932 ADVANCE_PC(2) 6933 GOTO_NEXT 6934 6935/* continuation for OP_APUT_WIDE */ 6936 6937.LOP_APUT_WIDE_finish: 6938 leal offArrayObject_contents(%eax,%ecx,8),%eax 6939 GET_VREG_WORD(%ecx,rINST_FULL,0) 6940 GET_VREG_WORD(rINST_FULL,rINST_FULL,1) 6941 movl rINST_FULL,4(%eax) 6942 FETCH_INST_WORD(2) 6943 movl %ecx,(%eax) 6944 ADVANCE_PC(2) 6945 GOTO_NEXT 6946 6947/* continuation for OP_APUT_OBJECT */ 6948 6949 /* On entry: 6950 * eax<- array object 6951 * ecx<- index 6952 * rINST_FULL<- vAA 6953 */ 6954.LOP_APUT_OBJECT_continue: 6955 leal offArrayObject_contents(%eax,%ecx,4),%ecx 6956 testl rINST_FULL,rINST_FULL # storing null reference? 6957 je .LOP_APUT_OBJECT_skip_check 6958 SPILL(rPC) 6959 SPILL_TMP(%ecx) 6960 movl offObject_clazz(%eax),%eax # eax<- arrayObj->clazz 6961 movl offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz 6962 movl %eax,OUT_ARG1(%esp) 6963 movl %ecx,OUT_ARG0(%esp) 6964 call dvmCanPutArrayElement # test object type vs. array type 6965 UNSPILL(rPC) 6966 UNSPILL_TMP(%ecx) 6967 testl %eax,%eax 6968 GET_GLUE(%eax) 6969 je common_errArrayStore 6970 movl offGlue_cardTable(%eax),%eax # get card table base 6971 movl rINST_FULL,(%ecx) 6972 FETCH_INST_WORD(2) 6973 shrl $GC_CARD_SHIFT,%ecx # convert addr to card number 6974 movb %al,(%eax,%ecx) # mark card 6975 ADVANCE_PC(2) 6976 GOTO_NEXT 6977 6978.LOP_APUT_OBJECT_skip_check: 6979 movl rINST_FULL,(%ecx) 6980 FETCH_INST_WORD(2) 6981 ADVANCE_PC(2) 6982 GOTO_NEXT 6983 6984/* continuation for OP_IGET */ 6985 6986 6987.LOP_IGET_resolve: 6988 EXPORT_PC() 6989 SPILL(rPC) 6990 movl offGlue_method(rIBASE),rPC # rPC<- current method 6991 UNSPILL(rIBASE) 6992 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 6993 SPILL_TMP(%ecx) # save object pointer across call 6994 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 6995 call dvmResolveInstField # ... to dvmResolveInstField 6996 UNSPILL_TMP(%ecx) 6997 UNSPILL(rPC) 6998 testl %eax,%eax # ... which returns InstrField ptr 6999 jne .LOP_IGET_finish 7000 jmp common_exceptionThrown 7001 7002.LOP_IGET_finish: 7003 /* 7004 * Currently: 7005 * eax holds resolved field 7006 * ecx holds object 7007 * rIBASE is scratch, but needs to be unspilled 7008 * rINST_FULL holds A 7009 */ 7010 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7011 UNSPILL(rIBASE) 7012 testl %ecx,%ecx # object null? 7013 je common_errNullObject # object was null 7014 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7015 movl rINST_FULL,%eax # eax<- A 7016 FETCH_INST_WORD(2) 7017 SET_VREG(%ecx,%eax) 7018 ADVANCE_PC(2) 7019 GOTO_NEXT 7020 7021/* continuation for OP_IGET_WIDE */ 7022 7023 7024.LOP_IGET_WIDE_resolve: 7025 EXPORT_PC() 7026 SPILL(rPC) 7027 movl offGlue_method(rIBASE),rPC # rPC<- current method 7028 UNSPILL(rIBASE) 7029 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7030 SPILL_TMP(%ecx) # save object pointer across call 7031 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7032 call dvmResolveInstField # ... to dvmResolveInstField 7033 UNSPILL_TMP(%ecx) 7034 UNSPILL(rPC) 7035 testl %eax,%eax # ... which returns InstrField ptr 7036 jne .LOP_IGET_WIDE_finish 7037 jmp common_exceptionThrown 7038 7039.LOP_IGET_WIDE_finish: 7040 /* 7041 * Currently: 7042 * eax holds resolved field 7043 * ecx holds object 7044 * rIBASE is scratch, but needs to be unspilled 7045 * rINST_FULL holds A 7046 */ 7047 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7048 UNSPILL(rIBASE) 7049 testl %ecx,%ecx # object null? 7050 je common_errNullObject # object was null 7051 leal (%ecx,%eax,1),%eax # eax<- address of field 7052 movl (%eax),%ecx # ecx<- lsw 7053 movl 4(%eax),%eax # eax<- msw 7054 SET_VREG_WORD(%ecx,rINST_FULL,0) 7055 SET_VREG_WORD(%eax,rINST_FULL,1) 7056 FETCH_INST_WORD(2) 7057 ADVANCE_PC(2) 7058 GOTO_NEXT 7059 7060/* continuation for OP_IGET_OBJECT */ 7061 7062 7063.LOP_IGET_OBJECT_resolve: 7064 EXPORT_PC() 7065 SPILL(rPC) 7066 movl offGlue_method(rIBASE),rPC # rPC<- current method 7067 UNSPILL(rIBASE) 7068 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7069 SPILL_TMP(%ecx) # save object pointer across call 7070 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7071 call dvmResolveInstField # ... to dvmResolveInstField 7072 UNSPILL_TMP(%ecx) 7073 UNSPILL(rPC) 7074 testl %eax,%eax # ... which returns InstrField ptr 7075 jne .LOP_IGET_OBJECT_finish 7076 jmp common_exceptionThrown 7077 7078.LOP_IGET_OBJECT_finish: 7079 /* 7080 * Currently: 7081 * eax holds resolved field 7082 * ecx holds object 7083 * rIBASE is scratch, but needs to be unspilled 7084 * rINST_FULL holds A 7085 */ 7086 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7087 UNSPILL(rIBASE) 7088 testl %ecx,%ecx # object null? 7089 je common_errNullObject # object was null 7090 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7091 movl rINST_FULL,%eax # eax<- A 7092 FETCH_INST_WORD(2) 7093 SET_VREG(%ecx,%eax) 7094 ADVANCE_PC(2) 7095 GOTO_NEXT 7096 7097/* continuation for OP_IGET_BOOLEAN */ 7098 7099 7100.LOP_IGET_BOOLEAN_resolve: 7101 EXPORT_PC() 7102 SPILL(rPC) 7103 movl offGlue_method(rIBASE),rPC # rPC<- current method 7104 UNSPILL(rIBASE) 7105 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7106 SPILL_TMP(%ecx) # save object pointer across call 7107 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7108 call dvmResolveInstField # ... to dvmResolveInstField 7109 UNSPILL_TMP(%ecx) 7110 UNSPILL(rPC) 7111 testl %eax,%eax # ... which returns InstrField ptr 7112 jne .LOP_IGET_BOOLEAN_finish 7113 jmp common_exceptionThrown 7114 7115.LOP_IGET_BOOLEAN_finish: 7116 /* 7117 * Currently: 7118 * eax holds resolved field 7119 * ecx holds object 7120 * rIBASE is scratch, but needs to be unspilled 7121 * rINST_FULL holds A 7122 */ 7123 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7124 UNSPILL(rIBASE) 7125 testl %ecx,%ecx # object null? 7126 je common_errNullObject # object was null 7127 movzbl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7128 movl rINST_FULL,%eax # eax<- A 7129 FETCH_INST_WORD(2) 7130 SET_VREG(%ecx,%eax) 7131 ADVANCE_PC(2) 7132 GOTO_NEXT 7133 7134/* continuation for OP_IGET_BYTE */ 7135 7136 7137.LOP_IGET_BYTE_resolve: 7138 EXPORT_PC() 7139 SPILL(rPC) 7140 movl offGlue_method(rIBASE),rPC # rPC<- current method 7141 UNSPILL(rIBASE) 7142 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7143 SPILL_TMP(%ecx) # save object pointer across call 7144 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7145 call dvmResolveInstField # ... to dvmResolveInstField 7146 UNSPILL_TMP(%ecx) 7147 UNSPILL(rPC) 7148 testl %eax,%eax # ... which returns InstrField ptr 7149 jne .LOP_IGET_BYTE_finish 7150 jmp common_exceptionThrown 7151 7152.LOP_IGET_BYTE_finish: 7153 /* 7154 * Currently: 7155 * eax holds resolved field 7156 * ecx holds object 7157 * rIBASE is scratch, but needs to be unspilled 7158 * rINST_FULL holds A 7159 */ 7160 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7161 UNSPILL(rIBASE) 7162 testl %ecx,%ecx # object null? 7163 je common_errNullObject # object was null 7164 movsbl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7165 movl rINST_FULL,%eax # eax<- A 7166 FETCH_INST_WORD(2) 7167 SET_VREG(%ecx,%eax) 7168 ADVANCE_PC(2) 7169 GOTO_NEXT 7170 7171/* continuation for OP_IGET_CHAR */ 7172 7173 7174.LOP_IGET_CHAR_resolve: 7175 EXPORT_PC() 7176 SPILL(rPC) 7177 movl offGlue_method(rIBASE),rPC # rPC<- current method 7178 UNSPILL(rIBASE) 7179 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7180 SPILL_TMP(%ecx) # save object pointer across call 7181 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7182 call dvmResolveInstField # ... to dvmResolveInstField 7183 UNSPILL_TMP(%ecx) 7184 UNSPILL(rPC) 7185 testl %eax,%eax # ... which returns InstrField ptr 7186 jne .LOP_IGET_CHAR_finish 7187 jmp common_exceptionThrown 7188 7189.LOP_IGET_CHAR_finish: 7190 /* 7191 * Currently: 7192 * eax holds resolved field 7193 * ecx holds object 7194 * rIBASE is scratch, but needs to be unspilled 7195 * rINST_FULL holds A 7196 */ 7197 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7198 UNSPILL(rIBASE) 7199 testl %ecx,%ecx # object null? 7200 je common_errNullObject # object was null 7201 movzwl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7202 movl rINST_FULL,%eax # eax<- A 7203 FETCH_INST_WORD(2) 7204 SET_VREG(%ecx,%eax) 7205 ADVANCE_PC(2) 7206 GOTO_NEXT 7207 7208/* continuation for OP_IGET_SHORT */ 7209 7210 7211.LOP_IGET_SHORT_resolve: 7212 EXPORT_PC() 7213 SPILL(rPC) 7214 movl offGlue_method(rIBASE),rPC # rPC<- current method 7215 UNSPILL(rIBASE) 7216 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7217 SPILL_TMP(%ecx) # save object pointer across call 7218 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7219 call dvmResolveInstField # ... to dvmResolveInstField 7220 UNSPILL_TMP(%ecx) 7221 UNSPILL(rPC) 7222 testl %eax,%eax # ... which returns InstrField ptr 7223 jne .LOP_IGET_SHORT_finish 7224 jmp common_exceptionThrown 7225 7226.LOP_IGET_SHORT_finish: 7227 /* 7228 * Currently: 7229 * eax holds resolved field 7230 * ecx holds object 7231 * rIBASE is scratch, but needs to be unspilled 7232 * rINST_FULL holds A 7233 */ 7234 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7235 UNSPILL(rIBASE) 7236 testl %ecx,%ecx # object null? 7237 je common_errNullObject # object was null 7238 movswl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7239 movl rINST_FULL,%eax # eax<- A 7240 FETCH_INST_WORD(2) 7241 SET_VREG(%ecx,%eax) 7242 ADVANCE_PC(2) 7243 GOTO_NEXT 7244 7245/* continuation for OP_IPUT */ 7246 7247 7248.LOP_IPUT_resolve: 7249 EXPORT_PC() 7250 SPILL(rPC) 7251 movl offGlue_method(rIBASE),rPC # rPC<- current method 7252 UNSPILL(rIBASE) 7253 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7254 SPILL_TMP(%ecx) # save object pointer across call 7255 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7256 call dvmResolveInstField # ... to dvmResolveInstField 7257 UNSPILL_TMP(%ecx) 7258 UNSPILL(rPC) 7259 testl %eax,%eax # ... which returns InstrField ptr 7260 jne .LOP_IPUT_finish 7261 jmp common_exceptionThrown 7262 7263.LOP_IPUT_finish: 7264 /* 7265 * Currently: 7266 * eax holds resolved field 7267 * ecx holds object 7268 * rIBASE is scratch, but needs to be unspilled 7269 * rINST_FULL holds A 7270 */ 7271 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 7272 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7273 UNSPILL(rIBASE) 7274 testl %ecx,%ecx # object null? 7275 je common_errNullObject # object was null 7276 movl rINST_FULL,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7277 FETCH_INST_WORD(2) 7278 ADVANCE_PC(2) 7279 GOTO_NEXT 7280 7281/* continuation for OP_IPUT_WIDE */ 7282 7283 7284.LOP_IPUT_WIDE_resolve: 7285 EXPORT_PC() 7286 SPILL(rPC) 7287 movl offGlue_method(rIBASE),rPC # rPC<- current method 7288 UNSPILL(rIBASE) 7289 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7290 SPILL_TMP(%ecx) # save object pointer across call 7291 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7292 call dvmResolveInstField # ... to dvmResolveInstField 7293 UNSPILL_TMP(%ecx) 7294 UNSPILL(rPC) 7295 testl %eax,%eax # ... which returns InstrField ptr 7296 jne .LOP_IPUT_WIDE_finish 7297 jmp common_exceptionThrown 7298 7299.LOP_IPUT_WIDE_finish: 7300 /* 7301 * Currently: 7302 * eax holds resolved field 7303 * ecx holds object 7304 * rIBASE is scratch, but needs to be unspilled 7305 * rINST_FULL holds A 7306 */ 7307 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7308 UNSPILL(rIBASE) 7309 testl %ecx,%ecx # object null? 7310 je common_errNullObject # object was null 7311 leal (%ecx,%eax,1),%eax # eax<- address of field 7312 GET_VREG_WORD(%ecx,rINST_FULL,0) # ecx<- lsw 7313 GET_VREG_WORD(rINST_FULL,rINST_FULL,1) # rINST_FULL<- msw 7314 movl rINST_FULL,4(%eax) 7315 FETCH_INST_WORD(2) 7316 movl %ecx,(%eax) 7317 ADVANCE_PC(2) 7318 GOTO_NEXT 7319 7320/* continuation for OP_IPUT_OBJECT */ 7321 7322 7323.LOP_IPUT_OBJECT_resolve: 7324 EXPORT_PC() 7325 SPILL(rPC) 7326 movl offGlue_method(rIBASE),rPC # rPC<- current method 7327 UNSPILL(rIBASE) 7328 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7329 SPILL_TMP(%ecx) # save object pointer across call 7330 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7331 call dvmResolveInstField # ... to dvmResolveInstField 7332 UNSPILL_TMP(%ecx) 7333 UNSPILL(rPC) 7334 testl %eax,%eax # ... which returns InstrField ptr 7335 jne .LOP_IPUT_OBJECT_finish 7336 jmp common_exceptionThrown 7337 7338.LOP_IPUT_OBJECT_finish: 7339 /* 7340 * Currently: 7341 * eax holds resolved field 7342 * ecx holds object 7343 * rIBASE is scratch, but needs to be unspilled 7344 * rINST_FULL holds A 7345 */ 7346 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 7347 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7348 UNSPILL(rIBASE) 7349 testl %ecx,%ecx # object null? 7350 je common_errNullObject # object was null 7351 movl rINST_FULL,(%ecx,%eax) # obj.field <- v[A](8/16/32 bits) 7352 GET_GLUE(%eax) 7353 testl rINST_FULL,rINST_FULL # stored a NULL? 7354 movl offGlue_cardTable(%eax),%eax # get card table base 7355 FETCH_INST_WORD(2) 7356 je 1f # skip card mark if null store 7357 shrl $GC_CARD_SHIFT,%ecx # object head to card number 7358 movb %al,(%eax,%ecx) # mark card 73591: 7360 ADVANCE_PC(2) 7361 GOTO_NEXT 7362 7363/* continuation for OP_IPUT_BOOLEAN */ 7364 7365 7366.LOP_IPUT_BOOLEAN_resolve: 7367 EXPORT_PC() 7368 SPILL(rPC) 7369 movl offGlue_method(rIBASE),rPC # rPC<- current method 7370 UNSPILL(rIBASE) 7371 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7372 SPILL_TMP(%ecx) # save object pointer across call 7373 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7374 call dvmResolveInstField # ... to dvmResolveInstField 7375 UNSPILL_TMP(%ecx) 7376 UNSPILL(rPC) 7377 testl %eax,%eax # ... which returns InstrField ptr 7378 jne .LOP_IPUT_BOOLEAN_finish 7379 jmp common_exceptionThrown 7380 7381.LOP_IPUT_BOOLEAN_finish: 7382 /* 7383 * Currently: 7384 * eax holds resolved field 7385 * ecx holds object 7386 * rIBASE is scratch, but needs to be unspilled 7387 * rINST_FULL holds A 7388 */ 7389 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 7390 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7391 UNSPILL(rIBASE) 7392 testl %ecx,%ecx # object null? 7393 je common_errNullObject # object was null 7394 movb rINST_LO,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7395 FETCH_INST_WORD(2) 7396 ADVANCE_PC(2) 7397 GOTO_NEXT 7398 7399/* continuation for OP_IPUT_BYTE */ 7400 7401 7402.LOP_IPUT_BYTE_resolve: 7403 EXPORT_PC() 7404 SPILL(rPC) 7405 movl offGlue_method(rIBASE),rPC # rPC<- current method 7406 UNSPILL(rIBASE) 7407 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7408 SPILL_TMP(%ecx) # save object pointer across call 7409 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7410 call dvmResolveInstField # ... to dvmResolveInstField 7411 UNSPILL_TMP(%ecx) 7412 UNSPILL(rPC) 7413 testl %eax,%eax # ... which returns InstrField ptr 7414 jne .LOP_IPUT_BYTE_finish 7415 jmp common_exceptionThrown 7416 7417.LOP_IPUT_BYTE_finish: 7418 /* 7419 * Currently: 7420 * eax holds resolved field 7421 * ecx holds object 7422 * rIBASE is scratch, but needs to be unspilled 7423 * rINST_FULL holds A 7424 */ 7425 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 7426 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7427 UNSPILL(rIBASE) 7428 testl %ecx,%ecx # object null? 7429 je common_errNullObject # object was null 7430 movb rINST_LO,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7431 FETCH_INST_WORD(2) 7432 ADVANCE_PC(2) 7433 GOTO_NEXT 7434 7435/* continuation for OP_IPUT_CHAR */ 7436 7437 7438.LOP_IPUT_CHAR_resolve: 7439 EXPORT_PC() 7440 SPILL(rPC) 7441 movl offGlue_method(rIBASE),rPC # rPC<- current method 7442 UNSPILL(rIBASE) 7443 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7444 SPILL_TMP(%ecx) # save object pointer across call 7445 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7446 call dvmResolveInstField # ... to dvmResolveInstField 7447 UNSPILL_TMP(%ecx) 7448 UNSPILL(rPC) 7449 testl %eax,%eax # ... which returns InstrField ptr 7450 jne .LOP_IPUT_CHAR_finish 7451 jmp common_exceptionThrown 7452 7453.LOP_IPUT_CHAR_finish: 7454 /* 7455 * Currently: 7456 * eax holds resolved field 7457 * ecx holds object 7458 * rIBASE is scratch, but needs to be unspilled 7459 * rINST_FULL holds A 7460 */ 7461 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 7462 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7463 UNSPILL(rIBASE) 7464 testl %ecx,%ecx # object null? 7465 je common_errNullObject # object was null 7466 movw rINST,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7467 FETCH_INST_WORD(2) 7468 ADVANCE_PC(2) 7469 GOTO_NEXT 7470 7471/* continuation for OP_IPUT_SHORT */ 7472 7473 7474.LOP_IPUT_SHORT_resolve: 7475 EXPORT_PC() 7476 SPILL(rPC) 7477 movl offGlue_method(rIBASE),rPC # rPC<- current method 7478 UNSPILL(rIBASE) 7479 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7480 SPILL_TMP(%ecx) # save object pointer across call 7481 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7482 call dvmResolveInstField # ... to dvmResolveInstField 7483 UNSPILL_TMP(%ecx) 7484 UNSPILL(rPC) 7485 testl %eax,%eax # ... which returns InstrField ptr 7486 jne .LOP_IPUT_SHORT_finish 7487 jmp common_exceptionThrown 7488 7489.LOP_IPUT_SHORT_finish: 7490 /* 7491 * Currently: 7492 * eax holds resolved field 7493 * ecx holds object 7494 * rIBASE is scratch, but needs to be unspilled 7495 * rINST_FULL holds A 7496 */ 7497 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 7498 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7499 UNSPILL(rIBASE) 7500 testl %ecx,%ecx # object null? 7501 je common_errNullObject # object was null 7502 movw rINST,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7503 FETCH_INST_WORD(2) 7504 ADVANCE_PC(2) 7505 GOTO_NEXT 7506 7507/* continuation for OP_SGET */ 7508 7509 /* 7510 * Go resolve the field 7511 */ 7512.LOP_SGET_resolve: 7513 GET_GLUE(%ecx) 7514 movzwl 2(rPC),%eax # eax<- field ref BBBB 7515 movl offGlue_method(%ecx),%ecx # ecx<- current method 7516 EXPORT_PC() # could throw, need to export 7517 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7518 SPILL(rPC) 7519 movl %eax,OUT_ARG1(%esp) 7520 movl %ecx,OUT_ARG0(%esp) 7521 call dvmResolveStaticField # eax<- resolved StaticField ptr 7522 UNSPILL(rPC) 7523 testl %eax,%eax 7524 jne .LOP_SGET_finish # success, continue 7525 jmp common_exceptionThrown # no, handle exception 7526 7527/* continuation for OP_SGET_WIDE */ 7528 7529 /* 7530 * Go resolve the field 7531 */ 7532.LOP_SGET_WIDE_resolve: 7533 GET_GLUE(%ecx) 7534 movzwl 2(rPC),%eax # eax<- field ref BBBB 7535 movl offGlue_method(%ecx),%ecx # ecx<- current method 7536 EXPORT_PC() # could throw, need to export 7537 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7538 SPILL(rPC) 7539 movl %eax,OUT_ARG1(%esp) 7540 movl %ecx,OUT_ARG0(%esp) 7541 call dvmResolveStaticField # eax<- resolved StaticField ptr 7542 UNSPILL(rPC) 7543 testl %eax,%eax 7544 jne .LOP_SGET_WIDE_finish # success, continue 7545 jmp common_exceptionThrown # no, handle exception 7546 7547/* continuation for OP_SGET_OBJECT */ 7548 7549 /* 7550 * Go resolve the field 7551 */ 7552.LOP_SGET_OBJECT_resolve: 7553 GET_GLUE(%ecx) 7554 movzwl 2(rPC),%eax # eax<- field ref BBBB 7555 movl offGlue_method(%ecx),%ecx # ecx<- current method 7556 EXPORT_PC() # could throw, need to export 7557 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7558 SPILL(rPC) 7559 movl %eax,OUT_ARG1(%esp) 7560 movl %ecx,OUT_ARG0(%esp) 7561 call dvmResolveStaticField # eax<- resolved StaticField ptr 7562 UNSPILL(rPC) 7563 testl %eax,%eax 7564 jne .LOP_SGET_OBJECT_finish # success, continue 7565 jmp common_exceptionThrown # no, handle exception 7566 7567/* continuation for OP_SGET_BOOLEAN */ 7568 7569 /* 7570 * Go resolve the field 7571 */ 7572.LOP_SGET_BOOLEAN_resolve: 7573 GET_GLUE(%ecx) 7574 movzwl 2(rPC),%eax # eax<- field ref BBBB 7575 movl offGlue_method(%ecx),%ecx # ecx<- current method 7576 EXPORT_PC() # could throw, need to export 7577 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7578 SPILL(rPC) 7579 movl %eax,OUT_ARG1(%esp) 7580 movl %ecx,OUT_ARG0(%esp) 7581 call dvmResolveStaticField # eax<- resolved StaticField ptr 7582 UNSPILL(rPC) 7583 testl %eax,%eax 7584 jne .LOP_SGET_BOOLEAN_finish # success, continue 7585 jmp common_exceptionThrown # no, handle exception 7586 7587/* continuation for OP_SGET_BYTE */ 7588 7589 /* 7590 * Go resolve the field 7591 */ 7592.LOP_SGET_BYTE_resolve: 7593 GET_GLUE(%ecx) 7594 movzwl 2(rPC),%eax # eax<- field ref BBBB 7595 movl offGlue_method(%ecx),%ecx # ecx<- current method 7596 EXPORT_PC() # could throw, need to export 7597 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7598 SPILL(rPC) 7599 movl %eax,OUT_ARG1(%esp) 7600 movl %ecx,OUT_ARG0(%esp) 7601 call dvmResolveStaticField # eax<- resolved StaticField ptr 7602 UNSPILL(rPC) 7603 testl %eax,%eax 7604 jne .LOP_SGET_BYTE_finish # success, continue 7605 jmp common_exceptionThrown # no, handle exception 7606 7607/* continuation for OP_SGET_CHAR */ 7608 7609 /* 7610 * Go resolve the field 7611 */ 7612.LOP_SGET_CHAR_resolve: 7613 GET_GLUE(%ecx) 7614 movzwl 2(rPC),%eax # eax<- field ref BBBB 7615 movl offGlue_method(%ecx),%ecx # ecx<- current method 7616 EXPORT_PC() # could throw, need to export 7617 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7618 SPILL(rPC) 7619 movl %eax,OUT_ARG1(%esp) 7620 movl %ecx,OUT_ARG0(%esp) 7621 call dvmResolveStaticField # eax<- resolved StaticField ptr 7622 UNSPILL(rPC) 7623 testl %eax,%eax 7624 jne .LOP_SGET_CHAR_finish # success, continue 7625 jmp common_exceptionThrown # no, handle exception 7626 7627/* continuation for OP_SGET_SHORT */ 7628 7629 /* 7630 * Go resolve the field 7631 */ 7632.LOP_SGET_SHORT_resolve: 7633 GET_GLUE(%ecx) 7634 movzwl 2(rPC),%eax # eax<- field ref BBBB 7635 movl offGlue_method(%ecx),%ecx # ecx<- current method 7636 EXPORT_PC() # could throw, need to export 7637 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7638 SPILL(rPC) 7639 movl %eax,OUT_ARG1(%esp) 7640 movl %ecx,OUT_ARG0(%esp) 7641 call dvmResolveStaticField # eax<- resolved StaticField ptr 7642 UNSPILL(rPC) 7643 testl %eax,%eax 7644 jne .LOP_SGET_SHORT_finish # success, continue 7645 jmp common_exceptionThrown # no, handle exception 7646 7647/* continuation for OP_SPUT */ 7648 7649 /* 7650 * Go resolve the field 7651 */ 7652.LOP_SPUT_resolve: 7653 GET_GLUE(%ecx) 7654 movzwl 2(rPC),%eax # eax<- field ref BBBB 7655 movl offGlue_method(%ecx),%ecx # ecx<- current method 7656 EXPORT_PC() # could throw, need to export 7657 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7658 SPILL(rPC) 7659 movl %eax,OUT_ARG1(%esp) 7660 movl %ecx,OUT_ARG0(%esp) 7661 call dvmResolveStaticField # eax<- resolved StaticField ptr 7662 UNSPILL(rPC) 7663 testl %eax,%eax 7664 jne .LOP_SPUT_finish # success, continue 7665 jmp common_exceptionThrown # no, handle exception 7666 7667/* continuation for OP_SPUT_WIDE */ 7668 7669 /* 7670 * Go resolve the field 7671 */ 7672.LOP_SPUT_WIDE_resolve: 7673 GET_GLUE(%ecx) 7674 movzwl 2(rPC),%eax # eax<- field ref BBBB 7675 movl offGlue_method(%ecx),%ecx # ecx<- current method 7676 EXPORT_PC() # could throw, need to export 7677 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7678 SPILL(rPC) 7679 movl %eax,OUT_ARG1(%esp) 7680 movl %ecx,OUT_ARG0(%esp) 7681 call dvmResolveStaticField # eax<- resolved StaticField ptr 7682 UNSPILL(rPC) 7683 testl %eax,%eax 7684 jne .LOP_SPUT_WIDE_finish # success, continue 7685 jmp common_exceptionThrown # no, handle exception 7686 7687/* continuation for OP_SPUT_OBJECT */ 7688 7689 7690.LOP_SPUT_OBJECT_continue: 7691 movl %ecx,offStaticField_value(%eax) 7692 testl %ecx,%ecx 7693 GET_GLUE(%ecx) 7694 FETCH_INST_WORD(2) 7695 je 1f 7696 movl offGlue_cardTable(%ecx),%ecx # get card table base 7697 shrl $GC_CARD_SHIFT,%eax # head to card number 7698 movb %cl,(%ecx,%eax) # mark card 76991: 7700 ADVANCE_PC(2) 7701 GOTO_NEXT 7702 7703.LOP_SPUT_OBJECT_resolve: 7704 GET_GLUE(%ecx) 7705 movzwl 2(rPC),%eax # eax<- field ref BBBB 7706 movl offGlue_method(%ecx),%ecx # ecx<- current method 7707 EXPORT_PC() # could throw, need to export 7708 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7709 SPILL(rPC) 7710 movl %eax,OUT_ARG1(%esp) 7711 movl %ecx,OUT_ARG0(%esp) 7712 call dvmResolveStaticField # eax<- resolved StaticField ptr 7713 UNSPILL(rPC) 7714 testl %eax,%eax 7715 jne .LOP_SPUT_OBJECT_finish # success, continue 7716 jmp common_exceptionThrown # no, handle exception 7717 7718/* continuation for OP_SPUT_BOOLEAN */ 7719 7720 /* 7721 * Go resolve the field 7722 */ 7723.LOP_SPUT_BOOLEAN_resolve: 7724 GET_GLUE(%ecx) 7725 movzwl 2(rPC),%eax # eax<- field ref BBBB 7726 movl offGlue_method(%ecx),%ecx # ecx<- current method 7727 EXPORT_PC() # could throw, need to export 7728 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7729 SPILL(rPC) 7730 movl %eax,OUT_ARG1(%esp) 7731 movl %ecx,OUT_ARG0(%esp) 7732 call dvmResolveStaticField # eax<- resolved StaticField ptr 7733 UNSPILL(rPC) 7734 testl %eax,%eax 7735 jne .LOP_SPUT_BOOLEAN_finish # success, continue 7736 jmp common_exceptionThrown # no, handle exception 7737 7738/* continuation for OP_SPUT_BYTE */ 7739 7740 /* 7741 * Go resolve the field 7742 */ 7743.LOP_SPUT_BYTE_resolve: 7744 GET_GLUE(%ecx) 7745 movzwl 2(rPC),%eax # eax<- field ref BBBB 7746 movl offGlue_method(%ecx),%ecx # ecx<- current method 7747 EXPORT_PC() # could throw, need to export 7748 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7749 SPILL(rPC) 7750 movl %eax,OUT_ARG1(%esp) 7751 movl %ecx,OUT_ARG0(%esp) 7752 call dvmResolveStaticField # eax<- resolved StaticField ptr 7753 UNSPILL(rPC) 7754 testl %eax,%eax 7755 jne .LOP_SPUT_BYTE_finish # success, continue 7756 jmp common_exceptionThrown # no, handle exception 7757 7758/* continuation for OP_SPUT_CHAR */ 7759 7760 /* 7761 * Go resolve the field 7762 */ 7763.LOP_SPUT_CHAR_resolve: 7764 GET_GLUE(%ecx) 7765 movzwl 2(rPC),%eax # eax<- field ref BBBB 7766 movl offGlue_method(%ecx),%ecx # ecx<- current method 7767 EXPORT_PC() # could throw, need to export 7768 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7769 SPILL(rPC) 7770 movl %eax,OUT_ARG1(%esp) 7771 movl %ecx,OUT_ARG0(%esp) 7772 call dvmResolveStaticField # eax<- resolved StaticField ptr 7773 UNSPILL(rPC) 7774 testl %eax,%eax 7775 jne .LOP_SPUT_CHAR_finish # success, continue 7776 jmp common_exceptionThrown # no, handle exception 7777 7778/* continuation for OP_SPUT_SHORT */ 7779 7780 /* 7781 * Go resolve the field 7782 */ 7783.LOP_SPUT_SHORT_resolve: 7784 GET_GLUE(%ecx) 7785 movzwl 2(rPC),%eax # eax<- field ref BBBB 7786 movl offGlue_method(%ecx),%ecx # ecx<- current method 7787 EXPORT_PC() # could throw, need to export 7788 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7789 SPILL(rPC) 7790 movl %eax,OUT_ARG1(%esp) 7791 movl %ecx,OUT_ARG0(%esp) 7792 call dvmResolveStaticField # eax<- resolved StaticField ptr 7793 UNSPILL(rPC) 7794 testl %eax,%eax 7795 jne .LOP_SPUT_SHORT_finish # success, continue 7796 jmp common_exceptionThrown # no, handle exception 7797 7798/* continuation for OP_INVOKE_VIRTUAL */ 7799 7800 7801.LOP_INVOKE_VIRTUAL_more: 7802 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz 7803 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 7804 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags 7805 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7806 UNSPILL(rPC) 7807 testl %eax,%eax # got null? 7808 jne .LOP_INVOKE_VIRTUAL_continue # no, continue 7809 jmp common_exceptionThrown # yes, handle exception 7810 7811 /* At this point: 7812 * eax = resolved base method 7813 * ecx = scratch 7814 */ 7815.LOP_INVOKE_VIRTUAL_continue: 7816 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC 7817 .if (!0) 7818 andl $0xf,%ecx # ecx<- D (or stays CCCC) 7819 .endif 7820 GET_VREG(%ecx,%ecx) # ecx<- "this" 7821 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex 7822 testl %ecx,%ecx # null this? 7823 je common_errNullObject # go if so 7824 movl offObject_clazz(%ecx),%ecx # ecx<- thisPtr->clazz 7825 movl offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable 7826 movl (%ecx,%eax,4),%eax # eax<- vtable[methodIndex] 7827 jmp common_invokeMethodNoRange 7828 7829/* continuation for OP_INVOKE_SUPER */ 7830 7831 /* 7832 * At this point: 7833 * ecx = resolved base method [r0] 7834 * eax = method->clazz [r9] 7835 */ 7836.LOP_INVOKE_SUPER_continue: 7837 movl offClassObject_super(%eax),%eax # eax<- method->clazz->super 7838 movzwl offMethod_methodIndex(%ecx),%ecx # ecx<- baseMthod->methodIndex 7839 cmpl offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount) 7840 jae .LOP_INVOKE_SUPER_nsm # method not present in superclass 7841 movl offClassObject_vtable(%eax),%eax # eax<- ...clazz->super->vtable 7842 movl (%eax,%ecx,4),%eax # eax<- vtable[methodIndex] 7843 jmp common_invokeMethodNoRange 7844 7845 7846 /* At this point: 7847 * ecx = null (needs to be resolved base method) 7848 * eax = method->clazz 7849 */ 7850.LOP_INVOKE_SUPER_resolve: 7851 SPILL_TMP(%eax) # method->clazz 7852 movl %eax,OUT_ARG0(%esp) # arg0<- method->clazz 7853 movzwl 2(rPC),%ecx # ecx<- BBBB 7854 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- resolver method type 7855 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 7856 SPILL(rPC) 7857 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7858 UNSPILL(rPC) 7859 testl %eax,%eax # got null? 7860 movl %eax,%ecx # ecx<- resolved base method 7861 UNSPILL_TMP(%eax) # restore method->clazz 7862 jne .LOP_INVOKE_SUPER_continue # good to go - continue 7863 jmp common_exceptionThrown # handle exception 7864 7865 /* 7866 * Throw a NoSuchMethodError with the method name as the message. 7867 * ecx = resolved base method 7868 */ 7869.LOP_INVOKE_SUPER_nsm: 7870 movl offMethod_name(%ecx),%eax 7871 mov %eax,OUT_ARG1(%esp) 7872 jmp common_errNoSuchMethod 7873 7874/* continuation for OP_INVOKE_DIRECT */ 7875 7876 /* 7877 * On entry: 7878 * TMP_SPILL <- "this" register 7879 * Things a bit ugly on this path, but it's the less 7880 * frequent one. We'll have to do some reloading. 7881 */ 7882.LOP_INVOKE_DIRECT_resolve: 7883 SPILL_TMP(%ecx) 7884 GET_GLUE(%ecx) 7885 UNSPILL(rPC) 7886 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 7887 movzwl 2(rPC),%eax # reference (BBBB or CCCC) 7888 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7889 movl $METHOD_DIRECT,OUT_ARG2(%esp) 7890 movl %eax,OUT_ARG1(%esp) 7891 movl %ecx,OUT_ARG0(%esp) 7892 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7893 UNSPILL_TMP(%ecx) 7894 testl %eax,%eax 7895 jne .LOP_INVOKE_DIRECT_finish 7896 UNSPILL(rPC) 7897 jmp common_exceptionThrown 7898 7899/* continuation for OP_INVOKE_STATIC */ 7900 7901.LOP_INVOKE_STATIC_continue: 7902 movl $METHOD_STATIC,%eax 7903 movl %eax,OUT_ARG2(%esp) # arg2<- flags 7904 SPILL(rPC) 7905 call dvmResolveMethod # call(clazz,ref,flags) 7906 UNSPILL(rPC) 7907 testl %eax,%eax # got null? 7908 jne common_invokeMethodNoRange 7909 jmp common_exceptionThrown 7910 7911/* continuation for OP_INVOKE_INTERFACE */ 7912 7913.LOP_INVOKE_INTERFACE_continue: 7914 call dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex) 7915 UNSPILL(rPC) 7916 testl %eax,%eax 7917 je common_exceptionThrown 7918 jmp common_invokeMethodNoRange 7919 7920/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 7921 7922 7923.LOP_INVOKE_VIRTUAL_RANGE_more: 7924 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz 7925 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 7926 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags 7927 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7928 UNSPILL(rPC) 7929 testl %eax,%eax # got null? 7930 jne .LOP_INVOKE_VIRTUAL_RANGE_continue # no, continue 7931 jmp common_exceptionThrown # yes, handle exception 7932 7933 /* At this point: 7934 * eax = resolved base method 7935 * ecx = scratch 7936 */ 7937.LOP_INVOKE_VIRTUAL_RANGE_continue: 7938 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC 7939 .if (!1) 7940 andl $0xf,%ecx # ecx<- D (or stays CCCC) 7941 .endif 7942 GET_VREG(%ecx,%ecx) # ecx<- "this" 7943 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex 7944 testl %ecx,%ecx # null this? 7945 je common_errNullObject # go if so 7946 movl offObject_clazz(%ecx),%ecx # ecx<- thisPtr->clazz 7947 movl offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable 7948 movl (%ecx,%eax,4),%eax # eax<- vtable[methodIndex] 7949 jmp common_invokeMethodRange 7950 7951/* continuation for OP_INVOKE_SUPER_RANGE */ 7952 7953 /* 7954 * At this point: 7955 * ecx = resolved base method [r0] 7956 * eax = method->clazz [r9] 7957 */ 7958.LOP_INVOKE_SUPER_RANGE_continue: 7959 movl offClassObject_super(%eax),%eax # eax<- method->clazz->super 7960 movzwl offMethod_methodIndex(%ecx),%ecx # ecx<- baseMthod->methodIndex 7961 cmpl offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount) 7962 jae .LOP_INVOKE_SUPER_RANGE_nsm # method not present in superclass 7963 movl offClassObject_vtable(%eax),%eax # eax<- ...clazz->super->vtable 7964 movl (%eax,%ecx,4),%eax # eax<- vtable[methodIndex] 7965 jmp common_invokeMethodRange 7966 7967 7968 /* At this point: 7969 * ecx = null (needs to be resolved base method) 7970 * eax = method->clazz 7971 */ 7972.LOP_INVOKE_SUPER_RANGE_resolve: 7973 SPILL_TMP(%eax) # method->clazz 7974 movl %eax,OUT_ARG0(%esp) # arg0<- method->clazz 7975 movzwl 2(rPC),%ecx # ecx<- BBBB 7976 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- resolver method type 7977 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 7978 SPILL(rPC) 7979 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7980 UNSPILL(rPC) 7981 testl %eax,%eax # got null? 7982 movl %eax,%ecx # ecx<- resolved base method 7983 UNSPILL_TMP(%eax) # restore method->clazz 7984 jne .LOP_INVOKE_SUPER_RANGE_continue # good to go - continue 7985 jmp common_exceptionThrown # handle exception 7986 7987 /* 7988 * Throw a NoSuchMethodError with the method name as the message. 7989 * ecx = resolved base method 7990 */ 7991.LOP_INVOKE_SUPER_RANGE_nsm: 7992 movl offMethod_name(%ecx),%eax 7993 mov %eax,OUT_ARG1(%esp) 7994 jmp common_errNoSuchMethod 7995 7996/* continuation for OP_INVOKE_DIRECT_RANGE */ 7997 7998 /* 7999 * On entry: 8000 * TMP_SPILL <- "this" register 8001 * Things a bit ugly on this path, but it's the less 8002 * frequent one. We'll have to do some reloading. 8003 */ 8004.LOP_INVOKE_DIRECT_RANGE_resolve: 8005 SPILL_TMP(%ecx) 8006 GET_GLUE(%ecx) 8007 UNSPILL(rPC) 8008 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 8009 movzwl 2(rPC),%eax # reference (BBBB or CCCC) 8010 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8011 movl $METHOD_DIRECT,OUT_ARG2(%esp) 8012 movl %eax,OUT_ARG1(%esp) 8013 movl %ecx,OUT_ARG0(%esp) 8014 call dvmResolveMethod # eax<- call(clazz, ref, flags) 8015 UNSPILL_TMP(%ecx) 8016 testl %eax,%eax 8017 jne .LOP_INVOKE_DIRECT_RANGE_finish 8018 UNSPILL(rPC) 8019 jmp common_exceptionThrown 8020 8021/* continuation for OP_INVOKE_STATIC_RANGE */ 8022 8023.LOP_INVOKE_STATIC_RANGE_continue: 8024 movl $METHOD_STATIC,%eax 8025 movl %eax,OUT_ARG2(%esp) # arg2<- flags 8026 SPILL(rPC) 8027 call dvmResolveMethod # call(clazz,ref,flags) 8028 UNSPILL(rPC) 8029 testl %eax,%eax # got null? 8030 jne common_invokeMethodRange 8031 jmp common_exceptionThrown 8032 8033/* continuation for OP_INVOKE_INTERFACE_RANGE */ 8034 8035.LOP_INVOKE_INTERFACE_RANGE_continue: 8036 call dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex) 8037 UNSPILL(rPC) 8038 testl %eax,%eax 8039 je common_exceptionThrown 8040 jmp common_invokeMethodRange 8041 8042/* continuation for OP_FLOAT_TO_INT */ 8043 8044 8045.LOP_FLOAT_TO_INT_continue: 8046 .if 0 8047 movl $0x80000000,%eax 8048 xorl 4(rFP,%ecx,4),%eax 8049 orl (rFP,%ecx,4),%eax 8050 .else 8051 cmpl $0x80000000,(rFP,%ecx,4) 8052 .endif 8053 je .LOP_FLOAT_TO_INT_special_case # fix up result 8054 8055.LOP_FLOAT_TO_INT_finish: 8056 ADVANCE_PC(1) 8057 GOTO_NEXT 8058 8059.LOP_FLOAT_TO_INT_special_case: 8060 fnstsw %ax 8061 sahf 8062 jp .LOP_FLOAT_TO_INT_isNaN 8063 adcl $-1,(rFP,%ecx,4) 8064 .if 0 8065 adcl $-1,4(rFP,%ecx,4) 8066 .endif 8067 jmp .LOP_FLOAT_TO_INT_finish 8068.LOP_FLOAT_TO_INT_isNaN: 8069 movl $0,(rFP,%ecx,4) 8070 .if 0 8071 movl $0,4(rFP,%ecx,4) 8072 .endif 8073 jmp .LOP_FLOAT_TO_INT_finish 8074 8075/* continuation for OP_FLOAT_TO_LONG */ 8076 8077 8078.LOP_FLOAT_TO_LONG_continue: 8079 .if 1 8080 movl $0x80000000,%eax 8081 xorl 4(rFP,%ecx,4),%eax 8082 orl (rFP,%ecx,4),%eax 8083 .else 8084 cmpl $0x80000000,(rFP,%ecx,4) 8085 .endif 8086 je .LOP_FLOAT_TO_LONG_special_case # fix up result 8087 8088.LOP_FLOAT_TO_LONG_finish: 8089 ADVANCE_PC(1) 8090 GOTO_NEXT 8091 8092.LOP_FLOAT_TO_LONG_special_case: 8093 fnstsw %ax 8094 sahf 8095 jp .LOP_FLOAT_TO_LONG_isNaN 8096 adcl $-1,(rFP,%ecx,4) 8097 .if 1 8098 adcl $-1,4(rFP,%ecx,4) 8099 .endif 8100 jmp .LOP_FLOAT_TO_LONG_finish 8101.LOP_FLOAT_TO_LONG_isNaN: 8102 movl $0,(rFP,%ecx,4) 8103 .if 1 8104 movl $0,4(rFP,%ecx,4) 8105 .endif 8106 jmp .LOP_FLOAT_TO_LONG_finish 8107 8108/* continuation for OP_DOUBLE_TO_INT */ 8109 8110 8111.LOP_DOUBLE_TO_INT_continue: 8112 .if 0 8113 movl $0x80000000,%eax 8114 xorl 4(rFP,%ecx,4),%eax 8115 orl (rFP,%ecx,4),%eax 8116 .else 8117 cmpl $0x80000000,(rFP,%ecx,4) 8118 .endif 8119 je .LOP_DOUBLE_TO_INT_special_case # fix up result 8120 8121.LOP_DOUBLE_TO_INT_finish: 8122 ADVANCE_PC(1) 8123 GOTO_NEXT 8124 8125.LOP_DOUBLE_TO_INT_special_case: 8126 fnstsw %ax 8127 sahf 8128 jp .LOP_DOUBLE_TO_INT_isNaN 8129 adcl $-1,(rFP,%ecx,4) 8130 .if 0 8131 adcl $-1,4(rFP,%ecx,4) 8132 .endif 8133 jmp .LOP_DOUBLE_TO_INT_finish 8134.LOP_DOUBLE_TO_INT_isNaN: 8135 movl $0,(rFP,%ecx,4) 8136 .if 0 8137 movl $0,4(rFP,%ecx,4) 8138 .endif 8139 jmp .LOP_DOUBLE_TO_INT_finish 8140 8141/* continuation for OP_DOUBLE_TO_LONG */ 8142 8143 8144.LOP_DOUBLE_TO_LONG_continue: 8145 .if 1 8146 movl $0x80000000,%eax 8147 xorl 4(rFP,%ecx,4),%eax 8148 orl (rFP,%ecx,4),%eax 8149 .else 8150 cmpl $0x80000000,(rFP,%ecx,4) 8151 .endif 8152 je .LOP_DOUBLE_TO_LONG_special_case # fix up result 8153 8154.LOP_DOUBLE_TO_LONG_finish: 8155 ADVANCE_PC(1) 8156 GOTO_NEXT 8157 8158.LOP_DOUBLE_TO_LONG_special_case: 8159 fnstsw %ax 8160 sahf 8161 jp .LOP_DOUBLE_TO_LONG_isNaN 8162 adcl $-1,(rFP,%ecx,4) 8163 .if 1 8164 adcl $-1,4(rFP,%ecx,4) 8165 .endif 8166 jmp .LOP_DOUBLE_TO_LONG_finish 8167.LOP_DOUBLE_TO_LONG_isNaN: 8168 movl $0,(rFP,%ecx,4) 8169 .if 1 8170 movl $0,4(rFP,%ecx,4) 8171 .endif 8172 jmp .LOP_DOUBLE_TO_LONG_finish 8173 8174/* continuation for OP_DIV_INT */ 8175.LOP_DIV_INT_continue_div: 8176 cltd 8177 idivl %ecx 8178.LOP_DIV_INT_finish_div: 8179 movzbl rINST_HI,%ecx # ecl<- AA 8180 SET_VREG(%eax,%ecx) 8181 UNSPILL(rPC) 8182 FETCH_INST_WORD(2) 8183 ADVANCE_PC(2) 8184 GOTO_NEXT 8185 8186/* continuation for OP_REM_INT */ 8187.LOP_REM_INT_continue_div: 8188 cltd 8189 idivl %ecx 8190.LOP_REM_INT_finish_div: 8191 movzbl rINST_HI,%ecx # ecl<- AA 8192 SET_VREG(%edx,%ecx) 8193 UNSPILL(rPC) 8194 FETCH_INST_WORD(2) 8195 ADVANCE_PC(2) 8196 GOTO_NEXT 8197 8198/* continuation for OP_MUL_LONG */ 8199 8200.LOP_MUL_LONG_continue: 8201 leal (%ecx,%edx),%edx # full result now in %edx:%eax 8202 movzbl rINST_HI,%ecx # ecx<- A 8203 movl %edx,4(rFP,%ecx,4) # v[B+1]<- %edx 8204 UNSPILL(rPC) # restore rPC/%edx 8205 FETCH_INST_WORD(2) 8206 UNSPILL(rIBASE) 8207 movl %eax,(rFP,%ecx,4) # v[B]<- %eax 8208 ADVANCE_PC(2) 8209 GOTO_NEXT 8210 8211/* continuation for OP_DIV_LONG */ 8212 8213.LOP_DIV_LONG_continue: 8214 call __divdi3 8215.LOP_DIV_LONG_finish: 8216 movzbl rINST_HI,%ecx 8217 SET_VREG_WORD(rPC,%ecx,1) 8218 UNSPILL(rPC) 8219 SET_VREG_WORD(%eax,%ecx,0) 8220 FETCH_INST_WORD(2) 8221 ADVANCE_PC(2) 8222 GOTO_NEXT 8223 8224.LOP_DIV_LONG_check_zero: 8225 testl rPC,rPC 8226 jne .LOP_DIV_LONG_notSpecial 8227 UNSPILL(rPC) 8228 jmp common_errDivideByZero 8229.LOP_DIV_LONG_check_neg1: 8230 testl rPC,%eax 8231 jne .LOP_DIV_LONG_notSpecial 8232 GET_VREG_WORD(rPC,%ecx,0) 8233 GET_VREG_WORD(%ecx,%ecx,1) 8234 testl rPC,rPC 8235 jne .LOP_DIV_LONG_notSpecial1 8236 cmpl $0x80000000,%ecx 8237 jne .LOP_DIV_LONG_notSpecial1 8238 /* minint / -1, return minint on div, 0 on rem */ 8239 xorl %eax,%eax 8240 movl $0x80000000,%edx 8241 jmp .LOP_DIV_LONG_finish 8242 8243/* continuation for OP_REM_LONG */ 8244 8245.LOP_REM_LONG_continue: 8246 call __moddi3 8247.LOP_REM_LONG_finish: 8248 movzbl rINST_HI,%ecx 8249 SET_VREG_WORD(rPC,%ecx,1) 8250 UNSPILL(rPC) 8251 SET_VREG_WORD(%eax,%ecx,0) 8252 FETCH_INST_WORD(2) 8253 ADVANCE_PC(2) 8254 GOTO_NEXT 8255 8256.LOP_REM_LONG_check_zero: 8257 testl rPC,rPC 8258 jne .LOP_REM_LONG_notSpecial 8259 UNSPILL(rPC) 8260 jmp common_errDivideByZero 8261.LOP_REM_LONG_check_neg1: 8262 testl rPC,%eax 8263 jne .LOP_REM_LONG_notSpecial 8264 GET_VREG_WORD(rPC,%ecx,0) 8265 GET_VREG_WORD(%ecx,%ecx,1) 8266 testl rPC,rPC 8267 jne .LOP_REM_LONG_notSpecial1 8268 cmpl $0x80000000,%ecx 8269 jne .LOP_REM_LONG_notSpecial1 8270 /* minint / -1, return minint on div, 0 on rem */ 8271 xorl %eax,%eax 8272 movl $0,%edx 8273 jmp .LOP_REM_LONG_finish 8274 8275/* continuation for OP_SHL_LONG */ 8276 8277.LOP_SHL_LONG_finish: 8278 SET_VREG_WORD(%eax,%ecx,0) # v[AA+0]<- %eax 8279 ADVANCE_PC(2) 8280 GOTO_NEXT 8281 8282/* continuation for OP_SHR_LONG */ 8283 8284 8285.LOP_SHR_LONG_finish: 8286 SET_VREG_WORD(%eax,%ecx,0) # v[AA+0]<- eax 8287 ADVANCE_PC(2) 8288 GOTO_NEXT 8289 8290/* continuation for OP_USHR_LONG */ 8291 8292 8293.LOP_USHR_LONG_finish: 8294 SET_VREG_WORD(%eax,%ecx,0) # v[BB+0]<- eax 8295 FETCH_INST_WORD(2) 8296 ADVANCE_PC(2) 8297 GOTO_NEXT 8298 8299/* continuation for OP_DIV_INT_2ADDR */ 8300.LOP_DIV_INT_2ADDR_continue_div2addr: 8301 cltd 8302 idivl %ecx 8303.LOP_DIV_INT_2ADDR_finish_div2addr: 8304 SET_VREG(%eax,rINST_FULL) 8305 UNSPILL(rPC) 8306 FETCH_INST_WORD(1) 8307 ADVANCE_PC(1) 8308 GOTO_NEXT 8309 8310/* continuation for OP_REM_INT_2ADDR */ 8311.LOP_REM_INT_2ADDR_continue_div2addr: 8312 cltd 8313 idivl %ecx 8314.LOP_REM_INT_2ADDR_finish_div2addr: 8315 SET_VREG(%edx,rINST_FULL) 8316 UNSPILL(rPC) 8317 FETCH_INST_WORD(1) 8318 ADVANCE_PC(1) 8319 GOTO_NEXT 8320 8321/* continuation for OP_MUL_LONG_2ADDR */ 8322 8323.LOP_MUL_LONG_2ADDR_continue: 8324 leal (%ecx,%edx),%edx # full result now in %edx:%eax 8325 movl %edx,4(rIBASE) # v[A+1]<- %edx 8326 UNSPILL(rPC) # restore rPC/%edx 8327 FETCH_INST_WORD(1) 8328 movl %eax,(rIBASE) # v[A]<- %eax 8329 UNSPILL(rFP) 8330 UNSPILL(rIBASE) 8331 ADVANCE_PC(1) 8332 GOTO_NEXT 8333 8334/* continuation for OP_DIV_LONG_2ADDR */ 8335 8336.LOP_DIV_LONG_2ADDR_continue: 8337 movl %eax,OUT_ARG3(%esp) 8338 movl rPC,OUT_ARG0(%esp) 8339 movl %ecx,OUT_ARG1(%esp) 8340 call __divdi3 8341.LOP_DIV_LONG_2ADDR_finish: 8342 movl rINST_FULL,%ecx 8343 SET_VREG_WORD(rPC,%ecx,1) 8344 UNSPILL(rPC) 8345 SET_VREG_WORD(%eax,%ecx,0) 8346 FETCH_INST_WORD(1) 8347 ADVANCE_PC(1) 8348 GOTO_NEXT 8349 8350.LOP_DIV_LONG_2ADDR_check_zero: 8351 testl rPC,rPC 8352 jne .LOP_DIV_LONG_2ADDR_notSpecial 8353 UNSPILL(rPC) 8354 jmp common_errDivideByZero 8355.LOP_DIV_LONG_2ADDR_check_neg1: 8356 testl rPC,%eax 8357 jne .LOP_DIV_LONG_2ADDR_notSpecial 8358 GET_VREG_WORD(rPC,rINST_FULL,0) 8359 GET_VREG_WORD(%ecx,rINST_FULL,1) 8360 testl rPC,rPC 8361 jne .LOP_DIV_LONG_2ADDR_notSpecial1 8362 cmpl $0x80000000,%ecx 8363 jne .LOP_DIV_LONG_2ADDR_notSpecial1 8364 /* minint / -1, return minint on div, 0 on rem */ 8365 xorl %eax,%eax 8366 movl $0x80000000,%edx 8367 jmp .LOP_DIV_LONG_2ADDR_finish 8368 8369/* continuation for OP_REM_LONG_2ADDR */ 8370 8371.LOP_REM_LONG_2ADDR_continue: 8372 movl %eax,OUT_ARG3(%esp) 8373 movl rPC,OUT_ARG0(%esp) 8374 movl %ecx,OUT_ARG1(%esp) 8375 call __moddi3 8376.LOP_REM_LONG_2ADDR_finish: 8377 movl rINST_FULL,%ecx 8378 SET_VREG_WORD(rPC,%ecx,1) 8379 UNSPILL(rPC) 8380 SET_VREG_WORD(%eax,%ecx,0) 8381 FETCH_INST_WORD(1) 8382 ADVANCE_PC(1) 8383 GOTO_NEXT 8384 8385.LOP_REM_LONG_2ADDR_check_zero: 8386 testl rPC,rPC 8387 jne .LOP_REM_LONG_2ADDR_notSpecial 8388 UNSPILL(rPC) 8389 jmp common_errDivideByZero 8390.LOP_REM_LONG_2ADDR_check_neg1: 8391 testl rPC,%eax 8392 jne .LOP_REM_LONG_2ADDR_notSpecial 8393 GET_VREG_WORD(rPC,rINST_FULL,0) 8394 GET_VREG_WORD(%ecx,rINST_FULL,1) 8395 testl rPC,rPC 8396 jne .LOP_REM_LONG_2ADDR_notSpecial1 8397 cmpl $0x80000000,%ecx 8398 jne .LOP_REM_LONG_2ADDR_notSpecial1 8399 /* minint / -1, return minint on div, 0 on rem */ 8400 xorl %eax,%eax 8401 movl $0,%edx 8402 jmp .LOP_REM_LONG_2ADDR_finish 8403 8404/* continuation for OP_SHL_LONG_2ADDR */ 8405 8406 8407.LOP_SHL_LONG_2ADDR_finish: 8408 SET_VREG_WORD(%eax,rINST_FULL,0) # v[AA+0]<- eax 8409 FETCH_INST_WORD(1) 8410 ADVANCE_PC(1) 8411 GOTO_NEXT 8412 8413/* continuation for OP_SHR_LONG_2ADDR */ 8414 8415 8416.LOP_SHR_LONG_2ADDR_finish: 8417 SET_VREG_WORD(%eax,rINST_FULL,0) # v[AA+0]<- eax 8418 FETCH_INST_WORD(1) 8419 ADVANCE_PC(1) 8420 GOTO_NEXT 8421 8422/* continuation for OP_USHR_LONG_2ADDR */ 8423 8424 8425.LOP_USHR_LONG_2ADDR_finish: 8426 SET_VREG_WORD(%eax,rINST_FULL,0) # v[AA+0]<- eax 8427 FETCH_INST_WORD(1) 8428 ADVANCE_PC(1) 8429 GOTO_NEXT 8430 8431/* continuation for OP_DIV_INT_LIT16 */ 8432.LOP_DIV_INT_LIT16_continue_div: 8433 cltd 8434 idivl %ecx 8435.LOP_DIV_INT_LIT16_finish_div: 8436 SET_VREG(%eax,rINST_FULL) 8437 UNSPILL(rPC) 8438 FETCH_INST_WORD(2) 8439 ADVANCE_PC(2) 8440 GOTO_NEXT 8441 8442/* continuation for OP_REM_INT_LIT16 */ 8443.LOP_REM_INT_LIT16_continue_div: 8444 cltd 8445 idivl %ecx 8446.LOP_REM_INT_LIT16_finish_div: 8447 SET_VREG(%edx,rINST_FULL) 8448 UNSPILL(rPC) 8449 FETCH_INST_WORD(2) 8450 ADVANCE_PC(2) 8451 GOTO_NEXT 8452 8453/* continuation for OP_DIV_INT_LIT8 */ 8454.LOP_DIV_INT_LIT8_continue_div: 8455 cltd 8456 idivl %ecx 8457.LOP_DIV_INT_LIT8_finish_div: 8458 SET_VREG(%eax,rINST_FULL) 8459 UNSPILL(rPC) 8460 FETCH_INST_WORD(2) 8461 ADVANCE_PC(2) 8462 GOTO_NEXT 8463 8464/* continuation for OP_REM_INT_LIT8 */ 8465.LOP_REM_INT_LIT8_continue_div: 8466 cltd 8467 idivl %ecx 8468.LOP_REM_INT_LIT8_finish_div: 8469 SET_VREG(%edx,rINST_FULL) 8470 UNSPILL(rPC) 8471 FETCH_INST_WORD(2) 8472 ADVANCE_PC(2) 8473 GOTO_NEXT 8474 8475/* continuation for OP_IGET_VOLATILE */ 8476 8477 8478.LOP_IGET_VOLATILE_resolve: 8479 EXPORT_PC() 8480 SPILL(rPC) 8481 movl offGlue_method(rIBASE),rPC # rPC<- current method 8482 UNSPILL(rIBASE) 8483 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 8484 SPILL_TMP(%ecx) # save object pointer across call 8485 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 8486 call dvmResolveInstField # ... to dvmResolveInstField 8487 UNSPILL_TMP(%ecx) 8488 UNSPILL(rPC) 8489 testl %eax,%eax # ... which returns InstrField ptr 8490 jne .LOP_IGET_VOLATILE_finish 8491 jmp common_exceptionThrown 8492 8493.LOP_IGET_VOLATILE_finish: 8494 /* 8495 * Currently: 8496 * eax holds resolved field 8497 * ecx holds object 8498 * rIBASE is scratch, but needs to be unspilled 8499 * rINST_FULL holds A 8500 */ 8501 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 8502 UNSPILL(rIBASE) 8503 testl %ecx,%ecx # object null? 8504 je common_errNullObject # object was null 8505 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 8506 movl rINST_FULL,%eax # eax<- A 8507 FETCH_INST_WORD(2) 8508 SET_VREG(%ecx,%eax) 8509 ADVANCE_PC(2) 8510 GOTO_NEXT 8511 8512/* continuation for OP_IPUT_VOLATILE */ 8513 8514 8515.LOP_IPUT_VOLATILE_resolve: 8516 EXPORT_PC() 8517 SPILL(rPC) 8518 movl offGlue_method(rIBASE),rPC # rPC<- current method 8519 UNSPILL(rIBASE) 8520 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 8521 SPILL_TMP(%ecx) # save object pointer across call 8522 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 8523 call dvmResolveInstField # ... to dvmResolveInstField 8524 UNSPILL_TMP(%ecx) 8525 UNSPILL(rPC) 8526 testl %eax,%eax # ... which returns InstrField ptr 8527 jne .LOP_IPUT_VOLATILE_finish 8528 jmp common_exceptionThrown 8529 8530.LOP_IPUT_VOLATILE_finish: 8531 /* 8532 * Currently: 8533 * eax holds resolved field 8534 * ecx holds object 8535 * rIBASE is scratch, but needs to be unspilled 8536 * rINST_FULL holds A 8537 */ 8538 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 8539 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 8540 UNSPILL(rIBASE) 8541 testl %ecx,%ecx # object null? 8542 je common_errNullObject # object was null 8543 movl rINST_FULL,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 8544 FETCH_INST_WORD(2) 8545 ADVANCE_PC(2) 8546 GOTO_NEXT 8547 8548/* continuation for OP_SGET_VOLATILE */ 8549 8550 /* 8551 * Go resolve the field 8552 */ 8553.LOP_SGET_VOLATILE_resolve: 8554 GET_GLUE(%ecx) 8555 movzwl 2(rPC),%eax # eax<- field ref BBBB 8556 movl offGlue_method(%ecx),%ecx # ecx<- current method 8557 EXPORT_PC() # could throw, need to export 8558 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8559 SPILL(rPC) 8560 movl %eax,OUT_ARG1(%esp) 8561 movl %ecx,OUT_ARG0(%esp) 8562 call dvmResolveStaticField # eax<- resolved StaticField ptr 8563 UNSPILL(rPC) 8564 testl %eax,%eax 8565 jne .LOP_SGET_VOLATILE_finish # success, continue 8566 jmp common_exceptionThrown # no, handle exception 8567 8568/* continuation for OP_SPUT_VOLATILE */ 8569 8570 /* 8571 * Go resolve the field 8572 */ 8573.LOP_SPUT_VOLATILE_resolve: 8574 GET_GLUE(%ecx) 8575 movzwl 2(rPC),%eax # eax<- field ref BBBB 8576 movl offGlue_method(%ecx),%ecx # ecx<- current method 8577 EXPORT_PC() # could throw, need to export 8578 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8579 SPILL(rPC) 8580 movl %eax,OUT_ARG1(%esp) 8581 movl %ecx,OUT_ARG0(%esp) 8582 call dvmResolveStaticField # eax<- resolved StaticField ptr 8583 UNSPILL(rPC) 8584 testl %eax,%eax 8585 jne .LOP_SPUT_VOLATILE_finish # success, continue 8586 jmp common_exceptionThrown # no, handle exception 8587 8588/* continuation for OP_IGET_OBJECT_VOLATILE */ 8589 8590 8591.LOP_IGET_OBJECT_VOLATILE_resolve: 8592 EXPORT_PC() 8593 SPILL(rPC) 8594 movl offGlue_method(rIBASE),rPC # rPC<- current method 8595 UNSPILL(rIBASE) 8596 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 8597 SPILL_TMP(%ecx) # save object pointer across call 8598 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 8599 call dvmResolveInstField # ... to dvmResolveInstField 8600 UNSPILL_TMP(%ecx) 8601 UNSPILL(rPC) 8602 testl %eax,%eax # ... which returns InstrField ptr 8603 jne .LOP_IGET_OBJECT_VOLATILE_finish 8604 jmp common_exceptionThrown 8605 8606.LOP_IGET_OBJECT_VOLATILE_finish: 8607 /* 8608 * Currently: 8609 * eax holds resolved field 8610 * ecx holds object 8611 * rIBASE is scratch, but needs to be unspilled 8612 * rINST_FULL holds A 8613 */ 8614 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 8615 UNSPILL(rIBASE) 8616 testl %ecx,%ecx # object null? 8617 je common_errNullObject # object was null 8618 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 8619 movl rINST_FULL,%eax # eax<- A 8620 FETCH_INST_WORD(2) 8621 SET_VREG(%ecx,%eax) 8622 ADVANCE_PC(2) 8623 GOTO_NEXT 8624 8625/* continuation for OP_EXECUTE_INLINE */ 8626 8627.LOP_EXECUTE_INLINE_continue: 8628 /* 8629 * Extract args, call function. 8630 * ecx = #of args (0-4) 8631 * eax = call index 8632 * @esp = return addr 8633 * esp is -4 from normal 8634 * 8635 * Go ahead and load all 4 args, even if not used. 8636 */ 8637 movzwl 4(rPC),rPC 8638 8639 movl $0xf,%ecx 8640 andl rPC,%ecx 8641 GET_VREG(%ecx,%ecx) 8642 sarl $4,rPC 8643 movl %ecx,4+OUT_ARG0(%esp) 8644 8645 movl $0xf,%ecx 8646 andl rPC,%ecx 8647 GET_VREG(%ecx,%ecx) 8648 sarl $4,rPC 8649 movl %ecx,4+OUT_ARG1(%esp) 8650 8651 movl $0xf,%ecx 8652 andl rPC,%ecx 8653 GET_VREG(%ecx,%ecx) 8654 sarl $4,rPC 8655 movl %ecx,4+OUT_ARG2(%esp) 8656 8657 movl $0xf,%ecx 8658 andl rPC,%ecx 8659 GET_VREG(%ecx,%ecx) 8660 sarl $4,rPC 8661 movl %ecx,4+OUT_ARG3(%esp) 8662 8663 sall $4,%eax # index *= sizeof(table entry) 8664 jmp *gDvmInlineOpsTable(%eax) 8665 # will return to caller of .LOP_EXECUTE_INLINE_continue 8666 8667/* continuation for OP_IPUT_OBJECT_QUICK */ 8668 8669.LOP_IPUT_OBJECT_QUICK_finish: 8670 testl rINST_FULL,rINST_FULL # did we store null? 8671 FETCH_INST_WORD(2) 8672 movl offGlue_cardTable(%eax),%eax # get card table base 8673 je 1f # skip card mark if null store 8674 shrl $GC_CARD_SHIFT,%ecx # object head to card number 8675 movb %al,(%eax,%ecx) # mark card 86761: 8677 ADVANCE_PC(2) 8678 GOTO_NEXT 8679 8680/* continuation for OP_IPUT_OBJECT_VOLATILE */ 8681 8682 8683.LOP_IPUT_OBJECT_VOLATILE_resolve: 8684 EXPORT_PC() 8685 SPILL(rPC) 8686 movl offGlue_method(rIBASE),rPC # rPC<- current method 8687 UNSPILL(rIBASE) 8688 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 8689 SPILL_TMP(%ecx) # save object pointer across call 8690 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 8691 call dvmResolveInstField # ... to dvmResolveInstField 8692 UNSPILL_TMP(%ecx) 8693 UNSPILL(rPC) 8694 testl %eax,%eax # ... which returns InstrField ptr 8695 jne .LOP_IPUT_OBJECT_VOLATILE_finish 8696 jmp common_exceptionThrown 8697 8698.LOP_IPUT_OBJECT_VOLATILE_finish: 8699 /* 8700 * Currently: 8701 * eax holds resolved field 8702 * ecx holds object 8703 * rIBASE is scratch, but needs to be unspilled 8704 * rINST_FULL holds A 8705 */ 8706 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 8707 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 8708 UNSPILL(rIBASE) 8709 testl %ecx,%ecx # object null? 8710 je common_errNullObject # object was null 8711 movl rINST_FULL,(%ecx,%eax) # obj.field <- v[A](8/16/32 bits) 8712 GET_GLUE(%eax) 8713 testl rINST_FULL,rINST_FULL # stored a NULL? 8714 movl offGlue_cardTable(%eax),%eax # get card table base 8715 FETCH_INST_WORD(2) 8716 je 1f # skip card mark if null store 8717 shrl $GC_CARD_SHIFT,%ecx # object head to card number 8718 movb %al,(%eax,%ecx) # mark card 87191: 8720 ADVANCE_PC(2) 8721 GOTO_NEXT 8722 8723/* continuation for OP_SGET_OBJECT_VOLATILE */ 8724 8725 /* 8726 * Go resolve the field 8727 */ 8728.LOP_SGET_OBJECT_VOLATILE_resolve: 8729 GET_GLUE(%ecx) 8730 movzwl 2(rPC),%eax # eax<- field ref BBBB 8731 movl offGlue_method(%ecx),%ecx # ecx<- current method 8732 EXPORT_PC() # could throw, need to export 8733 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8734 SPILL(rPC) 8735 movl %eax,OUT_ARG1(%esp) 8736 movl %ecx,OUT_ARG0(%esp) 8737 call dvmResolveStaticField # eax<- resolved StaticField ptr 8738 UNSPILL(rPC) 8739 testl %eax,%eax 8740 jne .LOP_SGET_OBJECT_VOLATILE_finish # success, continue 8741 jmp common_exceptionThrown # no, handle exception 8742 8743/* continuation for OP_SPUT_OBJECT_VOLATILE */ 8744 8745 8746.LOP_SPUT_OBJECT_VOLATILE_continue: 8747 movl %ecx,offStaticField_value(%eax) 8748 testl %ecx,%ecx 8749 GET_GLUE(%ecx) 8750 FETCH_INST_WORD(2) 8751 je 1f 8752 movl offGlue_cardTable(%ecx),%ecx # get card table base 8753 shrl $GC_CARD_SHIFT,%eax # head to card number 8754 movb %cl,(%ecx,%eax) # mark card 87551: 8756 ADVANCE_PC(2) 8757 GOTO_NEXT 8758 8759.LOP_SPUT_OBJECT_VOLATILE_resolve: 8760 GET_GLUE(%ecx) 8761 movzwl 2(rPC),%eax # eax<- field ref BBBB 8762 movl offGlue_method(%ecx),%ecx # ecx<- current method 8763 EXPORT_PC() # could throw, need to export 8764 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8765 SPILL(rPC) 8766 movl %eax,OUT_ARG1(%esp) 8767 movl %ecx,OUT_ARG0(%esp) 8768 call dvmResolveStaticField # eax<- resolved StaticField ptr 8769 UNSPILL(rPC) 8770 testl %eax,%eax 8771 jne .LOP_SPUT_OBJECT_VOLATILE_finish # success, continue 8772 jmp common_exceptionThrown # no, handle exception 8773 8774 .size dvmAsmSisterStart, .-dvmAsmSisterStart 8775 .global dvmAsmSisterEnd 8776dvmAsmSisterEnd: 8777 8778/* File: x86/entry.S */ 8779/* 8780 * Copyright (C) 2008 The Android Open Source Project 8781 * 8782 * Licensed under the Apache License, Version 2.0 (the "License"); 8783 * you may not use this file except in compliance with the License. 8784 * You may obtain a copy of the License at 8785 * 8786 * http://www.apache.org/licenses/LICENSE-2.0 8787 * 8788 * Unless required by applicable law or agreed to in writing, software 8789 * distributed under the License is distributed on an "AS IS" BASIS, 8790 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8791 * See the License for the specific language governing permissions and 8792 * limitations under the License. 8793 */ 8794 8795 8796 .text 8797 .global dvmMterpStdRun 8798 .type dvmMterpStdRun, %function 8799/* 8800 * bool dvmMterpStdRun(MterpGlue* glue) 8801 * 8802 * Interpreter entry point. Returns changeInterp. 8803 * 8804 */ 8805dvmMterpStdRun: 8806 push %ebp 8807 movl %esp,%ebp 8808 push %edi 8809 push %esi 8810 push %ebx 8811 8812/* at this point, stack is misaligned by 1 word 8813 We're allocating spill space for 6 words, plus 8814 outgoing argument (5 words) and local variables 8815 (4 words) - 15 words or 60 bytes total. See 8816 diagram in header.S 8817*/ 8818 subl $60,%esp 8819 8820/* Set up "named" registers */ 8821 movl IN_ARG0(%ebp),%ecx 8822 movl %ecx,rGLUE_SPILL(%ebp) 8823 LOAD_PC_FROM_GLUE(%ecx) 8824 LOAD_FP_FROM_GLUE(%ecx) 8825 movl $dvmAsmInstructionStart,rIBASE 8826 8827/* Remember %esp for future "longjmp" */ 8828 movl %esp,offGlue_bailPtr(%ecx) 8829 8830/* How to start? */ 8831 movb offGlue_entryPoint(%ecx),%al 8832 8833/* Normal start? */ 8834 cmpb $kInterpEntryInstr,%al 8835 jne .Lnot_instr 8836 8837 /* Normal case: start executing the instruction at rPC */ 8838 FETCH_INST() 8839 GOTO_NEXT 8840 8841.Lnot_instr: 8842 /* Reset to normal case */ 8843 movb $kInterpEntryInstr,offGlue_entryPoint(%ecx) 8844 cmpb $kInterpEntryReturn,%al 8845 je common_returnFromMethod 8846 cmpb $kInterpEntryThrow,%al 8847 je common_exceptionThrown 8848 movzx %al,%eax 8849 movl %eax,OUT_ARG1(%esp) 8850 movl $.LstrBadEntryPoint,OUT_ARG0(%esp) 8851 call printf 8852 call dvmAbort 8853 /* Not reached */ 8854 8855 8856 .global dvmMterpStdBail 8857 .type dvmMterpStdBail, %function 8858/* 8859 * void dvmMterpStdBail(MterpGlue* glue, bool changeInterp) 8860 * 8861 * Restore the stack pointer and PC from the save point established on entry. 8862 * This is essentially the same as a longjmp, but should be cheaper. The 8863 * last instruction causes us to return to whoever called dvmMterpStdRun. 8864 * 8865 * We're not going to build a standard frame here, so the arg accesses will 8866 * look a little strange. 8867 * 8868 * On entry: 8869 * esp+4 (arg0) MterpGlue* glue 8870 * esp+8 (arg1) bool changeInterp 8871 */ 8872dvmMterpStdBail: 8873 movl 4(%esp),%ecx # grab glue 8874 movl 8(%esp),%eax # changeInterp to return reg 8875 movl offGlue_bailPtr(%ecx),%esp # Stack back to normal 8876 addl $60,%esp # Strip dvmMterpStdRun's frame 8877 pop %ebx 8878 pop %esi 8879 pop %edi 8880 pop %ebp 8881 ret # return to dvmMterpStdRun's caller 8882 8883 8884/* 8885 * Strings 8886 */ 8887 .section .rodata 8888.LstrBadEntryPoint: 8889 .asciz "Bad entry point %d\n" 8890 8891/* File: x86/footer.S */ 8892/* 8893 * Copyright (C) 2008 The Android Open Source Project 8894 * 8895 * Licensed under the Apache License, Version 2.0 (the "License"); 8896 * you may not use this file except in compliance with the License. 8897 * You may obtain a copy of the License at 8898 * 8899 * http://www.apache.org/licenses/LICENSE-2.0 8900 * 8901 * Unless required by applicable law or agreed to in writing, software 8902 * distributed under the License is distributed on an "AS IS" BASIS, 8903 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8904 * See the License for the specific language governing permissions and 8905 * limitations under the License. 8906 */ 8907/* 8908 * Common subroutines and data. 8909 */ 8910 8911/* 8912 * Common code when a backwards branch is taken 8913 * 8914 * On entry: 8915 * ebx (a.k.a. rINST_FULL) -> PC adjustment in 16-bit words 8916 */ 8917common_backwardBranch: 8918 GET_GLUE(%ecx) 8919 call common_periodicChecks # Note: expects rPC to be preserved 8920 ADVANCE_PC_INDEXED(rINST_FULL) 8921 FETCH_INST() 8922 GOTO_NEXT 8923 8924 8925 8926/* 8927 * Common code for method invocation with range. 8928 * 8929 * On entry: 8930 * eax = Method* methodToCall 8931 * rINST trashed, must reload 8932 */ 8933 8934common_invokeMethodRange: 8935.LinvokeNewRange: 8936 8937 /* 8938 * prepare to copy args to "outs" area of current frame 8939 */ 8940 8941 movzbl 1(rPC),rINST_FULL # rINST_FULL<- AA 8942 movzwl 4(rPC), %ecx # %ecx<- CCCC 8943 SPILL(rPC) 8944 SAVEAREA_FROM_FP(%edx,rFP) # %edx<- &StackSaveArea 8945 test rINST_FULL, rINST_FULL 8946 movl rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA 8947 jz .LinvokeArgsDone # no args; jump to args done 8948 8949 8950 /* 8951 * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, %edx=&outs (&stackSaveArea) 8952 * (very few methods have > 10 args; could unroll for common cases) 8953 */ 8954 8955 movl %ebx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- save %ebx 8956 lea (rFP, %ecx, 4), %ecx # %ecx<- &vCCCC 8957 shll $2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset 8958 subl LOCAL0_OFFSET(%ebp), %edx # %edx<- update &outs 8959 shrl $2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset 89601: 8961 movl (%ecx), %ebx # %ebx<- vCCCC 8962 lea 4(%ecx), %ecx # %ecx<- &vCCCC++ 8963 subl $1, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- LOCAL0_OFFSET-- 8964 movl %ebx, (%edx) # *outs<- vCCCC 8965 lea 4(%edx), %edx # outs++ 8966 jne 1b # loop if count (LOCAL0_OFFSET(%ebp)) not zero 8967 movl LOCAL1_OFFSET(%ebp), %ebx # %ebx<- restore %ebx 8968 jmp .LinvokeArgsDone # continue 8969 8970 /* 8971 * %eax is "Method* methodToCall", the method we're trying to call 8972 * prepare to copy args to "outs" area of current frame 8973 */ 8974 8975common_invokeMethodNoRange: 8976.LinvokeNewNoRange: 8977 movzbl 1(rPC),rINST_FULL # rINST_FULL<- BA 8978 SPILL(rPC) 8979 movl rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA 8980 shrl $4, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- B 8981 je .LinvokeArgsDone # no args; jump to args done 8982 movzwl 4(rPC), %ecx # %ecx<- GFED 8983 SAVEAREA_FROM_FP(%edx,rFP) # %edx<- &StackSaveArea 8984 8985 /* 8986 * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs 8987 */ 8988 8989.LinvokeNonRange: 8990 cmp $2, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 2 8991 movl %ecx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- GFED 8992 jl 1f # handle 1 arg 8993 je 2f # handle 2 args 8994 cmp $4, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 4 8995 jl 3f # handle 3 args 8996 je 4f # handle 4 args 89975: 8998 andl $15, rINST_FULL # rINST<- A 8999 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 9000 movl (rFP, rINST_FULL, 4), %ecx # %ecx<- vA 9001 movl %ecx, (%edx) # *outs<- vA 9002 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 90034: 9004 shr $12, %ecx # %ecx<- G 9005 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 9006 movl (rFP, %ecx, 4), %ecx # %ecx<- vG 9007 movl %ecx, (%edx) # *outs<- vG 9008 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 90093: 9010 and $0x0f00, %ecx # %ecx<- 0F00 9011 shr $8, %ecx # %ecx<- F 9012 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 9013 movl (rFP, %ecx, 4), %ecx # %ecx<- vF 9014 movl %ecx, (%edx) # *outs<- vF 9015 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 90162: 9017 and $0x00f0, %ecx # %ecx<- 00E0 9018 shr $4, %ecx # %ecx<- E 9019 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 9020 movl (rFP, %ecx, 4), %ecx # %ecx<- vE 9021 movl %ecx, (%edx) # *outs<- vE 9022 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 90231: 9024 and $0x000f, %ecx # %ecx<- 000D 9025 movl (rFP, %ecx, 4), %ecx # %ecx<- vD 9026 movl %ecx, -4(%edx) # *--outs<- vD 90270: 9028 9029 /* 9030 * %eax is "Method* methodToCall", the method we're trying to call 9031 * find space for the new stack frame, check for overflow 9032 */ 9033 9034.LinvokeArgsDone: 9035 movzwl offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize 9036 movzwl offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize 9037 movl %eax, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- methodToCall 9038 shl $2, %edx # %edx<- update offset 9039 SAVEAREA_FROM_FP(%eax,rFP) # %eax<- &StackSaveArea 9040 subl %edx, %eax # %eax<- newFP; (old savearea - regsSize) 9041 GET_GLUE(%edx) # %edx<- pMterpGlue 9042 movl %eax, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- &outs 9043 subl $sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP) 9044 movl offGlue_interpStackEnd(%edx), %edx # %edx<- glue->interpStackEnd 9045 movl %edx, LOCAL2_OFFSET(%ebp) # LOCAL2_OFFSET<- glue->interpStackEnd 9046 shl $2, %ecx # %ecx<- update offset for outsSize 9047 movl %eax, %edx # %edx<- newSaveArea 9048 sub %ecx, %eax # %eax<- bottom; (newSaveArea - outsSize) 9049 cmp LOCAL2_OFFSET(%ebp), %eax # compare interpStackEnd and bottom 9050 movl LOCAL0_OFFSET(%ebp), %eax # %eax<- restore methodToCall 9051 jl .LstackOverflow # handle frame overflow 9052 9053 /* 9054 * set up newSaveArea 9055 */ 9056 9057#ifdef EASY_GDB 9058 SAVEAREA_FROM_FP(%ecx,rFP) # %ecx<- &StackSaveArea 9059 movl %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs 9060#endif 9061 movl rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP 9062 movl rPC_SPILL(%ebp), %ecx 9063 movl %ecx, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC 9064 testl $ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call 9065 movl %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call 9066 jne .LinvokeNative # handle native call 9067 9068 /* 9069 * Update "glue" values for the new method 9070 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp 9071 */ 9072 9073 movl offMethod_clazz(%eax), %edx # %edx<- method->clazz 9074 GET_GLUE(%ecx) # %ecx<- pMterpGlue 9075 movl offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex 9076 movl %eax, offGlue_method(%ecx) # glue->method<- methodToCall 9077 movl %edx, offGlue_methodClassDex(%ecx) # glue->methodClassDex<- method->clazz->pDvmDex 9078 movl offMethod_insns(%eax), rPC # rPC<- methodToCall->insns 9079 movl offGlue_self(%ecx), %eax # %eax<- glue->self 9080 movl LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP 9081 movl rFP, offThread_curFrame(%eax) # glue->self->curFrame<- newFP 9082 FETCH_INST() 9083 GOTO_NEXT # jump to methodToCall->insns 9084 9085 /* 9086 * Prep for the native call 9087 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea 9088 */ 9089 9090.LinvokeNative: 9091 GET_GLUE(%ecx) # %ecx<- pMterpGlue 9092 movl %eax, OUT_ARG1(%esp) # push parameter methodToCall 9093 movl offGlue_self(%ecx), %ecx # %ecx<- glue->self 9094 movl offThread_jniLocal_topCookie(%ecx), %eax # %eax<- self->localRef->... 9095 movl %eax, offStackSaveArea_localRefCookie(%edx) # newSaveArea->localRefCookie<- top 9096 movl %edx, OUT_ARG4(%esp) # save newSaveArea 9097 movl LOCAL1_OFFSET(%ebp), %edx # %edx<- newFP 9098 movl %edx, offThread_curFrame(%ecx) # glue->self->curFrame<- newFP 9099 movl %ecx, OUT_ARG3(%esp) # save glue->self 9100 movl %ecx, OUT_ARG2(%esp) # push parameter glue->self 9101 GET_GLUE(%ecx) # %ecx<- pMterpGlue 9102 movl OUT_ARG1(%esp), %eax # %eax<- methodToCall 9103 lea offGlue_retval(%ecx), %ecx # %ecx<- &retval 9104 movl %ecx, OUT_ARG0(%esp) # push parameter pMterpGlue 9105 push %edx # push parameter newFP 9106 9107 call *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc 9108 lea 4(%esp), %esp 9109 movl OUT_ARG4(%esp), %ecx # %ecx<- newSaveArea 9110 movl OUT_ARG3(%esp), %eax # %eax<- glue->self 9111 movl offStackSaveArea_localRefCookie(%ecx), %edx # %edx<- old top 9112 cmp $0, offThread_exception(%eax) # check for exception 9113 movl rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP 9114 movl %edx, offThread_jniLocal_topCookie(%eax) # new top <- old top 9115 UNSPILL(rPC) 9116 jne common_exceptionThrown # handle exception 9117 FETCH_INST_WORD(3) 9118 ADVANCE_PC(3) 9119 GOTO_NEXT # jump to next instruction 9120 9121.LstackOverflow: # eax=methodToCall 9122 movl %eax, OUT_ARG1(%esp) # push parameter methodToCall 9123 GET_GLUE(%eax) # %eax<- pMterpGlue 9124 movl offGlue_self(%eax), %eax # %eax<- glue->self 9125 movl %eax, OUT_ARG0(%esp) # push parameter self 9126 call dvmHandleStackOverflow # call: (Thread* self, Method* meth) 9127 UNSPILL(rPC) # return: void 9128 jmp common_exceptionThrown # handle exception 9129 9130 9131/* 9132 * Common invoke code (old-style). 9133 * TUNING: Rewrite along lines of new armv5 code? 9134 * 9135 * On entry: 9136 * eax = Method* methodToCall 9137 * ecx = bool methodCallRange 9138 * rINST trashed, must reload 9139 */ 9140common_invokeOld: 9141 movl %ecx,OUT_ARG1(%esp) # arg1<- methodCallRange 9142 GET_GLUE(%ecx) 9143 movzwl (rPC),rINST_FULL # recover rINST 9144 movl %eax,OUT_ARG2(%esp) # arg2<- method 9145 movzwl 4(rPC),%eax # eax<- GFED or CCCC 9146 SAVE_PC_TO_GLUE(%ecx) 9147 SAVE_FP_TO_GLUE(%ecx) 9148 movzbl rINST_HI,rINST_FULL 9149 movl rINST_FULL,OUT_ARG3(%esp)# arg3<- AA 9150 movl %ecx,OUT_ARG0(%esp) # arg0<- GLUE 9151 movl %eax,OUT_ARG4(%esp) # arg4<- GFED/CCCC 9152 call dvmMterp_invokeMethod 9153 jmp common_resumeAfterGlueCall 9154 9155 9156/* 9157 * Do we need the thread to be suspended or have debugger/profiling activity? 9158 * 9159 * On entry: 9160 * ebx -> PC adjustment in 16-bit words (must be preserved) 9161 * ecx -> GLUE pointer 9162 * reentry type, e.g. kInterpEntryInstr stored in rGLUE->entryPoint 9163 * 9164 * Note: A call will normally kill %eax, rPC/%edx and %ecx. To 9165 * streamline the normal case, this routine will preserve rPC and 9166 * %ecx in addition to the normal caller save regs. The save/restore 9167 * is a bit ugly, but will happen in the relatively uncommon path. 9168 * TODO: Basic-block style Jit will need a hook here as well. Fold it into 9169 * the suspendCount check so we can get both in 1 shot. 9170 */ 9171common_periodicChecks: 9172 movl offGlue_pSelfSuspendCount(%ecx),%eax # eax <- &suspendCount 9173 cmpl $0,(%eax) 9174 jne 1f 9175 91766: 9177 movl offGlue_pDebuggerActive(%ecx),%eax # eax <- &DebuggerActive 9178 movl offGlue_pActiveProfilers(%ecx),%ecx # ecx <- &ActiveProfilers 9179 testl %eax,%eax # debugger enabled? 9180 je 2f 9181 movzbl (%eax),%eax # get active count 91822: 9183 orl (%ecx),%eax # eax <- debuggerActive | activeProfilers 9184 GET_GLUE(%ecx) # restore rGLUE 9185 jne 3f # one or both active - switch interp 9186 91875: 9188 ret 9189 9190 /* Check for suspend */ 91911: 9192 /* At this point, the return pointer to the caller of 9193 * common_periodicChecks is on the top of stack. We need to preserve 9194 * rPC(edx) and GLUE(ecx). We'll spill rPC, and reload GLUE. 9195 * The outgoing profile is: 9196 * bool dvmCheckSuspendPending(Thread* self) 9197 * Because we reached here via a call, go ahead and build a new frame. 9198 */ 9199 EXPORT_PC() # need for precise GC 9200 movl offGlue_self(%ecx),%eax # eax<- glue->self 9201 SPILL(rPC) # save edx 9202 push %ebp 9203 movl %esp,%ebp 9204 subl $24,%esp 9205 movl %eax,OUT_ARG0(%esp) 9206 call dvmCheckSuspendPending 9207 addl $24,%esp 9208 pop %ebp 9209 UNSPILL(rPC) 9210 GET_GLUE(%ecx) 9211 9212 /* 9213 * Need to check to see if debugger or profiler flags got set 9214 * while we were suspended. 9215 */ 9216 jmp 6b 9217 9218 /* Switch interpreters */ 9219 /* Note: %ebx contains the 16-bit word offset to be applied to rPC to 9220 * "complete" the interpretation of backwards branches. In effect, we 9221 * are completing the interpretation of the branch instruction here, 9222 * and the new interpreter will resume interpretation at the branch 9223 * target. However, a switch request recognized during the handling 9224 * of a return from method instruction results in an immediate abort, 9225 * and the new interpreter will resume by re-interpreting the return 9226 * instruction. 9227 */ 92283: 9229 leal (rPC,%ebx,2),rPC # adjust pc to show target 9230 GET_GLUE(%ecx) # bail expect GLUE already loaded 9231 movl $1,rINST_FULL # set changeInterp to true 9232 jmp common_gotoBail 9233 9234 9235/* 9236 * Common code for handling a return instruction 9237 */ 9238common_returnFromMethod: 9239 GET_GLUE(%ecx) 9240 /* Set entry mode in case we bail */ 9241 movb $kInterpEntryReturn,offGlue_entryPoint(%ecx) 9242 xorl rINST_FULL,rINST_FULL # zero offset in case we switch interps 9243 call common_periodicChecks # Note: expects %ecx to be preserved 9244 9245 SAVEAREA_FROM_FP(%eax,rFP) # eax<- saveArea (old) 9246 movl offStackSaveArea_prevFrame(%eax),rFP # rFP<- prevFrame 9247 movl (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST_FULL 9248 cmpl $0,rINST_FULL # break? 9249 je common_gotoBail # break frame, bail out completely 9250 9251 movl offStackSaveArea_savedPc(%eax),rPC # pc<- saveArea->savedPC 9252 movl offGlue_self(%ecx),%eax # eax<- self 9253 movl rINST_FULL,offGlue_method(%ecx) # glue->method = newSave->meethod 9254 movl rFP,offThread_curFrame(%eax) # self->curFrame = fp 9255 movl offMethod_clazz(rINST_FULL),%eax # eax<- method->clazz 9256 FETCH_INST_WORD(3) 9257 movl offClassObject_pDvmDex(%eax),%eax # eax<- method->clazz->pDvmDex 9258 ADVANCE_PC(3) 9259 movl %eax,offGlue_methodClassDex(%ecx) 9260 /* not bailing - restore entry mode to default */ 9261 movb $kInterpEntryInstr,offGlue_entryPoint(%ecx) 9262 GOTO_NEXT 9263 9264/* 9265 * Prepare to strip the current frame and "longjump" back to caller of 9266 * dvmMterpStdRun. 9267 * 9268 * on entry: 9269 * rINST_FULL holds changeInterp 9270 * ecx holds glue pointer 9271 * 9272 * expected profile: dvmMterpStdBail(MterpGlue *glue, bool changeInterp) 9273 */ 9274common_gotoBail: 9275 SAVE_PC_TO_GLUE(%ecx) # export state to glue 9276 SAVE_FP_TO_GLUE(%ecx) 9277 movl %ecx,OUT_ARG0(%esp) # glue in arg0 9278 movl rINST_FULL,OUT_ARG1(%esp) # changeInterp in arg1 9279 call dvmMterpStdBail # bail out.... 9280 9281 9282/* 9283 * After returning from a "glued" function, pull out the updated values 9284 * and start executing at the next instruction. 9285 */ 9286 common_resumeAfterGlueCall: 9287 GET_GLUE(%ecx) 9288 LOAD_PC_FROM_GLUE(%ecx) 9289 LOAD_FP_FROM_GLUE(%ecx) 9290 FETCH_INST() 9291 GOTO_NEXT 9292 9293/* 9294 * Integer divide or mod by zero 9295 */ 9296common_errDivideByZero: 9297 EXPORT_PC() 9298 movl $.LstrArithmeticException,%eax 9299 movl %eax,OUT_ARG0(%esp) 9300 movl $.LstrDivideByZero,%eax 9301 movl %eax,OUT_ARG1(%esp) 9302 SPILL(rPC) 9303 call dvmThrowException 9304 UNSPILL(rPC) 9305 jmp common_exceptionThrown 9306 9307/* 9308 * Attempt to allocate an array with a negative size. 9309 */ 9310common_errNegativeArraySize: 9311 EXPORT_PC() 9312 movl $.LstrNegativeArraySizeException,%eax 9313 movl %eax,OUT_ARG0(%esp) 9314 xorl %eax,%eax 9315 movl %eax,OUT_ARG1(%esp) 9316 SPILL(rPC) 9317 call dvmThrowException 9318 UNSPILL(rPC) 9319 jmp common_exceptionThrown 9320 9321/* 9322 * Attempt to allocate an array with a negative size. 9323 */ 9324common_errNoSuchMethod: 9325 9326 EXPORT_PC() 9327 movl $.LstrNoSuchMethodError,%eax 9328 movl %eax,OUT_ARG0(%esp) 9329 xorl %eax,%eax 9330 movl %eax,OUT_ARG1(%esp) 9331 SPILL(rPC) 9332 call dvmThrowException 9333 UNSPILL(rPC) 9334 jmp common_exceptionThrown 9335 9336/* 9337 * Hit a null object when we weren't expecting one. Export the PC, throw a 9338 * NullPointerException and goto the exception processing code. 9339 */ 9340common_errNullObject: 9341 EXPORT_PC() 9342 movl $.LstrNullPointerException,%eax 9343 movl %eax,OUT_ARG0(%esp) 9344 xorl %eax,%eax 9345 movl %eax,OUT_ARG1(%esp) 9346 SPILL(rPC) 9347 call dvmThrowException 9348 UNSPILL(rPC) 9349 jmp common_exceptionThrown 9350 9351/* 9352 * Array index exceeds max. 9353 */ 9354common_errArrayIndex: 9355 EXPORT_PC() 9356 movl $.LstrArrayIndexException,%eax 9357 movl %eax,OUT_ARG0(%esp) 9358 xorl %eax,%eax 9359 movl %eax,OUT_ARG1(%esp) 9360 SPILL(rPC) 9361 call dvmThrowException 9362 UNSPILL(rPC) 9363 jmp common_exceptionThrown 9364/* 9365 * Invalid array value. 9366 */ 9367common_errArrayStore: 9368 EXPORT_PC() 9369 movl $.LstrArrayStoreException,%eax 9370 movl %eax,OUT_ARG0(%esp) 9371 xorl %eax,%eax 9372 movl %eax,OUT_ARG1(%esp) 9373 SPILL(rPC) 9374 call dvmThrowException 9375 UNSPILL(rPC) 9376 jmp common_exceptionThrown 9377 9378/* 9379 * Somebody has thrown an exception. Handle it. 9380 * 9381 * If the exception processing code returns to us (instead of falling 9382 * out of the interpreter), continue with whatever the next instruction 9383 * now happens to be. 9384 * 9385 * This does not return. 9386 */ 9387common_exceptionThrown: 9388 GET_GLUE(%ecx) 9389 SAVE_PC_TO_GLUE(%ecx) 9390 SAVE_FP_TO_GLUE(%ecx) 9391 movl %ecx,OUT_ARG0(%esp) 9392 call dvmMterp_exceptionThrown 9393 jmp common_resumeAfterGlueCall 9394 9395common_abort: 9396 movl $0xdeadf00d,%eax 9397 call *%eax 9398 9399 9400/* 9401 * Strings 9402 */ 9403 9404 .section .rodata 9405.LstrNullPointerException: 9406 .asciz "Ljava/lang/NullPointerException;" 9407.LstrArithmeticException: 9408 .asciz "Ljava/lang/ArithmeticException;" 9409.LstrDivideByZero: 9410 .asciz "divide by zero" 9411.LstrArrayIndexException: 9412 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 9413.LstrArrayStoreException: 9414 .asciz "Ljava/lang/ArrayStoreException;" 9415.LstrNegativeArraySizeException: 9416 .asciz "Ljava/lang/NegativeArraySizeException;" 9417.LstrInstantiationError: 9418 .asciz "Ljava/lang/InstantiationError;" 9419.LstrClassCastException: 9420 .asciz "Ljava/lang/ClassCastException;" 9421.LstrNoSuchMethodError: 9422 .asciz "Ljava/lang/NoSuchMethodError;" 9423.LstrInternalError: 9424 .asciz "Ljava/lang/InternalError;" 9425.LstrFilledNewArrayNotImpl: 9426 .asciz "filled-new-array only implemented for 'int'" 9427 9428