InterpAsm-x86.S revision b78c76f88ea42e7a3b295c210ca9ee86e7290043
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 FETCH_INST_WORD(2) 7690 je 1f # skip card mark if null 7691 GET_GLUE(%ecx) 7692 movl offField_clazz(%eax),%eax # eax<- field->clazz 7693 movl offGlue_cardTable(%ecx),%ecx # get card table base 7694 shrl $GC_CARD_SHIFT,%eax # head to card number 7695 movb %cl,(%ecx,%eax) # mark card 76961: 7697 ADVANCE_PC(2) 7698 GOTO_NEXT 7699 7700.LOP_SPUT_OBJECT_resolve: 7701 GET_GLUE(%ecx) 7702 movzwl 2(rPC),%eax # eax<- field ref BBBB 7703 movl offGlue_method(%ecx),%ecx # ecx<- current method 7704 EXPORT_PC() # could throw, need to export 7705 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7706 SPILL(rPC) 7707 movl %eax,OUT_ARG1(%esp) 7708 movl %ecx,OUT_ARG0(%esp) 7709 call dvmResolveStaticField # eax<- resolved StaticField ptr 7710 UNSPILL(rPC) 7711 testl %eax,%eax 7712 jne .LOP_SPUT_OBJECT_finish # success, continue 7713 jmp common_exceptionThrown # no, handle exception 7714 7715/* continuation for OP_SPUT_BOOLEAN */ 7716 7717 /* 7718 * Go resolve the field 7719 */ 7720.LOP_SPUT_BOOLEAN_resolve: 7721 GET_GLUE(%ecx) 7722 movzwl 2(rPC),%eax # eax<- field ref BBBB 7723 movl offGlue_method(%ecx),%ecx # ecx<- current method 7724 EXPORT_PC() # could throw, need to export 7725 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7726 SPILL(rPC) 7727 movl %eax,OUT_ARG1(%esp) 7728 movl %ecx,OUT_ARG0(%esp) 7729 call dvmResolveStaticField # eax<- resolved StaticField ptr 7730 UNSPILL(rPC) 7731 testl %eax,%eax 7732 jne .LOP_SPUT_BOOLEAN_finish # success, continue 7733 jmp common_exceptionThrown # no, handle exception 7734 7735/* continuation for OP_SPUT_BYTE */ 7736 7737 /* 7738 * Go resolve the field 7739 */ 7740.LOP_SPUT_BYTE_resolve: 7741 GET_GLUE(%ecx) 7742 movzwl 2(rPC),%eax # eax<- field ref BBBB 7743 movl offGlue_method(%ecx),%ecx # ecx<- current method 7744 EXPORT_PC() # could throw, need to export 7745 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7746 SPILL(rPC) 7747 movl %eax,OUT_ARG1(%esp) 7748 movl %ecx,OUT_ARG0(%esp) 7749 call dvmResolveStaticField # eax<- resolved StaticField ptr 7750 UNSPILL(rPC) 7751 testl %eax,%eax 7752 jne .LOP_SPUT_BYTE_finish # success, continue 7753 jmp common_exceptionThrown # no, handle exception 7754 7755/* continuation for OP_SPUT_CHAR */ 7756 7757 /* 7758 * Go resolve the field 7759 */ 7760.LOP_SPUT_CHAR_resolve: 7761 GET_GLUE(%ecx) 7762 movzwl 2(rPC),%eax # eax<- field ref BBBB 7763 movl offGlue_method(%ecx),%ecx # ecx<- current method 7764 EXPORT_PC() # could throw, need to export 7765 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7766 SPILL(rPC) 7767 movl %eax,OUT_ARG1(%esp) 7768 movl %ecx,OUT_ARG0(%esp) 7769 call dvmResolveStaticField # eax<- resolved StaticField ptr 7770 UNSPILL(rPC) 7771 testl %eax,%eax 7772 jne .LOP_SPUT_CHAR_finish # success, continue 7773 jmp common_exceptionThrown # no, handle exception 7774 7775/* continuation for OP_SPUT_SHORT */ 7776 7777 /* 7778 * Go resolve the field 7779 */ 7780.LOP_SPUT_SHORT_resolve: 7781 GET_GLUE(%ecx) 7782 movzwl 2(rPC),%eax # eax<- field ref BBBB 7783 movl offGlue_method(%ecx),%ecx # ecx<- current method 7784 EXPORT_PC() # could throw, need to export 7785 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7786 SPILL(rPC) 7787 movl %eax,OUT_ARG1(%esp) 7788 movl %ecx,OUT_ARG0(%esp) 7789 call dvmResolveStaticField # eax<- resolved StaticField ptr 7790 UNSPILL(rPC) 7791 testl %eax,%eax 7792 jne .LOP_SPUT_SHORT_finish # success, continue 7793 jmp common_exceptionThrown # no, handle exception 7794 7795/* continuation for OP_INVOKE_VIRTUAL */ 7796 7797 7798.LOP_INVOKE_VIRTUAL_more: 7799 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz 7800 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 7801 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags 7802 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7803 UNSPILL(rPC) 7804 testl %eax,%eax # got null? 7805 jne .LOP_INVOKE_VIRTUAL_continue # no, continue 7806 jmp common_exceptionThrown # yes, handle exception 7807 7808 /* At this point: 7809 * eax = resolved base method 7810 * ecx = scratch 7811 */ 7812.LOP_INVOKE_VIRTUAL_continue: 7813 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC 7814 .if (!0) 7815 andl $0xf,%ecx # ecx<- D (or stays CCCC) 7816 .endif 7817 GET_VREG(%ecx,%ecx) # ecx<- "this" 7818 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex 7819 testl %ecx,%ecx # null this? 7820 je common_errNullObject # go if so 7821 movl offObject_clazz(%ecx),%ecx # ecx<- thisPtr->clazz 7822 movl offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable 7823 movl (%ecx,%eax,4),%eax # eax<- vtable[methodIndex] 7824 jmp common_invokeMethodNoRange 7825 7826/* continuation for OP_INVOKE_SUPER */ 7827 7828 /* 7829 * At this point: 7830 * ecx = resolved base method [r0] 7831 * eax = method->clazz [r9] 7832 */ 7833.LOP_INVOKE_SUPER_continue: 7834 movl offClassObject_super(%eax),%eax # eax<- method->clazz->super 7835 movzwl offMethod_methodIndex(%ecx),%ecx # ecx<- baseMthod->methodIndex 7836 cmpl offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount) 7837 jae .LOP_INVOKE_SUPER_nsm # method not present in superclass 7838 movl offClassObject_vtable(%eax),%eax # eax<- ...clazz->super->vtable 7839 movl (%eax,%ecx,4),%eax # eax<- vtable[methodIndex] 7840 jmp common_invokeMethodNoRange 7841 7842 7843 /* At this point: 7844 * ecx = null (needs to be resolved base method) 7845 * eax = method->clazz 7846 */ 7847.LOP_INVOKE_SUPER_resolve: 7848 SPILL_TMP(%eax) # method->clazz 7849 movl %eax,OUT_ARG0(%esp) # arg0<- method->clazz 7850 movzwl 2(rPC),%ecx # ecx<- BBBB 7851 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- resolver method type 7852 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 7853 SPILL(rPC) 7854 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7855 UNSPILL(rPC) 7856 testl %eax,%eax # got null? 7857 movl %eax,%ecx # ecx<- resolved base method 7858 UNSPILL_TMP(%eax) # restore method->clazz 7859 jne .LOP_INVOKE_SUPER_continue # good to go - continue 7860 jmp common_exceptionThrown # handle exception 7861 7862 /* 7863 * Throw a NoSuchMethodError with the method name as the message. 7864 * ecx = resolved base method 7865 */ 7866.LOP_INVOKE_SUPER_nsm: 7867 movl offMethod_name(%ecx),%eax 7868 mov %eax,OUT_ARG1(%esp) 7869 jmp common_errNoSuchMethod 7870 7871/* continuation for OP_INVOKE_DIRECT */ 7872 7873 /* 7874 * On entry: 7875 * TMP_SPILL <- "this" register 7876 * Things a bit ugly on this path, but it's the less 7877 * frequent one. We'll have to do some reloading. 7878 */ 7879.LOP_INVOKE_DIRECT_resolve: 7880 SPILL_TMP(%ecx) 7881 GET_GLUE(%ecx) 7882 UNSPILL(rPC) 7883 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 7884 movzwl 2(rPC),%eax # reference (BBBB or CCCC) 7885 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7886 movl $METHOD_DIRECT,OUT_ARG2(%esp) 7887 movl %eax,OUT_ARG1(%esp) 7888 movl %ecx,OUT_ARG0(%esp) 7889 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7890 UNSPILL_TMP(%ecx) 7891 testl %eax,%eax 7892 jne .LOP_INVOKE_DIRECT_finish 7893 UNSPILL(rPC) 7894 jmp common_exceptionThrown 7895 7896/* continuation for OP_INVOKE_STATIC */ 7897 7898.LOP_INVOKE_STATIC_continue: 7899 movl $METHOD_STATIC,%eax 7900 movl %eax,OUT_ARG2(%esp) # arg2<- flags 7901 SPILL(rPC) 7902 call dvmResolveMethod # call(clazz,ref,flags) 7903 UNSPILL(rPC) 7904 testl %eax,%eax # got null? 7905 jne common_invokeMethodNoRange 7906 jmp common_exceptionThrown 7907 7908/* continuation for OP_INVOKE_INTERFACE */ 7909 7910.LOP_INVOKE_INTERFACE_continue: 7911 call dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex) 7912 UNSPILL(rPC) 7913 testl %eax,%eax 7914 je common_exceptionThrown 7915 jmp common_invokeMethodNoRange 7916 7917/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 7918 7919 7920.LOP_INVOKE_VIRTUAL_RANGE_more: 7921 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz 7922 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 7923 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags 7924 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7925 UNSPILL(rPC) 7926 testl %eax,%eax # got null? 7927 jne .LOP_INVOKE_VIRTUAL_RANGE_continue # no, continue 7928 jmp common_exceptionThrown # yes, handle exception 7929 7930 /* At this point: 7931 * eax = resolved base method 7932 * ecx = scratch 7933 */ 7934.LOP_INVOKE_VIRTUAL_RANGE_continue: 7935 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC 7936 .if (!1) 7937 andl $0xf,%ecx # ecx<- D (or stays CCCC) 7938 .endif 7939 GET_VREG(%ecx,%ecx) # ecx<- "this" 7940 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex 7941 testl %ecx,%ecx # null this? 7942 je common_errNullObject # go if so 7943 movl offObject_clazz(%ecx),%ecx # ecx<- thisPtr->clazz 7944 movl offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable 7945 movl (%ecx,%eax,4),%eax # eax<- vtable[methodIndex] 7946 jmp common_invokeMethodRange 7947 7948/* continuation for OP_INVOKE_SUPER_RANGE */ 7949 7950 /* 7951 * At this point: 7952 * ecx = resolved base method [r0] 7953 * eax = method->clazz [r9] 7954 */ 7955.LOP_INVOKE_SUPER_RANGE_continue: 7956 movl offClassObject_super(%eax),%eax # eax<- method->clazz->super 7957 movzwl offMethod_methodIndex(%ecx),%ecx # ecx<- baseMthod->methodIndex 7958 cmpl offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount) 7959 jae .LOP_INVOKE_SUPER_RANGE_nsm # method not present in superclass 7960 movl offClassObject_vtable(%eax),%eax # eax<- ...clazz->super->vtable 7961 movl (%eax,%ecx,4),%eax # eax<- vtable[methodIndex] 7962 jmp common_invokeMethodRange 7963 7964 7965 /* At this point: 7966 * ecx = null (needs to be resolved base method) 7967 * eax = method->clazz 7968 */ 7969.LOP_INVOKE_SUPER_RANGE_resolve: 7970 SPILL_TMP(%eax) # method->clazz 7971 movl %eax,OUT_ARG0(%esp) # arg0<- method->clazz 7972 movzwl 2(rPC),%ecx # ecx<- BBBB 7973 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- resolver method type 7974 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 7975 SPILL(rPC) 7976 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7977 UNSPILL(rPC) 7978 testl %eax,%eax # got null? 7979 movl %eax,%ecx # ecx<- resolved base method 7980 UNSPILL_TMP(%eax) # restore method->clazz 7981 jne .LOP_INVOKE_SUPER_RANGE_continue # good to go - continue 7982 jmp common_exceptionThrown # handle exception 7983 7984 /* 7985 * Throw a NoSuchMethodError with the method name as the message. 7986 * ecx = resolved base method 7987 */ 7988.LOP_INVOKE_SUPER_RANGE_nsm: 7989 movl offMethod_name(%ecx),%eax 7990 mov %eax,OUT_ARG1(%esp) 7991 jmp common_errNoSuchMethod 7992 7993/* continuation for OP_INVOKE_DIRECT_RANGE */ 7994 7995 /* 7996 * On entry: 7997 * TMP_SPILL <- "this" register 7998 * Things a bit ugly on this path, but it's the less 7999 * frequent one. We'll have to do some reloading. 8000 */ 8001.LOP_INVOKE_DIRECT_RANGE_resolve: 8002 SPILL_TMP(%ecx) 8003 GET_GLUE(%ecx) 8004 UNSPILL(rPC) 8005 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 8006 movzwl 2(rPC),%eax # reference (BBBB or CCCC) 8007 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8008 movl $METHOD_DIRECT,OUT_ARG2(%esp) 8009 movl %eax,OUT_ARG1(%esp) 8010 movl %ecx,OUT_ARG0(%esp) 8011 call dvmResolveMethod # eax<- call(clazz, ref, flags) 8012 UNSPILL_TMP(%ecx) 8013 testl %eax,%eax 8014 jne .LOP_INVOKE_DIRECT_RANGE_finish 8015 UNSPILL(rPC) 8016 jmp common_exceptionThrown 8017 8018/* continuation for OP_INVOKE_STATIC_RANGE */ 8019 8020.LOP_INVOKE_STATIC_RANGE_continue: 8021 movl $METHOD_STATIC,%eax 8022 movl %eax,OUT_ARG2(%esp) # arg2<- flags 8023 SPILL(rPC) 8024 call dvmResolveMethod # call(clazz,ref,flags) 8025 UNSPILL(rPC) 8026 testl %eax,%eax # got null? 8027 jne common_invokeMethodRange 8028 jmp common_exceptionThrown 8029 8030/* continuation for OP_INVOKE_INTERFACE_RANGE */ 8031 8032.LOP_INVOKE_INTERFACE_RANGE_continue: 8033 call dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex) 8034 UNSPILL(rPC) 8035 testl %eax,%eax 8036 je common_exceptionThrown 8037 jmp common_invokeMethodRange 8038 8039/* continuation for OP_FLOAT_TO_INT */ 8040 8041 8042.LOP_FLOAT_TO_INT_continue: 8043 .if 0 8044 movl $0x80000000,%eax 8045 xorl 4(rFP,%ecx,4),%eax 8046 orl (rFP,%ecx,4),%eax 8047 .else 8048 cmpl $0x80000000,(rFP,%ecx,4) 8049 .endif 8050 je .LOP_FLOAT_TO_INT_special_case # fix up result 8051 8052.LOP_FLOAT_TO_INT_finish: 8053 ADVANCE_PC(1) 8054 GOTO_NEXT 8055 8056.LOP_FLOAT_TO_INT_special_case: 8057 fnstsw %ax 8058 sahf 8059 jp .LOP_FLOAT_TO_INT_isNaN 8060 adcl $-1,(rFP,%ecx,4) 8061 .if 0 8062 adcl $-1,4(rFP,%ecx,4) 8063 .endif 8064 jmp .LOP_FLOAT_TO_INT_finish 8065.LOP_FLOAT_TO_INT_isNaN: 8066 movl $0,(rFP,%ecx,4) 8067 .if 0 8068 movl $0,4(rFP,%ecx,4) 8069 .endif 8070 jmp .LOP_FLOAT_TO_INT_finish 8071 8072/* continuation for OP_FLOAT_TO_LONG */ 8073 8074 8075.LOP_FLOAT_TO_LONG_continue: 8076 .if 1 8077 movl $0x80000000,%eax 8078 xorl 4(rFP,%ecx,4),%eax 8079 orl (rFP,%ecx,4),%eax 8080 .else 8081 cmpl $0x80000000,(rFP,%ecx,4) 8082 .endif 8083 je .LOP_FLOAT_TO_LONG_special_case # fix up result 8084 8085.LOP_FLOAT_TO_LONG_finish: 8086 ADVANCE_PC(1) 8087 GOTO_NEXT 8088 8089.LOP_FLOAT_TO_LONG_special_case: 8090 fnstsw %ax 8091 sahf 8092 jp .LOP_FLOAT_TO_LONG_isNaN 8093 adcl $-1,(rFP,%ecx,4) 8094 .if 1 8095 adcl $-1,4(rFP,%ecx,4) 8096 .endif 8097 jmp .LOP_FLOAT_TO_LONG_finish 8098.LOP_FLOAT_TO_LONG_isNaN: 8099 movl $0,(rFP,%ecx,4) 8100 .if 1 8101 movl $0,4(rFP,%ecx,4) 8102 .endif 8103 jmp .LOP_FLOAT_TO_LONG_finish 8104 8105/* continuation for OP_DOUBLE_TO_INT */ 8106 8107 8108.LOP_DOUBLE_TO_INT_continue: 8109 .if 0 8110 movl $0x80000000,%eax 8111 xorl 4(rFP,%ecx,4),%eax 8112 orl (rFP,%ecx,4),%eax 8113 .else 8114 cmpl $0x80000000,(rFP,%ecx,4) 8115 .endif 8116 je .LOP_DOUBLE_TO_INT_special_case # fix up result 8117 8118.LOP_DOUBLE_TO_INT_finish: 8119 ADVANCE_PC(1) 8120 GOTO_NEXT 8121 8122.LOP_DOUBLE_TO_INT_special_case: 8123 fnstsw %ax 8124 sahf 8125 jp .LOP_DOUBLE_TO_INT_isNaN 8126 adcl $-1,(rFP,%ecx,4) 8127 .if 0 8128 adcl $-1,4(rFP,%ecx,4) 8129 .endif 8130 jmp .LOP_DOUBLE_TO_INT_finish 8131.LOP_DOUBLE_TO_INT_isNaN: 8132 movl $0,(rFP,%ecx,4) 8133 .if 0 8134 movl $0,4(rFP,%ecx,4) 8135 .endif 8136 jmp .LOP_DOUBLE_TO_INT_finish 8137 8138/* continuation for OP_DOUBLE_TO_LONG */ 8139 8140 8141.LOP_DOUBLE_TO_LONG_continue: 8142 .if 1 8143 movl $0x80000000,%eax 8144 xorl 4(rFP,%ecx,4),%eax 8145 orl (rFP,%ecx,4),%eax 8146 .else 8147 cmpl $0x80000000,(rFP,%ecx,4) 8148 .endif 8149 je .LOP_DOUBLE_TO_LONG_special_case # fix up result 8150 8151.LOP_DOUBLE_TO_LONG_finish: 8152 ADVANCE_PC(1) 8153 GOTO_NEXT 8154 8155.LOP_DOUBLE_TO_LONG_special_case: 8156 fnstsw %ax 8157 sahf 8158 jp .LOP_DOUBLE_TO_LONG_isNaN 8159 adcl $-1,(rFP,%ecx,4) 8160 .if 1 8161 adcl $-1,4(rFP,%ecx,4) 8162 .endif 8163 jmp .LOP_DOUBLE_TO_LONG_finish 8164.LOP_DOUBLE_TO_LONG_isNaN: 8165 movl $0,(rFP,%ecx,4) 8166 .if 1 8167 movl $0,4(rFP,%ecx,4) 8168 .endif 8169 jmp .LOP_DOUBLE_TO_LONG_finish 8170 8171/* continuation for OP_DIV_INT */ 8172.LOP_DIV_INT_continue_div: 8173 cltd 8174 idivl %ecx 8175.LOP_DIV_INT_finish_div: 8176 movzbl rINST_HI,%ecx # ecl<- AA 8177 SET_VREG(%eax,%ecx) 8178 UNSPILL(rPC) 8179 FETCH_INST_WORD(2) 8180 ADVANCE_PC(2) 8181 GOTO_NEXT 8182 8183/* continuation for OP_REM_INT */ 8184.LOP_REM_INT_continue_div: 8185 cltd 8186 idivl %ecx 8187.LOP_REM_INT_finish_div: 8188 movzbl rINST_HI,%ecx # ecl<- AA 8189 SET_VREG(%edx,%ecx) 8190 UNSPILL(rPC) 8191 FETCH_INST_WORD(2) 8192 ADVANCE_PC(2) 8193 GOTO_NEXT 8194 8195/* continuation for OP_MUL_LONG */ 8196 8197.LOP_MUL_LONG_continue: 8198 leal (%ecx,%edx),%edx # full result now in %edx:%eax 8199 movzbl rINST_HI,%ecx # ecx<- A 8200 movl %edx,4(rFP,%ecx,4) # v[B+1]<- %edx 8201 UNSPILL(rPC) # restore rPC/%edx 8202 FETCH_INST_WORD(2) 8203 UNSPILL(rIBASE) 8204 movl %eax,(rFP,%ecx,4) # v[B]<- %eax 8205 ADVANCE_PC(2) 8206 GOTO_NEXT 8207 8208/* continuation for OP_DIV_LONG */ 8209 8210.LOP_DIV_LONG_continue: 8211 call __divdi3 8212.LOP_DIV_LONG_finish: 8213 movzbl rINST_HI,%ecx 8214 SET_VREG_WORD(rPC,%ecx,1) 8215 UNSPILL(rPC) 8216 SET_VREG_WORD(%eax,%ecx,0) 8217 FETCH_INST_WORD(2) 8218 ADVANCE_PC(2) 8219 GOTO_NEXT 8220 8221.LOP_DIV_LONG_check_zero: 8222 testl rPC,rPC 8223 jne .LOP_DIV_LONG_notSpecial 8224 UNSPILL(rPC) 8225 jmp common_errDivideByZero 8226.LOP_DIV_LONG_check_neg1: 8227 testl rPC,%eax 8228 jne .LOP_DIV_LONG_notSpecial 8229 GET_VREG_WORD(rPC,%ecx,0) 8230 GET_VREG_WORD(%ecx,%ecx,1) 8231 testl rPC,rPC 8232 jne .LOP_DIV_LONG_notSpecial1 8233 cmpl $0x80000000,%ecx 8234 jne .LOP_DIV_LONG_notSpecial1 8235 /* minint / -1, return minint on div, 0 on rem */ 8236 xorl %eax,%eax 8237 movl $0x80000000,%edx 8238 jmp .LOP_DIV_LONG_finish 8239 8240/* continuation for OP_REM_LONG */ 8241 8242.LOP_REM_LONG_continue: 8243 call __moddi3 8244.LOP_REM_LONG_finish: 8245 movzbl rINST_HI,%ecx 8246 SET_VREG_WORD(rPC,%ecx,1) 8247 UNSPILL(rPC) 8248 SET_VREG_WORD(%eax,%ecx,0) 8249 FETCH_INST_WORD(2) 8250 ADVANCE_PC(2) 8251 GOTO_NEXT 8252 8253.LOP_REM_LONG_check_zero: 8254 testl rPC,rPC 8255 jne .LOP_REM_LONG_notSpecial 8256 UNSPILL(rPC) 8257 jmp common_errDivideByZero 8258.LOP_REM_LONG_check_neg1: 8259 testl rPC,%eax 8260 jne .LOP_REM_LONG_notSpecial 8261 GET_VREG_WORD(rPC,%ecx,0) 8262 GET_VREG_WORD(%ecx,%ecx,1) 8263 testl rPC,rPC 8264 jne .LOP_REM_LONG_notSpecial1 8265 cmpl $0x80000000,%ecx 8266 jne .LOP_REM_LONG_notSpecial1 8267 /* minint / -1, return minint on div, 0 on rem */ 8268 xorl %eax,%eax 8269 movl $0,%edx 8270 jmp .LOP_REM_LONG_finish 8271 8272/* continuation for OP_SHL_LONG */ 8273 8274.LOP_SHL_LONG_finish: 8275 SET_VREG_WORD(%eax,%ecx,0) # v[AA+0]<- %eax 8276 ADVANCE_PC(2) 8277 GOTO_NEXT 8278 8279/* continuation for OP_SHR_LONG */ 8280 8281 8282.LOP_SHR_LONG_finish: 8283 SET_VREG_WORD(%eax,%ecx,0) # v[AA+0]<- eax 8284 ADVANCE_PC(2) 8285 GOTO_NEXT 8286 8287/* continuation for OP_USHR_LONG */ 8288 8289 8290.LOP_USHR_LONG_finish: 8291 SET_VREG_WORD(%eax,%ecx,0) # v[BB+0]<- eax 8292 FETCH_INST_WORD(2) 8293 ADVANCE_PC(2) 8294 GOTO_NEXT 8295 8296/* continuation for OP_DIV_INT_2ADDR */ 8297.LOP_DIV_INT_2ADDR_continue_div2addr: 8298 cltd 8299 idivl %ecx 8300.LOP_DIV_INT_2ADDR_finish_div2addr: 8301 SET_VREG(%eax,rINST_FULL) 8302 UNSPILL(rPC) 8303 FETCH_INST_WORD(1) 8304 ADVANCE_PC(1) 8305 GOTO_NEXT 8306 8307/* continuation for OP_REM_INT_2ADDR */ 8308.LOP_REM_INT_2ADDR_continue_div2addr: 8309 cltd 8310 idivl %ecx 8311.LOP_REM_INT_2ADDR_finish_div2addr: 8312 SET_VREG(%edx,rINST_FULL) 8313 UNSPILL(rPC) 8314 FETCH_INST_WORD(1) 8315 ADVANCE_PC(1) 8316 GOTO_NEXT 8317 8318/* continuation for OP_MUL_LONG_2ADDR */ 8319 8320.LOP_MUL_LONG_2ADDR_continue: 8321 leal (%ecx,%edx),%edx # full result now in %edx:%eax 8322 movl %edx,4(rIBASE) # v[A+1]<- %edx 8323 UNSPILL(rPC) # restore rPC/%edx 8324 FETCH_INST_WORD(1) 8325 movl %eax,(rIBASE) # v[A]<- %eax 8326 UNSPILL(rFP) 8327 UNSPILL(rIBASE) 8328 ADVANCE_PC(1) 8329 GOTO_NEXT 8330 8331/* continuation for OP_DIV_LONG_2ADDR */ 8332 8333.LOP_DIV_LONG_2ADDR_continue: 8334 movl %eax,OUT_ARG3(%esp) 8335 movl rPC,OUT_ARG0(%esp) 8336 movl %ecx,OUT_ARG1(%esp) 8337 call __divdi3 8338.LOP_DIV_LONG_2ADDR_finish: 8339 movl rINST_FULL,%ecx 8340 SET_VREG_WORD(rPC,%ecx,1) 8341 UNSPILL(rPC) 8342 SET_VREG_WORD(%eax,%ecx,0) 8343 FETCH_INST_WORD(1) 8344 ADVANCE_PC(1) 8345 GOTO_NEXT 8346 8347.LOP_DIV_LONG_2ADDR_check_zero: 8348 testl rPC,rPC 8349 jne .LOP_DIV_LONG_2ADDR_notSpecial 8350 UNSPILL(rPC) 8351 jmp common_errDivideByZero 8352.LOP_DIV_LONG_2ADDR_check_neg1: 8353 testl rPC,%eax 8354 jne .LOP_DIV_LONG_2ADDR_notSpecial 8355 GET_VREG_WORD(rPC,rINST_FULL,0) 8356 GET_VREG_WORD(%ecx,rINST_FULL,1) 8357 testl rPC,rPC 8358 jne .LOP_DIV_LONG_2ADDR_notSpecial1 8359 cmpl $0x80000000,%ecx 8360 jne .LOP_DIV_LONG_2ADDR_notSpecial1 8361 /* minint / -1, return minint on div, 0 on rem */ 8362 xorl %eax,%eax 8363 movl $0x80000000,%edx 8364 jmp .LOP_DIV_LONG_2ADDR_finish 8365 8366/* continuation for OP_REM_LONG_2ADDR */ 8367 8368.LOP_REM_LONG_2ADDR_continue: 8369 movl %eax,OUT_ARG3(%esp) 8370 movl rPC,OUT_ARG0(%esp) 8371 movl %ecx,OUT_ARG1(%esp) 8372 call __moddi3 8373.LOP_REM_LONG_2ADDR_finish: 8374 movl rINST_FULL,%ecx 8375 SET_VREG_WORD(rPC,%ecx,1) 8376 UNSPILL(rPC) 8377 SET_VREG_WORD(%eax,%ecx,0) 8378 FETCH_INST_WORD(1) 8379 ADVANCE_PC(1) 8380 GOTO_NEXT 8381 8382.LOP_REM_LONG_2ADDR_check_zero: 8383 testl rPC,rPC 8384 jne .LOP_REM_LONG_2ADDR_notSpecial 8385 UNSPILL(rPC) 8386 jmp common_errDivideByZero 8387.LOP_REM_LONG_2ADDR_check_neg1: 8388 testl rPC,%eax 8389 jne .LOP_REM_LONG_2ADDR_notSpecial 8390 GET_VREG_WORD(rPC,rINST_FULL,0) 8391 GET_VREG_WORD(%ecx,rINST_FULL,1) 8392 testl rPC,rPC 8393 jne .LOP_REM_LONG_2ADDR_notSpecial1 8394 cmpl $0x80000000,%ecx 8395 jne .LOP_REM_LONG_2ADDR_notSpecial1 8396 /* minint / -1, return minint on div, 0 on rem */ 8397 xorl %eax,%eax 8398 movl $0,%edx 8399 jmp .LOP_REM_LONG_2ADDR_finish 8400 8401/* continuation for OP_SHL_LONG_2ADDR */ 8402 8403 8404.LOP_SHL_LONG_2ADDR_finish: 8405 SET_VREG_WORD(%eax,rINST_FULL,0) # v[AA+0]<- eax 8406 FETCH_INST_WORD(1) 8407 ADVANCE_PC(1) 8408 GOTO_NEXT 8409 8410/* continuation for OP_SHR_LONG_2ADDR */ 8411 8412 8413.LOP_SHR_LONG_2ADDR_finish: 8414 SET_VREG_WORD(%eax,rINST_FULL,0) # v[AA+0]<- eax 8415 FETCH_INST_WORD(1) 8416 ADVANCE_PC(1) 8417 GOTO_NEXT 8418 8419/* continuation for OP_USHR_LONG_2ADDR */ 8420 8421 8422.LOP_USHR_LONG_2ADDR_finish: 8423 SET_VREG_WORD(%eax,rINST_FULL,0) # v[AA+0]<- eax 8424 FETCH_INST_WORD(1) 8425 ADVANCE_PC(1) 8426 GOTO_NEXT 8427 8428/* continuation for OP_DIV_INT_LIT16 */ 8429.LOP_DIV_INT_LIT16_continue_div: 8430 cltd 8431 idivl %ecx 8432.LOP_DIV_INT_LIT16_finish_div: 8433 SET_VREG(%eax,rINST_FULL) 8434 UNSPILL(rPC) 8435 FETCH_INST_WORD(2) 8436 ADVANCE_PC(2) 8437 GOTO_NEXT 8438 8439/* continuation for OP_REM_INT_LIT16 */ 8440.LOP_REM_INT_LIT16_continue_div: 8441 cltd 8442 idivl %ecx 8443.LOP_REM_INT_LIT16_finish_div: 8444 SET_VREG(%edx,rINST_FULL) 8445 UNSPILL(rPC) 8446 FETCH_INST_WORD(2) 8447 ADVANCE_PC(2) 8448 GOTO_NEXT 8449 8450/* continuation for OP_DIV_INT_LIT8 */ 8451.LOP_DIV_INT_LIT8_continue_div: 8452 cltd 8453 idivl %ecx 8454.LOP_DIV_INT_LIT8_finish_div: 8455 SET_VREG(%eax,rINST_FULL) 8456 UNSPILL(rPC) 8457 FETCH_INST_WORD(2) 8458 ADVANCE_PC(2) 8459 GOTO_NEXT 8460 8461/* continuation for OP_REM_INT_LIT8 */ 8462.LOP_REM_INT_LIT8_continue_div: 8463 cltd 8464 idivl %ecx 8465.LOP_REM_INT_LIT8_finish_div: 8466 SET_VREG(%edx,rINST_FULL) 8467 UNSPILL(rPC) 8468 FETCH_INST_WORD(2) 8469 ADVANCE_PC(2) 8470 GOTO_NEXT 8471 8472/* continuation for OP_IGET_VOLATILE */ 8473 8474 8475.LOP_IGET_VOLATILE_resolve: 8476 EXPORT_PC() 8477 SPILL(rPC) 8478 movl offGlue_method(rIBASE),rPC # rPC<- current method 8479 UNSPILL(rIBASE) 8480 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 8481 SPILL_TMP(%ecx) # save object pointer across call 8482 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 8483 call dvmResolveInstField # ... to dvmResolveInstField 8484 UNSPILL_TMP(%ecx) 8485 UNSPILL(rPC) 8486 testl %eax,%eax # ... which returns InstrField ptr 8487 jne .LOP_IGET_VOLATILE_finish 8488 jmp common_exceptionThrown 8489 8490.LOP_IGET_VOLATILE_finish: 8491 /* 8492 * Currently: 8493 * eax holds resolved field 8494 * ecx holds object 8495 * rIBASE is scratch, but needs to be unspilled 8496 * rINST_FULL holds A 8497 */ 8498 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 8499 UNSPILL(rIBASE) 8500 testl %ecx,%ecx # object null? 8501 je common_errNullObject # object was null 8502 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 8503 movl rINST_FULL,%eax # eax<- A 8504 FETCH_INST_WORD(2) 8505 SET_VREG(%ecx,%eax) 8506 ADVANCE_PC(2) 8507 GOTO_NEXT 8508 8509/* continuation for OP_IPUT_VOLATILE */ 8510 8511 8512.LOP_IPUT_VOLATILE_resolve: 8513 EXPORT_PC() 8514 SPILL(rPC) 8515 movl offGlue_method(rIBASE),rPC # rPC<- current method 8516 UNSPILL(rIBASE) 8517 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 8518 SPILL_TMP(%ecx) # save object pointer across call 8519 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 8520 call dvmResolveInstField # ... to dvmResolveInstField 8521 UNSPILL_TMP(%ecx) 8522 UNSPILL(rPC) 8523 testl %eax,%eax # ... which returns InstrField ptr 8524 jne .LOP_IPUT_VOLATILE_finish 8525 jmp common_exceptionThrown 8526 8527.LOP_IPUT_VOLATILE_finish: 8528 /* 8529 * Currently: 8530 * eax holds resolved field 8531 * ecx holds object 8532 * rIBASE is scratch, but needs to be unspilled 8533 * rINST_FULL holds A 8534 */ 8535 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 8536 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 8537 UNSPILL(rIBASE) 8538 testl %ecx,%ecx # object null? 8539 je common_errNullObject # object was null 8540 movl rINST_FULL,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 8541 FETCH_INST_WORD(2) 8542 ADVANCE_PC(2) 8543 GOTO_NEXT 8544 8545/* continuation for OP_SGET_VOLATILE */ 8546 8547 /* 8548 * Go resolve the field 8549 */ 8550.LOP_SGET_VOLATILE_resolve: 8551 GET_GLUE(%ecx) 8552 movzwl 2(rPC),%eax # eax<- field ref BBBB 8553 movl offGlue_method(%ecx),%ecx # ecx<- current method 8554 EXPORT_PC() # could throw, need to export 8555 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8556 SPILL(rPC) 8557 movl %eax,OUT_ARG1(%esp) 8558 movl %ecx,OUT_ARG0(%esp) 8559 call dvmResolveStaticField # eax<- resolved StaticField ptr 8560 UNSPILL(rPC) 8561 testl %eax,%eax 8562 jne .LOP_SGET_VOLATILE_finish # success, continue 8563 jmp common_exceptionThrown # no, handle exception 8564 8565/* continuation for OP_SPUT_VOLATILE */ 8566 8567 /* 8568 * Go resolve the field 8569 */ 8570.LOP_SPUT_VOLATILE_resolve: 8571 GET_GLUE(%ecx) 8572 movzwl 2(rPC),%eax # eax<- field ref BBBB 8573 movl offGlue_method(%ecx),%ecx # ecx<- current method 8574 EXPORT_PC() # could throw, need to export 8575 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8576 SPILL(rPC) 8577 movl %eax,OUT_ARG1(%esp) 8578 movl %ecx,OUT_ARG0(%esp) 8579 call dvmResolveStaticField # eax<- resolved StaticField ptr 8580 UNSPILL(rPC) 8581 testl %eax,%eax 8582 jne .LOP_SPUT_VOLATILE_finish # success, continue 8583 jmp common_exceptionThrown # no, handle exception 8584 8585/* continuation for OP_IGET_OBJECT_VOLATILE */ 8586 8587 8588.LOP_IGET_OBJECT_VOLATILE_resolve: 8589 EXPORT_PC() 8590 SPILL(rPC) 8591 movl offGlue_method(rIBASE),rPC # rPC<- current method 8592 UNSPILL(rIBASE) 8593 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 8594 SPILL_TMP(%ecx) # save object pointer across call 8595 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 8596 call dvmResolveInstField # ... to dvmResolveInstField 8597 UNSPILL_TMP(%ecx) 8598 UNSPILL(rPC) 8599 testl %eax,%eax # ... which returns InstrField ptr 8600 jne .LOP_IGET_OBJECT_VOLATILE_finish 8601 jmp common_exceptionThrown 8602 8603.LOP_IGET_OBJECT_VOLATILE_finish: 8604 /* 8605 * Currently: 8606 * eax holds resolved field 8607 * ecx holds object 8608 * rIBASE is scratch, but needs to be unspilled 8609 * rINST_FULL holds A 8610 */ 8611 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 8612 UNSPILL(rIBASE) 8613 testl %ecx,%ecx # object null? 8614 je common_errNullObject # object was null 8615 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 8616 movl rINST_FULL,%eax # eax<- A 8617 FETCH_INST_WORD(2) 8618 SET_VREG(%ecx,%eax) 8619 ADVANCE_PC(2) 8620 GOTO_NEXT 8621 8622/* continuation for OP_EXECUTE_INLINE */ 8623 8624.LOP_EXECUTE_INLINE_continue: 8625 /* 8626 * Extract args, call function. 8627 * ecx = #of args (0-4) 8628 * eax = call index 8629 * @esp = return addr 8630 * esp is -4 from normal 8631 * 8632 * Go ahead and load all 4 args, even if not used. 8633 */ 8634 movzwl 4(rPC),rPC 8635 8636 movl $0xf,%ecx 8637 andl rPC,%ecx 8638 GET_VREG(%ecx,%ecx) 8639 sarl $4,rPC 8640 movl %ecx,4+OUT_ARG0(%esp) 8641 8642 movl $0xf,%ecx 8643 andl rPC,%ecx 8644 GET_VREG(%ecx,%ecx) 8645 sarl $4,rPC 8646 movl %ecx,4+OUT_ARG1(%esp) 8647 8648 movl $0xf,%ecx 8649 andl rPC,%ecx 8650 GET_VREG(%ecx,%ecx) 8651 sarl $4,rPC 8652 movl %ecx,4+OUT_ARG2(%esp) 8653 8654 movl $0xf,%ecx 8655 andl rPC,%ecx 8656 GET_VREG(%ecx,%ecx) 8657 sarl $4,rPC 8658 movl %ecx,4+OUT_ARG3(%esp) 8659 8660 sall $4,%eax # index *= sizeof(table entry) 8661 jmp *gDvmInlineOpsTable(%eax) 8662 # will return to caller of .LOP_EXECUTE_INLINE_continue 8663 8664/* continuation for OP_IPUT_OBJECT_QUICK */ 8665 8666.LOP_IPUT_OBJECT_QUICK_finish: 8667 testl rINST_FULL,rINST_FULL # did we store null? 8668 FETCH_INST_WORD(2) 8669 movl offGlue_cardTable(%eax),%eax # get card table base 8670 je 1f # skip card mark if null store 8671 shrl $GC_CARD_SHIFT,%ecx # object head to card number 8672 movb %al,(%eax,%ecx) # mark card based on object head 86731: 8674 ADVANCE_PC(2) 8675 GOTO_NEXT 8676 8677/* continuation for OP_IPUT_OBJECT_VOLATILE */ 8678 8679 8680.LOP_IPUT_OBJECT_VOLATILE_resolve: 8681 EXPORT_PC() 8682 SPILL(rPC) 8683 movl offGlue_method(rIBASE),rPC # rPC<- current method 8684 UNSPILL(rIBASE) 8685 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 8686 SPILL_TMP(%ecx) # save object pointer across call 8687 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 8688 call dvmResolveInstField # ... to dvmResolveInstField 8689 UNSPILL_TMP(%ecx) 8690 UNSPILL(rPC) 8691 testl %eax,%eax # ... which returns InstrField ptr 8692 jne .LOP_IPUT_OBJECT_VOLATILE_finish 8693 jmp common_exceptionThrown 8694 8695.LOP_IPUT_OBJECT_VOLATILE_finish: 8696 /* 8697 * Currently: 8698 * eax holds resolved field 8699 * ecx holds object 8700 * rIBASE is scratch, but needs to be unspilled 8701 * rINST_FULL holds A 8702 */ 8703 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 8704 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 8705 UNSPILL(rIBASE) 8706 testl %ecx,%ecx # object null? 8707 je common_errNullObject # object was null 8708 movl rINST_FULL,(%ecx,%eax) # obj.field <- v[A](8/16/32 bits) 8709 GET_GLUE(%eax) 8710 testl rINST_FULL,rINST_FULL # stored a NULL? 8711 movl offGlue_cardTable(%eax),%eax # get card table base 8712 FETCH_INST_WORD(2) 8713 je 1f # skip card mark if null store 8714 shrl $GC_CARD_SHIFT,%ecx # object head to card number 8715 movb %al,(%eax,%ecx) # mark card using object head 87161: 8717 ADVANCE_PC(2) 8718 GOTO_NEXT 8719 8720/* continuation for OP_SGET_OBJECT_VOLATILE */ 8721 8722 /* 8723 * Go resolve the field 8724 */ 8725.LOP_SGET_OBJECT_VOLATILE_resolve: 8726 GET_GLUE(%ecx) 8727 movzwl 2(rPC),%eax # eax<- field ref BBBB 8728 movl offGlue_method(%ecx),%ecx # ecx<- current method 8729 EXPORT_PC() # could throw, need to export 8730 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8731 SPILL(rPC) 8732 movl %eax,OUT_ARG1(%esp) 8733 movl %ecx,OUT_ARG0(%esp) 8734 call dvmResolveStaticField # eax<- resolved StaticField ptr 8735 UNSPILL(rPC) 8736 testl %eax,%eax 8737 jne .LOP_SGET_OBJECT_VOLATILE_finish # success, continue 8738 jmp common_exceptionThrown # no, handle exception 8739 8740/* continuation for OP_SPUT_OBJECT_VOLATILE */ 8741 8742 8743.LOP_SPUT_OBJECT_VOLATILE_continue: 8744 movl %ecx,offStaticField_value(%eax) # do the store 8745 testl %ecx,%ecx # stored null object ptr? 8746 FETCH_INST_WORD(2) 8747 je 1f # skip card mark if null 8748 GET_GLUE(%ecx) 8749 movl offField_clazz(%eax),%eax # eax<- field->clazz 8750 movl offGlue_cardTable(%ecx),%ecx # get card table base 8751 shrl $GC_CARD_SHIFT,%eax # head to card number 8752 movb %cl,(%ecx,%eax) # mark card 87531: 8754 ADVANCE_PC(2) 8755 GOTO_NEXT 8756 8757.LOP_SPUT_OBJECT_VOLATILE_resolve: 8758 GET_GLUE(%ecx) 8759 movzwl 2(rPC),%eax # eax<- field ref BBBB 8760 movl offGlue_method(%ecx),%ecx # ecx<- current method 8761 EXPORT_PC() # could throw, need to export 8762 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8763 SPILL(rPC) 8764 movl %eax,OUT_ARG1(%esp) 8765 movl %ecx,OUT_ARG0(%esp) 8766 call dvmResolveStaticField # eax<- resolved StaticField ptr 8767 UNSPILL(rPC) 8768 testl %eax,%eax 8769 jne .LOP_SPUT_OBJECT_VOLATILE_finish # success, continue 8770 jmp common_exceptionThrown # no, handle exception 8771 8772 .size dvmAsmSisterStart, .-dvmAsmSisterStart 8773 .global dvmAsmSisterEnd 8774dvmAsmSisterEnd: 8775 8776/* File: x86/entry.S */ 8777/* 8778 * Copyright (C) 2008 The Android Open Source Project 8779 * 8780 * Licensed under the Apache License, Version 2.0 (the "License"); 8781 * you may not use this file except in compliance with the License. 8782 * You may obtain a copy of the License at 8783 * 8784 * http://www.apache.org/licenses/LICENSE-2.0 8785 * 8786 * Unless required by applicable law or agreed to in writing, software 8787 * distributed under the License is distributed on an "AS IS" BASIS, 8788 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8789 * See the License for the specific language governing permissions and 8790 * limitations under the License. 8791 */ 8792 8793 8794 .text 8795 .global dvmMterpStdRun 8796 .type dvmMterpStdRun, %function 8797/* 8798 * bool dvmMterpStdRun(MterpGlue* glue) 8799 * 8800 * Interpreter entry point. Returns changeInterp. 8801 * 8802 */ 8803dvmMterpStdRun: 8804 push %ebp 8805 movl %esp,%ebp 8806 push %edi 8807 push %esi 8808 push %ebx 8809 8810/* at this point, stack is misaligned by 1 word 8811 We're allocating spill space for 6 words, plus 8812 outgoing argument (5 words) and local variables 8813 (4 words) - 15 words or 60 bytes total. See 8814 diagram in header.S 8815*/ 8816 subl $60,%esp 8817 8818/* Set up "named" registers */ 8819 movl IN_ARG0(%ebp),%ecx 8820 movl %ecx,rGLUE_SPILL(%ebp) 8821 LOAD_PC_FROM_GLUE(%ecx) 8822 LOAD_FP_FROM_GLUE(%ecx) 8823 movl $dvmAsmInstructionStart,rIBASE 8824 8825/* Remember %esp for future "longjmp" */ 8826 movl %esp,offGlue_bailPtr(%ecx) 8827 8828/* How to start? */ 8829 movb offGlue_entryPoint(%ecx),%al 8830 8831/* Normal start? */ 8832 cmpb $kInterpEntryInstr,%al 8833 jne .Lnot_instr 8834 8835 /* Normal case: start executing the instruction at rPC */ 8836 FETCH_INST() 8837 GOTO_NEXT 8838 8839.Lnot_instr: 8840 /* Reset to normal case */ 8841 movb $kInterpEntryInstr,offGlue_entryPoint(%ecx) 8842 cmpb $kInterpEntryReturn,%al 8843 je common_returnFromMethod 8844 cmpb $kInterpEntryThrow,%al 8845 je common_exceptionThrown 8846 movzx %al,%eax 8847 movl %eax,OUT_ARG1(%esp) 8848 movl $.LstrBadEntryPoint,OUT_ARG0(%esp) 8849 call printf 8850 call dvmAbort 8851 /* Not reached */ 8852 8853 8854 .global dvmMterpStdBail 8855 .type dvmMterpStdBail, %function 8856/* 8857 * void dvmMterpStdBail(MterpGlue* glue, bool changeInterp) 8858 * 8859 * Restore the stack pointer and PC from the save point established on entry. 8860 * This is essentially the same as a longjmp, but should be cheaper. The 8861 * last instruction causes us to return to whoever called dvmMterpStdRun. 8862 * 8863 * We're not going to build a standard frame here, so the arg accesses will 8864 * look a little strange. 8865 * 8866 * On entry: 8867 * esp+4 (arg0) MterpGlue* glue 8868 * esp+8 (arg1) bool changeInterp 8869 */ 8870dvmMterpStdBail: 8871 movl 4(%esp),%ecx # grab glue 8872 movl 8(%esp),%eax # changeInterp to return reg 8873 movl offGlue_bailPtr(%ecx),%esp # Stack back to normal 8874 addl $60,%esp # Strip dvmMterpStdRun's frame 8875 pop %ebx 8876 pop %esi 8877 pop %edi 8878 pop %ebp 8879 ret # return to dvmMterpStdRun's caller 8880 8881 8882/* 8883 * Strings 8884 */ 8885 .section .rodata 8886.LstrBadEntryPoint: 8887 .asciz "Bad entry point %d\n" 8888 8889/* File: x86/footer.S */ 8890/* 8891 * Copyright (C) 2008 The Android Open Source Project 8892 * 8893 * Licensed under the Apache License, Version 2.0 (the "License"); 8894 * you may not use this file except in compliance with the License. 8895 * You may obtain a copy of the License at 8896 * 8897 * http://www.apache.org/licenses/LICENSE-2.0 8898 * 8899 * Unless required by applicable law or agreed to in writing, software 8900 * distributed under the License is distributed on an "AS IS" BASIS, 8901 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8902 * See the License for the specific language governing permissions and 8903 * limitations under the License. 8904 */ 8905/* 8906 * Common subroutines and data. 8907 */ 8908 8909/* 8910 * Common code when a backwards branch is taken 8911 * 8912 * On entry: 8913 * ebx (a.k.a. rINST_FULL) -> PC adjustment in 16-bit words 8914 */ 8915common_backwardBranch: 8916 GET_GLUE(%ecx) 8917 call common_periodicChecks # Note: expects rPC to be preserved 8918 ADVANCE_PC_INDEXED(rINST_FULL) 8919 FETCH_INST() 8920 GOTO_NEXT 8921 8922 8923 8924/* 8925 * Common code for method invocation with range. 8926 * 8927 * On entry: 8928 * eax = Method* methodToCall 8929 * rINST trashed, must reload 8930 */ 8931 8932common_invokeMethodRange: 8933.LinvokeNewRange: 8934 8935 /* 8936 * prepare to copy args to "outs" area of current frame 8937 */ 8938 8939 movzbl 1(rPC),rINST_FULL # rINST_FULL<- AA 8940 movzwl 4(rPC), %ecx # %ecx<- CCCC 8941 SPILL(rPC) 8942 SAVEAREA_FROM_FP(%edx,rFP) # %edx<- &StackSaveArea 8943 test rINST_FULL, rINST_FULL 8944 movl rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA 8945 jz .LinvokeArgsDone # no args; jump to args done 8946 8947 8948 /* 8949 * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, %edx=&outs (&stackSaveArea) 8950 * (very few methods have > 10 args; could unroll for common cases) 8951 */ 8952 8953 movl %ebx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- save %ebx 8954 lea (rFP, %ecx, 4), %ecx # %ecx<- &vCCCC 8955 shll $2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset 8956 subl LOCAL0_OFFSET(%ebp), %edx # %edx<- update &outs 8957 shrl $2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset 89581: 8959 movl (%ecx), %ebx # %ebx<- vCCCC 8960 lea 4(%ecx), %ecx # %ecx<- &vCCCC++ 8961 subl $1, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- LOCAL0_OFFSET-- 8962 movl %ebx, (%edx) # *outs<- vCCCC 8963 lea 4(%edx), %edx # outs++ 8964 jne 1b # loop if count (LOCAL0_OFFSET(%ebp)) not zero 8965 movl LOCAL1_OFFSET(%ebp), %ebx # %ebx<- restore %ebx 8966 jmp .LinvokeArgsDone # continue 8967 8968 /* 8969 * %eax is "Method* methodToCall", the method we're trying to call 8970 * prepare to copy args to "outs" area of current frame 8971 */ 8972 8973common_invokeMethodNoRange: 8974.LinvokeNewNoRange: 8975 movzbl 1(rPC),rINST_FULL # rINST_FULL<- BA 8976 SPILL(rPC) 8977 movl rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA 8978 shrl $4, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- B 8979 je .LinvokeArgsDone # no args; jump to args done 8980 movzwl 4(rPC), %ecx # %ecx<- GFED 8981 SAVEAREA_FROM_FP(%edx,rFP) # %edx<- &StackSaveArea 8982 8983 /* 8984 * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs 8985 */ 8986 8987.LinvokeNonRange: 8988 cmp $2, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 2 8989 movl %ecx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- GFED 8990 jl 1f # handle 1 arg 8991 je 2f # handle 2 args 8992 cmp $4, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 4 8993 jl 3f # handle 3 args 8994 je 4f # handle 4 args 89955: 8996 andl $15, rINST_FULL # rINST<- A 8997 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 8998 movl (rFP, rINST_FULL, 4), %ecx # %ecx<- vA 8999 movl %ecx, (%edx) # *outs<- vA 9000 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 90014: 9002 shr $12, %ecx # %ecx<- G 9003 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 9004 movl (rFP, %ecx, 4), %ecx # %ecx<- vG 9005 movl %ecx, (%edx) # *outs<- vG 9006 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 90073: 9008 and $0x0f00, %ecx # %ecx<- 0F00 9009 shr $8, %ecx # %ecx<- F 9010 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 9011 movl (rFP, %ecx, 4), %ecx # %ecx<- vF 9012 movl %ecx, (%edx) # *outs<- vF 9013 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 90142: 9015 and $0x00f0, %ecx # %ecx<- 00E0 9016 shr $4, %ecx # %ecx<- E 9017 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 9018 movl (rFP, %ecx, 4), %ecx # %ecx<- vE 9019 movl %ecx, (%edx) # *outs<- vE 9020 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 90211: 9022 and $0x000f, %ecx # %ecx<- 000D 9023 movl (rFP, %ecx, 4), %ecx # %ecx<- vD 9024 movl %ecx, -4(%edx) # *--outs<- vD 90250: 9026 9027 /* 9028 * %eax is "Method* methodToCall", the method we're trying to call 9029 * find space for the new stack frame, check for overflow 9030 */ 9031 9032.LinvokeArgsDone: 9033 movzwl offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize 9034 movzwl offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize 9035 movl %eax, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- methodToCall 9036 shl $2, %edx # %edx<- update offset 9037 SAVEAREA_FROM_FP(%eax,rFP) # %eax<- &StackSaveArea 9038 subl %edx, %eax # %eax<- newFP; (old savearea - regsSize) 9039 GET_GLUE(%edx) # %edx<- pMterpGlue 9040 movl %eax, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- &outs 9041 subl $sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP) 9042 movl offGlue_interpStackEnd(%edx), %edx # %edx<- glue->interpStackEnd 9043 movl %edx, LOCAL2_OFFSET(%ebp) # LOCAL2_OFFSET<- glue->interpStackEnd 9044 shl $2, %ecx # %ecx<- update offset for outsSize 9045 movl %eax, %edx # %edx<- newSaveArea 9046 sub %ecx, %eax # %eax<- bottom; (newSaveArea - outsSize) 9047 cmp LOCAL2_OFFSET(%ebp), %eax # compare interpStackEnd and bottom 9048 movl LOCAL0_OFFSET(%ebp), %eax # %eax<- restore methodToCall 9049 jl .LstackOverflow # handle frame overflow 9050 9051 /* 9052 * set up newSaveArea 9053 */ 9054 9055#ifdef EASY_GDB 9056 SAVEAREA_FROM_FP(%ecx,rFP) # %ecx<- &StackSaveArea 9057 movl %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs 9058#endif 9059 movl rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP 9060 movl rPC_SPILL(%ebp), %ecx 9061 movl %ecx, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC 9062 testl $ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call 9063 movl %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call 9064 jne .LinvokeNative # handle native call 9065 9066 /* 9067 * Update "glue" values for the new method 9068 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp 9069 */ 9070 9071 movl offMethod_clazz(%eax), %edx # %edx<- method->clazz 9072 GET_GLUE(%ecx) # %ecx<- pMterpGlue 9073 movl offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex 9074 movl %eax, offGlue_method(%ecx) # glue->method<- methodToCall 9075 movl %edx, offGlue_methodClassDex(%ecx) # glue->methodClassDex<- method->clazz->pDvmDex 9076 movl offMethod_insns(%eax), rPC # rPC<- methodToCall->insns 9077 movl offGlue_self(%ecx), %eax # %eax<- glue->self 9078 movl LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP 9079 movl rFP, offThread_curFrame(%eax) # glue->self->curFrame<- newFP 9080 FETCH_INST() 9081 GOTO_NEXT # jump to methodToCall->insns 9082 9083 /* 9084 * Prep for the native call 9085 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea 9086 */ 9087 9088.LinvokeNative: 9089 GET_GLUE(%ecx) # %ecx<- pMterpGlue 9090 movl %eax, OUT_ARG1(%esp) # push parameter methodToCall 9091 movl offGlue_self(%ecx), %ecx # %ecx<- glue->self 9092 movl offThread_jniLocal_topCookie(%ecx), %eax # %eax<- self->localRef->... 9093 movl %eax, offStackSaveArea_localRefCookie(%edx) # newSaveArea->localRefCookie<- top 9094 movl %edx, OUT_ARG4(%esp) # save newSaveArea 9095 movl LOCAL1_OFFSET(%ebp), %edx # %edx<- newFP 9096 movl %edx, offThread_curFrame(%ecx) # glue->self->curFrame<- newFP 9097 movl %ecx, OUT_ARG3(%esp) # save glue->self 9098 movl %ecx, OUT_ARG2(%esp) # push parameter glue->self 9099 GET_GLUE(%ecx) # %ecx<- pMterpGlue 9100 movl OUT_ARG1(%esp), %eax # %eax<- methodToCall 9101 lea offGlue_retval(%ecx), %ecx # %ecx<- &retval 9102 movl %ecx, OUT_ARG0(%esp) # push parameter pMterpGlue 9103 push %edx # push parameter newFP 9104 9105 call *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc 9106 lea 4(%esp), %esp 9107 movl OUT_ARG4(%esp), %ecx # %ecx<- newSaveArea 9108 movl OUT_ARG3(%esp), %eax # %eax<- glue->self 9109 movl offStackSaveArea_localRefCookie(%ecx), %edx # %edx<- old top 9110 cmp $0, offThread_exception(%eax) # check for exception 9111 movl rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP 9112 movl %edx, offThread_jniLocal_topCookie(%eax) # new top <- old top 9113 UNSPILL(rPC) 9114 jne common_exceptionThrown # handle exception 9115 FETCH_INST_WORD(3) 9116 ADVANCE_PC(3) 9117 GOTO_NEXT # jump to next instruction 9118 9119.LstackOverflow: # eax=methodToCall 9120 movl %eax, OUT_ARG1(%esp) # push parameter methodToCall 9121 GET_GLUE(%eax) # %eax<- pMterpGlue 9122 movl offGlue_self(%eax), %eax # %eax<- glue->self 9123 movl %eax, OUT_ARG0(%esp) # push parameter self 9124 call dvmHandleStackOverflow # call: (Thread* self, Method* meth) 9125 UNSPILL(rPC) # return: void 9126 jmp common_exceptionThrown # handle exception 9127 9128 9129/* 9130 * Common invoke code (old-style). 9131 * TUNING: Rewrite along lines of new armv5 code? 9132 * 9133 * On entry: 9134 * eax = Method* methodToCall 9135 * ecx = bool methodCallRange 9136 * rINST trashed, must reload 9137 */ 9138common_invokeOld: 9139 movl %ecx,OUT_ARG1(%esp) # arg1<- methodCallRange 9140 GET_GLUE(%ecx) 9141 movzwl (rPC),rINST_FULL # recover rINST 9142 movl %eax,OUT_ARG2(%esp) # arg2<- method 9143 movzwl 4(rPC),%eax # eax<- GFED or CCCC 9144 SAVE_PC_TO_GLUE(%ecx) 9145 SAVE_FP_TO_GLUE(%ecx) 9146 movzbl rINST_HI,rINST_FULL 9147 movl rINST_FULL,OUT_ARG3(%esp)# arg3<- AA 9148 movl %ecx,OUT_ARG0(%esp) # arg0<- GLUE 9149 movl %eax,OUT_ARG4(%esp) # arg4<- GFED/CCCC 9150 call dvmMterp_invokeMethod 9151 jmp common_resumeAfterGlueCall 9152 9153 9154/* 9155 * Do we need the thread to be suspended or have debugger/profiling activity? 9156 * 9157 * On entry: 9158 * ebx -> PC adjustment in 16-bit words (must be preserved) 9159 * ecx -> GLUE pointer 9160 * reentry type, e.g. kInterpEntryInstr stored in rGLUE->entryPoint 9161 * 9162 * Note: A call will normally kill %eax, rPC/%edx and %ecx. To 9163 * streamline the normal case, this routine will preserve rPC and 9164 * %ecx in addition to the normal caller save regs. The save/restore 9165 * is a bit ugly, but will happen in the relatively uncommon path. 9166 * TODO: Basic-block style Jit will need a hook here as well. Fold it into 9167 * the suspendCount check so we can get both in 1 shot. 9168 */ 9169common_periodicChecks: 9170 movl offGlue_pSelfSuspendCount(%ecx),%eax # eax <- &suspendCount 9171 cmpl $0,(%eax) 9172 jne 1f 9173 91746: 9175 movl offGlue_pDebuggerActive(%ecx),%eax # eax <- &DebuggerActive 9176 movl offGlue_pActiveProfilers(%ecx),%ecx # ecx <- &ActiveProfilers 9177 testl %eax,%eax # debugger enabled? 9178 je 2f 9179 movzbl (%eax),%eax # get active count 91802: 9181 orl (%ecx),%eax # eax <- debuggerActive | activeProfilers 9182 GET_GLUE(%ecx) # restore rGLUE 9183 jne 3f # one or both active - switch interp 9184 91855: 9186 ret 9187 9188 /* Check for suspend */ 91891: 9190 /* At this point, the return pointer to the caller of 9191 * common_periodicChecks is on the top of stack. We need to preserve 9192 * rPC(edx) and GLUE(ecx). We'll spill rPC, and reload GLUE. 9193 * The outgoing profile is: 9194 * bool dvmCheckSuspendPending(Thread* self) 9195 * Because we reached here via a call, go ahead and build a new frame. 9196 */ 9197 EXPORT_PC() # need for precise GC 9198 movl offGlue_self(%ecx),%eax # eax<- glue->self 9199 SPILL(rPC) # save edx 9200 push %ebp 9201 movl %esp,%ebp 9202 subl $24,%esp 9203 movl %eax,OUT_ARG0(%esp) 9204 call dvmCheckSuspendPending 9205 addl $24,%esp 9206 pop %ebp 9207 UNSPILL(rPC) 9208 GET_GLUE(%ecx) 9209 9210 /* 9211 * Need to check to see if debugger or profiler flags got set 9212 * while we were suspended. 9213 */ 9214 jmp 6b 9215 9216 /* Switch interpreters */ 9217 /* Note: %ebx contains the 16-bit word offset to be applied to rPC to 9218 * "complete" the interpretation of backwards branches. In effect, we 9219 * are completing the interpretation of the branch instruction here, 9220 * and the new interpreter will resume interpretation at the branch 9221 * target. However, a switch request recognized during the handling 9222 * of a return from method instruction results in an immediate abort, 9223 * and the new interpreter will resume by re-interpreting the return 9224 * instruction. 9225 */ 92263: 9227 leal (rPC,%ebx,2),rPC # adjust pc to show target 9228 GET_GLUE(%ecx) # bail expect GLUE already loaded 9229 movl $1,rINST_FULL # set changeInterp to true 9230 jmp common_gotoBail 9231 9232 9233/* 9234 * Common code for handling a return instruction 9235 */ 9236common_returnFromMethod: 9237 GET_GLUE(%ecx) 9238 /* Set entry mode in case we bail */ 9239 movb $kInterpEntryReturn,offGlue_entryPoint(%ecx) 9240 xorl rINST_FULL,rINST_FULL # zero offset in case we switch interps 9241 call common_periodicChecks # Note: expects %ecx to be preserved 9242 9243 SAVEAREA_FROM_FP(%eax,rFP) # eax<- saveArea (old) 9244 movl offStackSaveArea_prevFrame(%eax),rFP # rFP<- prevFrame 9245 movl (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST_FULL 9246 cmpl $0,rINST_FULL # break? 9247 je common_gotoBail # break frame, bail out completely 9248 9249 movl offStackSaveArea_savedPc(%eax),rPC # pc<- saveArea->savedPC 9250 movl offGlue_self(%ecx),%eax # eax<- self 9251 movl rINST_FULL,offGlue_method(%ecx) # glue->method = newSave->meethod 9252 movl rFP,offThread_curFrame(%eax) # self->curFrame = fp 9253 movl offMethod_clazz(rINST_FULL),%eax # eax<- method->clazz 9254 FETCH_INST_WORD(3) 9255 movl offClassObject_pDvmDex(%eax),%eax # eax<- method->clazz->pDvmDex 9256 ADVANCE_PC(3) 9257 movl %eax,offGlue_methodClassDex(%ecx) 9258 /* not bailing - restore entry mode to default */ 9259 movb $kInterpEntryInstr,offGlue_entryPoint(%ecx) 9260 GOTO_NEXT 9261 9262/* 9263 * Prepare to strip the current frame and "longjump" back to caller of 9264 * dvmMterpStdRun. 9265 * 9266 * on entry: 9267 * rINST_FULL holds changeInterp 9268 * ecx holds glue pointer 9269 * 9270 * expected profile: dvmMterpStdBail(MterpGlue *glue, bool changeInterp) 9271 */ 9272common_gotoBail: 9273 SAVE_PC_TO_GLUE(%ecx) # export state to glue 9274 SAVE_FP_TO_GLUE(%ecx) 9275 movl %ecx,OUT_ARG0(%esp) # glue in arg0 9276 movl rINST_FULL,OUT_ARG1(%esp) # changeInterp in arg1 9277 call dvmMterpStdBail # bail out.... 9278 9279 9280/* 9281 * After returning from a "glued" function, pull out the updated values 9282 * and start executing at the next instruction. 9283 */ 9284 common_resumeAfterGlueCall: 9285 GET_GLUE(%ecx) 9286 LOAD_PC_FROM_GLUE(%ecx) 9287 LOAD_FP_FROM_GLUE(%ecx) 9288 FETCH_INST() 9289 GOTO_NEXT 9290 9291/* 9292 * Integer divide or mod by zero 9293 */ 9294common_errDivideByZero: 9295 EXPORT_PC() 9296 movl $.LstrArithmeticException,%eax 9297 movl %eax,OUT_ARG0(%esp) 9298 movl $.LstrDivideByZero,%eax 9299 movl %eax,OUT_ARG1(%esp) 9300 SPILL(rPC) 9301 call dvmThrowException 9302 UNSPILL(rPC) 9303 jmp common_exceptionThrown 9304 9305/* 9306 * Attempt to allocate an array with a negative size. 9307 */ 9308common_errNegativeArraySize: 9309 EXPORT_PC() 9310 movl $.LstrNegativeArraySizeException,%eax 9311 movl %eax,OUT_ARG0(%esp) 9312 xorl %eax,%eax 9313 movl %eax,OUT_ARG1(%esp) 9314 SPILL(rPC) 9315 call dvmThrowException 9316 UNSPILL(rPC) 9317 jmp common_exceptionThrown 9318 9319/* 9320 * Attempt to allocate an array with a negative size. 9321 */ 9322common_errNoSuchMethod: 9323 9324 EXPORT_PC() 9325 movl $.LstrNoSuchMethodError,%eax 9326 movl %eax,OUT_ARG0(%esp) 9327 xorl %eax,%eax 9328 movl %eax,OUT_ARG1(%esp) 9329 SPILL(rPC) 9330 call dvmThrowException 9331 UNSPILL(rPC) 9332 jmp common_exceptionThrown 9333 9334/* 9335 * Hit a null object when we weren't expecting one. Export the PC, throw a 9336 * NullPointerException and goto the exception processing code. 9337 */ 9338common_errNullObject: 9339 EXPORT_PC() 9340 movl $.LstrNullPointerException,%eax 9341 movl %eax,OUT_ARG0(%esp) 9342 xorl %eax,%eax 9343 movl %eax,OUT_ARG1(%esp) 9344 SPILL(rPC) 9345 call dvmThrowException 9346 UNSPILL(rPC) 9347 jmp common_exceptionThrown 9348 9349/* 9350 * Array index exceeds max. 9351 */ 9352common_errArrayIndex: 9353 EXPORT_PC() 9354 movl $.LstrArrayIndexException,%eax 9355 movl %eax,OUT_ARG0(%esp) 9356 xorl %eax,%eax 9357 movl %eax,OUT_ARG1(%esp) 9358 SPILL(rPC) 9359 call dvmThrowException 9360 UNSPILL(rPC) 9361 jmp common_exceptionThrown 9362/* 9363 * Invalid array value. 9364 */ 9365common_errArrayStore: 9366 EXPORT_PC() 9367 movl $.LstrArrayStoreException,%eax 9368 movl %eax,OUT_ARG0(%esp) 9369 xorl %eax,%eax 9370 movl %eax,OUT_ARG1(%esp) 9371 SPILL(rPC) 9372 call dvmThrowException 9373 UNSPILL(rPC) 9374 jmp common_exceptionThrown 9375 9376/* 9377 * Somebody has thrown an exception. Handle it. 9378 * 9379 * If the exception processing code returns to us (instead of falling 9380 * out of the interpreter), continue with whatever the next instruction 9381 * now happens to be. 9382 * 9383 * This does not return. 9384 */ 9385common_exceptionThrown: 9386 GET_GLUE(%ecx) 9387 SAVE_PC_TO_GLUE(%ecx) 9388 SAVE_FP_TO_GLUE(%ecx) 9389 movl %ecx,OUT_ARG0(%esp) 9390 call dvmMterp_exceptionThrown 9391 jmp common_resumeAfterGlueCall 9392 9393common_abort: 9394 movl $0xdeadf00d,%eax 9395 call *%eax 9396 9397 9398/* 9399 * Strings 9400 */ 9401 9402 .section .rodata 9403.LstrNullPointerException: 9404 .asciz "Ljava/lang/NullPointerException;" 9405.LstrArithmeticException: 9406 .asciz "Ljava/lang/ArithmeticException;" 9407.LstrDivideByZero: 9408 .asciz "divide by zero" 9409.LstrArrayIndexException: 9410 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 9411.LstrArrayStoreException: 9412 .asciz "Ljava/lang/ArrayStoreException;" 9413.LstrNegativeArraySizeException: 9414 .asciz "Ljava/lang/NegativeArraySizeException;" 9415.LstrInstantiationError: 9416 .asciz "Ljava/lang/InstantiationError;" 9417.LstrClassCastException: 9418 .asciz "Ljava/lang/ClassCastException;" 9419.LstrNoSuchMethodError: 9420 .asciz "Ljava/lang/NoSuchMethodError;" 9421.LstrInternalError: 9422 .asciz "Ljava/lang/InternalError;" 9423.LstrFilledNewArrayNotImpl: 9424 .asciz "filled-new-array only implemented for 'int'" 9425 9426