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