InterpAsm-x86.S revision c35a2ef53d0cccd6f924eeba36633220ec67c32e
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/* File: x86/OP_IPUT.S */ 2225 2226 /* 2227 * General 32-bit instance field put. 2228 * 2229 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2230 */ 2231 /* op vA, vB, field@CCCC */ 2232 GET_GLUE(%ecx) 2233 SPILL(rIBASE) # need another reg 2234 movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC 2235 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2236 movzbl rINST_HI,%ecx # ecx<- BA 2237 sarl $4,%ecx # ecx<- B 2238 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2239 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 2240 andb $0xf,rINST_LO # rINST_FULL<- A 2241 GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr 2242 movl (%eax,rIBASE,4),%eax # resolved entry 2243 testl %eax,%eax # is resolved entry null? 2244 jne .LOP_IPUT_OBJECT_finish # no, already resolved 2245 movl rIBASE,OUT_ARG1(%esp) 2246 GET_GLUE(rIBASE) 2247 jmp .LOP_IPUT_OBJECT_resolve 2248 2249 2250/* ------------------------------ */ 2251 .balign 64 2252.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2253/* File: x86/OP_IPUT_BOOLEAN.S */ 2254/* File: x86/OP_IPUT.S */ 2255 2256 /* 2257 * General 32-bit instance field put. 2258 * 2259 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2260 */ 2261 /* op vA, vB, field@CCCC */ 2262 GET_GLUE(%ecx) 2263 SPILL(rIBASE) # need another reg 2264 movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC 2265 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2266 movzbl rINST_HI,%ecx # ecx<- BA 2267 sarl $4,%ecx # ecx<- B 2268 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2269 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 2270 andb $0xf,rINST_LO # rINST_FULL<- A 2271 GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr 2272 movl (%eax,rIBASE,4),%eax # resolved entry 2273 testl %eax,%eax # is resolved entry null? 2274 jne .LOP_IPUT_BOOLEAN_finish # no, already resolved 2275 movl rIBASE,OUT_ARG1(%esp) 2276 GET_GLUE(rIBASE) 2277 jmp .LOP_IPUT_BOOLEAN_resolve 2278 2279 2280/* ------------------------------ */ 2281 .balign 64 2282.L_OP_IPUT_BYTE: /* 0x5d */ 2283/* File: x86/OP_IPUT_BYTE.S */ 2284/* File: x86/OP_IPUT.S */ 2285 2286 /* 2287 * General 32-bit instance field put. 2288 * 2289 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2290 */ 2291 /* op vA, vB, field@CCCC */ 2292 GET_GLUE(%ecx) 2293 SPILL(rIBASE) # need another reg 2294 movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC 2295 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2296 movzbl rINST_HI,%ecx # ecx<- BA 2297 sarl $4,%ecx # ecx<- B 2298 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2299 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 2300 andb $0xf,rINST_LO # rINST_FULL<- A 2301 GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr 2302 movl (%eax,rIBASE,4),%eax # resolved entry 2303 testl %eax,%eax # is resolved entry null? 2304 jne .LOP_IPUT_BYTE_finish # no, already resolved 2305 movl rIBASE,OUT_ARG1(%esp) 2306 GET_GLUE(rIBASE) 2307 jmp .LOP_IPUT_BYTE_resolve 2308 2309 2310/* ------------------------------ */ 2311 .balign 64 2312.L_OP_IPUT_CHAR: /* 0x5e */ 2313/* File: x86/OP_IPUT_CHAR.S */ 2314/* File: x86/OP_IPUT.S */ 2315 2316 /* 2317 * General 32-bit instance field put. 2318 * 2319 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2320 */ 2321 /* op vA, vB, field@CCCC */ 2322 GET_GLUE(%ecx) 2323 SPILL(rIBASE) # need another reg 2324 movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC 2325 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2326 movzbl rINST_HI,%ecx # ecx<- BA 2327 sarl $4,%ecx # ecx<- B 2328 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2329 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 2330 andb $0xf,rINST_LO # rINST_FULL<- A 2331 GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr 2332 movl (%eax,rIBASE,4),%eax # resolved entry 2333 testl %eax,%eax # is resolved entry null? 2334 jne .LOP_IPUT_CHAR_finish # no, already resolved 2335 movl rIBASE,OUT_ARG1(%esp) 2336 GET_GLUE(rIBASE) 2337 jmp .LOP_IPUT_CHAR_resolve 2338 2339 2340/* ------------------------------ */ 2341 .balign 64 2342.L_OP_IPUT_SHORT: /* 0x5f */ 2343/* File: x86/OP_IPUT_SHORT.S */ 2344/* File: x86/OP_IPUT.S */ 2345 2346 /* 2347 * General 32-bit instance field put. 2348 * 2349 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2350 */ 2351 /* op vA, vB, field@CCCC */ 2352 GET_GLUE(%ecx) 2353 SPILL(rIBASE) # need another reg 2354 movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC 2355 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2356 movzbl rINST_HI,%ecx # ecx<- BA 2357 sarl $4,%ecx # ecx<- B 2358 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2359 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 2360 andb $0xf,rINST_LO # rINST_FULL<- A 2361 GET_VREG(%ecx,%ecx) # ecx<- fp[B], the object ptr 2362 movl (%eax,rIBASE,4),%eax # resolved entry 2363 testl %eax,%eax # is resolved entry null? 2364 jne .LOP_IPUT_SHORT_finish # no, already resolved 2365 movl rIBASE,OUT_ARG1(%esp) 2366 GET_GLUE(rIBASE) 2367 jmp .LOP_IPUT_SHORT_resolve 2368 2369 2370/* ------------------------------ */ 2371 .balign 64 2372.L_OP_SGET: /* 0x60 */ 2373/* File: x86/OP_SGET.S */ 2374 /* 2375 * General 32-bit SGET handler. 2376 * 2377 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2378 */ 2379 /* op vAA, field@BBBB */ 2380 GET_GLUE(%ecx) 2381 movzwl 2(rPC),%eax # eax<- field ref BBBB 2382 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2383 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2384 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2385 testl %eax,%eax # resolved entry null? 2386 je .LOP_SGET_resolve # if not, make it so 2387.LOP_SGET_finish: # field ptr in eax 2388 movl offStaticField_value(%eax),%eax 2389 movzbl rINST_HI,%ecx # ecx<- AA 2390 FETCH_INST_WORD(2) 2391 ADVANCE_PC(2) 2392 SET_VREG(%eax,%ecx) 2393 GOTO_NEXT 2394 2395/* ------------------------------ */ 2396 .balign 64 2397.L_OP_SGET_WIDE: /* 0x61 */ 2398/* File: x86/OP_SGET_WIDE.S */ 2399 /* 2400 * 64-bit SGET handler. 2401 * 2402 */ 2403 /* sget-wide vAA, field@BBBB */ 2404 GET_GLUE(%ecx) 2405 movzwl 2(rPC),%eax # eax<- field ref BBBB 2406 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2407 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2408 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2409 testl %eax,%eax # resolved entry null? 2410 je .LOP_SGET_WIDE_resolve # if not, make it so 2411.LOP_SGET_WIDE_finish: # field ptr in eax 2412 movl offStaticField_value(%eax),%ecx # ecx<- lsw 2413 movl 4+offStaticField_value(%eax),%eax # eax<- msw 2414 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA 2415 SET_VREG_WORD(%ecx,rINST_FULL,0) 2416 SET_VREG_WORD(%eax,rINST_FULL,1) 2417 FETCH_INST_WORD(2) 2418 ADVANCE_PC(2) 2419 GOTO_NEXT 2420 2421/* ------------------------------ */ 2422 .balign 64 2423.L_OP_SGET_OBJECT: /* 0x62 */ 2424/* File: x86/OP_SGET_OBJECT.S */ 2425/* File: x86/OP_SGET.S */ 2426 /* 2427 * General 32-bit SGET handler. 2428 * 2429 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2430 */ 2431 /* op vAA, field@BBBB */ 2432 GET_GLUE(%ecx) 2433 movzwl 2(rPC),%eax # eax<- field ref BBBB 2434 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2435 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2436 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2437 testl %eax,%eax # resolved entry null? 2438 je .LOP_SGET_OBJECT_resolve # if not, make it so 2439.LOP_SGET_OBJECT_finish: # field ptr in eax 2440 movl offStaticField_value(%eax),%eax 2441 movzbl rINST_HI,%ecx # ecx<- AA 2442 FETCH_INST_WORD(2) 2443 ADVANCE_PC(2) 2444 SET_VREG(%eax,%ecx) 2445 GOTO_NEXT 2446 2447 2448/* ------------------------------ */ 2449 .balign 64 2450.L_OP_SGET_BOOLEAN: /* 0x63 */ 2451/* File: x86/OP_SGET_BOOLEAN.S */ 2452/* File: x86/OP_SGET.S */ 2453 /* 2454 * General 32-bit SGET handler. 2455 * 2456 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2457 */ 2458 /* op vAA, field@BBBB */ 2459 GET_GLUE(%ecx) 2460 movzwl 2(rPC),%eax # eax<- field ref BBBB 2461 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2462 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2463 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2464 testl %eax,%eax # resolved entry null? 2465 je .LOP_SGET_BOOLEAN_resolve # if not, make it so 2466.LOP_SGET_BOOLEAN_finish: # field ptr in eax 2467 movl offStaticField_value(%eax),%eax 2468 movzbl rINST_HI,%ecx # ecx<- AA 2469 FETCH_INST_WORD(2) 2470 ADVANCE_PC(2) 2471 SET_VREG(%eax,%ecx) 2472 GOTO_NEXT 2473 2474 2475/* ------------------------------ */ 2476 .balign 64 2477.L_OP_SGET_BYTE: /* 0x64 */ 2478/* File: x86/OP_SGET_BYTE.S */ 2479/* File: x86/OP_SGET.S */ 2480 /* 2481 * General 32-bit SGET handler. 2482 * 2483 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2484 */ 2485 /* op vAA, field@BBBB */ 2486 GET_GLUE(%ecx) 2487 movzwl 2(rPC),%eax # eax<- field ref BBBB 2488 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2489 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2490 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2491 testl %eax,%eax # resolved entry null? 2492 je .LOP_SGET_BYTE_resolve # if not, make it so 2493.LOP_SGET_BYTE_finish: # field ptr in eax 2494 movl offStaticField_value(%eax),%eax 2495 movzbl rINST_HI,%ecx # ecx<- AA 2496 FETCH_INST_WORD(2) 2497 ADVANCE_PC(2) 2498 SET_VREG(%eax,%ecx) 2499 GOTO_NEXT 2500 2501 2502/* ------------------------------ */ 2503 .balign 64 2504.L_OP_SGET_CHAR: /* 0x65 */ 2505/* File: x86/OP_SGET_CHAR.S */ 2506/* File: x86/OP_SGET.S */ 2507 /* 2508 * General 32-bit SGET handler. 2509 * 2510 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2511 */ 2512 /* op vAA, field@BBBB */ 2513 GET_GLUE(%ecx) 2514 movzwl 2(rPC),%eax # eax<- field ref BBBB 2515 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2516 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2517 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2518 testl %eax,%eax # resolved entry null? 2519 je .LOP_SGET_CHAR_resolve # if not, make it so 2520.LOP_SGET_CHAR_finish: # field ptr in eax 2521 movl offStaticField_value(%eax),%eax 2522 movzbl rINST_HI,%ecx # ecx<- AA 2523 FETCH_INST_WORD(2) 2524 ADVANCE_PC(2) 2525 SET_VREG(%eax,%ecx) 2526 GOTO_NEXT 2527 2528 2529/* ------------------------------ */ 2530 .balign 64 2531.L_OP_SGET_SHORT: /* 0x66 */ 2532/* File: x86/OP_SGET_SHORT.S */ 2533/* File: x86/OP_SGET.S */ 2534 /* 2535 * General 32-bit SGET handler. 2536 * 2537 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2538 */ 2539 /* op vAA, field@BBBB */ 2540 GET_GLUE(%ecx) 2541 movzwl 2(rPC),%eax # eax<- field ref BBBB 2542 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2543 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2544 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2545 testl %eax,%eax # resolved entry null? 2546 je .LOP_SGET_SHORT_resolve # if not, make it so 2547.LOP_SGET_SHORT_finish: # field ptr in eax 2548 movl offStaticField_value(%eax),%eax 2549 movzbl rINST_HI,%ecx # ecx<- AA 2550 FETCH_INST_WORD(2) 2551 ADVANCE_PC(2) 2552 SET_VREG(%eax,%ecx) 2553 GOTO_NEXT 2554 2555 2556/* ------------------------------ */ 2557 .balign 64 2558.L_OP_SPUT: /* 0x67 */ 2559/* File: x86/OP_SPUT.S */ 2560 /* 2561 * General 32-bit SPUT handler. 2562 * 2563 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2564 */ 2565 /* op vAA, field@BBBB */ 2566 GET_GLUE(%ecx) 2567 movzwl 2(rPC),%eax # eax<- field ref BBBB 2568 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2569 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2570 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2571 testl %eax,%eax # resolved entry null? 2572 je .LOP_SPUT_resolve # if not, make it so 2573.LOP_SPUT_finish: # field ptr in eax 2574 movzbl rINST_HI,%ecx # ecx<- AA 2575 GET_VREG(%ecx,%ecx) 2576 FETCH_INST_WORD(2) 2577 movl %ecx,offStaticField_value(%eax) 2578 ADVANCE_PC(2) 2579 GOTO_NEXT 2580 2581/* ------------------------------ */ 2582 .balign 64 2583.L_OP_SPUT_WIDE: /* 0x68 */ 2584/* File: x86/OP_SPUT_WIDE.S */ 2585 /* 2586 * General 32-bit SPUT handler. 2587 * 2588 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2589 */ 2590 /* op vAA, field@BBBB */ 2591 GET_GLUE(%ecx) 2592 movzwl 2(rPC),%eax # eax<- field ref BBBB 2593 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2594 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2595 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2596 testl %eax,%eax # resolved entry null? 2597 je .LOP_SPUT_WIDE_resolve # if not, make it so 2598.LOP_SPUT_WIDE_finish: # field ptr in eax 2599 movzbl rINST_HI,%ecx # ecx<- AA 2600 GET_VREG_WORD(rINST_FULL,%ecx,0) # rINST_FULL<- lsw 2601 GET_VREG_WORD(%ecx,%ecx,1) # ecx<- msw 2602 movl rINST_FULL,offStaticField_value(%eax) 2603 FETCH_INST_WORD(2) 2604 ADVANCE_PC(2) 2605 movl %ecx,4+offStaticField_value(%eax) 2606 GOTO_NEXT 2607 2608/* ------------------------------ */ 2609 .balign 64 2610.L_OP_SPUT_OBJECT: /* 0x69 */ 2611/* File: x86/OP_SPUT_OBJECT.S */ 2612/* File: x86/OP_SPUT.S */ 2613 /* 2614 * General 32-bit SPUT handler. 2615 * 2616 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2617 */ 2618 /* op vAA, field@BBBB */ 2619 GET_GLUE(%ecx) 2620 movzwl 2(rPC),%eax # eax<- field ref BBBB 2621 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2622 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2623 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2624 testl %eax,%eax # resolved entry null? 2625 je .LOP_SPUT_OBJECT_resolve # if not, make it so 2626.LOP_SPUT_OBJECT_finish: # field ptr in eax 2627 movzbl rINST_HI,%ecx # ecx<- AA 2628 GET_VREG(%ecx,%ecx) 2629 FETCH_INST_WORD(2) 2630 movl %ecx,offStaticField_value(%eax) 2631 ADVANCE_PC(2) 2632 GOTO_NEXT 2633 2634 2635/* ------------------------------ */ 2636 .balign 64 2637.L_OP_SPUT_BOOLEAN: /* 0x6a */ 2638/* File: x86/OP_SPUT_BOOLEAN.S */ 2639/* File: x86/OP_SPUT.S */ 2640 /* 2641 * General 32-bit SPUT handler. 2642 * 2643 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2644 */ 2645 /* op vAA, field@BBBB */ 2646 GET_GLUE(%ecx) 2647 movzwl 2(rPC),%eax # eax<- field ref BBBB 2648 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2649 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2650 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2651 testl %eax,%eax # resolved entry null? 2652 je .LOP_SPUT_BOOLEAN_resolve # if not, make it so 2653.LOP_SPUT_BOOLEAN_finish: # field ptr in eax 2654 movzbl rINST_HI,%ecx # ecx<- AA 2655 GET_VREG(%ecx,%ecx) 2656 FETCH_INST_WORD(2) 2657 movl %ecx,offStaticField_value(%eax) 2658 ADVANCE_PC(2) 2659 GOTO_NEXT 2660 2661 2662/* ------------------------------ */ 2663 .balign 64 2664.L_OP_SPUT_BYTE: /* 0x6b */ 2665/* File: x86/OP_SPUT_BYTE.S */ 2666/* File: x86/OP_SPUT.S */ 2667 /* 2668 * General 32-bit SPUT handler. 2669 * 2670 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2671 */ 2672 /* op vAA, field@BBBB */ 2673 GET_GLUE(%ecx) 2674 movzwl 2(rPC),%eax # eax<- field ref BBBB 2675 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2676 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2677 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2678 testl %eax,%eax # resolved entry null? 2679 je .LOP_SPUT_BYTE_resolve # if not, make it so 2680.LOP_SPUT_BYTE_finish: # field ptr in eax 2681 movzbl rINST_HI,%ecx # ecx<- AA 2682 GET_VREG(%ecx,%ecx) 2683 FETCH_INST_WORD(2) 2684 movl %ecx,offStaticField_value(%eax) 2685 ADVANCE_PC(2) 2686 GOTO_NEXT 2687 2688 2689/* ------------------------------ */ 2690 .balign 64 2691.L_OP_SPUT_CHAR: /* 0x6c */ 2692/* File: x86/OP_SPUT_CHAR.S */ 2693/* File: x86/OP_SPUT.S */ 2694 /* 2695 * General 32-bit SPUT handler. 2696 * 2697 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2698 */ 2699 /* op vAA, field@BBBB */ 2700 GET_GLUE(%ecx) 2701 movzwl 2(rPC),%eax # eax<- field ref BBBB 2702 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2703 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2704 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2705 testl %eax,%eax # resolved entry null? 2706 je .LOP_SPUT_CHAR_resolve # if not, make it so 2707.LOP_SPUT_CHAR_finish: # field ptr in eax 2708 movzbl rINST_HI,%ecx # ecx<- AA 2709 GET_VREG(%ecx,%ecx) 2710 FETCH_INST_WORD(2) 2711 movl %ecx,offStaticField_value(%eax) 2712 ADVANCE_PC(2) 2713 GOTO_NEXT 2714 2715 2716/* ------------------------------ */ 2717 .balign 64 2718.L_OP_SPUT_SHORT: /* 0x6d */ 2719/* File: x86/OP_SPUT_SHORT.S */ 2720/* File: x86/OP_SPUT.S */ 2721 /* 2722 * General 32-bit SPUT handler. 2723 * 2724 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2725 */ 2726 /* op vAA, field@BBBB */ 2727 GET_GLUE(%ecx) 2728 movzwl 2(rPC),%eax # eax<- field ref BBBB 2729 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2730 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2731 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2732 testl %eax,%eax # resolved entry null? 2733 je .LOP_SPUT_SHORT_resolve # if not, make it so 2734.LOP_SPUT_SHORT_finish: # field ptr in eax 2735 movzbl rINST_HI,%ecx # ecx<- AA 2736 GET_VREG(%ecx,%ecx) 2737 FETCH_INST_WORD(2) 2738 movl %ecx,offStaticField_value(%eax) 2739 ADVANCE_PC(2) 2740 GOTO_NEXT 2741 2742 2743/* ------------------------------ */ 2744 .balign 64 2745.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 2746/* File: x86/OP_INVOKE_VIRTUAL.S */ 2747 2748 /* 2749 * Handle a virtual method call. 2750 * 2751 * for: invoke-virtual, invoke-virtual/range 2752 */ 2753 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 2754 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 2755 GET_GLUE(%eax) 2756 movzwl 2(rPC),%ecx # ecx<- BBBB 2757 movl offGlue_methodClassDex(%eax),%eax # eax<- pDvmDex 2758 EXPORT_PC() 2759 movl offDvmDex_pResMethods(%eax),%eax # eax<- pDvmDex->pResMethods 2760 movl (%eax,%ecx,4),%eax # eax<- resolved baseMethod 2761 testl %eax,%eax # already resolved? 2762 jne .LOP_INVOKE_VIRTUAL_continue # yes, continue 2763 GET_GLUE(%eax) 2764 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 2765 movl offGlue_method(%eax),%eax # eax<- glue->method 2766 SPILL(rPC) 2767 jmp .LOP_INVOKE_VIRTUAL_more 2768 2769/* ------------------------------ */ 2770 .balign 64 2771.L_OP_INVOKE_SUPER: /* 0x6f */ 2772/* File: x86/OP_INVOKE_SUPER.S */ 2773 /* 2774 * Handle a "super" method call. 2775 * 2776 * for: invoke-super, invoke-super/range 2777 */ 2778 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 2779 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 2780 GET_GLUE(rINST_FULL) 2781 movzwl 2(rPC),%eax # eax<- BBBB 2782 movl offGlue_methodClassDex(rINST_FULL),%ecx # ecx<- pDvmDex 2783 EXPORT_PC() 2784 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods 2785 movl (%ecx,%eax,4),%ecx # ecx<- resolved baseMethod 2786 movl offGlue_method(rINST_FULL),%eax # eax<- method 2787 movzwl 4(rPC),rINST_FULL # rINST_FULL<- GFED or CCCC 2788 .if (!0) 2789 andl $0xf,rINST_FULL # rINST_FULL<- D (or stays CCCC) 2790 .endif 2791 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- "this" ptr 2792 testl rINST_FULL,rINST_FULL # null "this"? 2793 je common_errNullObject # yes, throw 2794 movl offMethod_clazz(%eax),%eax # eax<- method->clazz 2795 testl %ecx,%ecx # already resolved? 2796 jne .LOP_INVOKE_SUPER_continue # yes - go on 2797 jmp .LOP_INVOKE_SUPER_resolve 2798 2799/* ------------------------------ */ 2800 .balign 64 2801.L_OP_INVOKE_DIRECT: /* 0x70 */ 2802/* File: x86/OP_INVOKE_DIRECT.S */ 2803 /* 2804 * Handle a direct method call. 2805 * 2806 * (We could defer the "is 'this' pointer null" test to the common 2807 * method invocation code, and use a flag to indicate that static 2808 * calls don't count. If we do this as part of copying the arguments 2809 * out we could avoiding loading the first arg twice.) 2810 * 2811 * for: invoke-direct, invoke-direct/range 2812 */ 2813 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 2814 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 2815 GET_GLUE(%ecx) 2816 movzwl 2(rPC),%eax # eax<- BBBB 2817 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex 2818 EXPORT_PC() 2819 SPILL(rPC) 2820 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods 2821 movzwl 4(rPC),rPC # rPC<- GFED or CCCC 2822 movl (%ecx,%eax,4),%eax # eax<- resolved methodToCall 2823 .if (!0) 2824 andl $0xf,rPC # rPC<- D (or stays CCCC) 2825 .endif 2826 testl %eax,%eax # already resolved? 2827 GET_VREG(%ecx,rPC) # ecx<- "this" ptr 2828 je .LOP_INVOKE_DIRECT_resolve # not resolved, do it now 2829.LOP_INVOKE_DIRECT_finish: 2830 UNSPILL(rPC) 2831 testl %ecx,%ecx # null "this"? 2832 jne common_invokeMethodNoRange # no, continue on 2833 jmp common_errNullObject 2834 2835/* ------------------------------ */ 2836 .balign 64 2837.L_OP_INVOKE_STATIC: /* 0x71 */ 2838/* File: x86/OP_INVOKE_STATIC.S */ 2839 /* 2840 * Handle a static method call. 2841 * 2842 * for: invoke-static, invoke-static/range 2843 */ 2844 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 2845 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 2846 GET_GLUE(%ecx) 2847 movzwl 2(rPC),%eax # eax<- BBBB 2848 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex 2849 EXPORT_PC() 2850 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods 2851 movl (%ecx,%eax,4),%eax # eax<- resolved methodToCall 2852 testl %eax,%eax 2853 jne common_invokeMethodNoRange 2854 GET_GLUE(%ecx) 2855 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 2856 movzwl 2(rPC),%eax 2857 movl offMethod_clazz(%ecx),%ecx# ecx<- method->clazz 2858 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB 2859 movl %ecx,OUT_ARG0(%esp) # arg0<- clazz 2860 jmp .LOP_INVOKE_STATIC_continue 2861 2862/* ------------------------------ */ 2863 .balign 64 2864.L_OP_INVOKE_INTERFACE: /* 0x72 */ 2865/* File: x86/OP_INVOKE_INTERFACE.S */ 2866 /* 2867 * Handle an interface method call. 2868 * 2869 * for: invoke-interface, invoke-interface/range 2870 */ 2871 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 2872 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 2873 movzwl 4(rPC),%eax # eax<- FEDC or CCCC 2874 GET_GLUE(%ecx) 2875 .if (!0) 2876 andl $0xf,%eax # eax<- C (or stays CCCC) 2877 .endif 2878 GET_VREG(%eax,%eax) # eax<- "this" 2879 EXPORT_PC() 2880 testl %eax,%eax # null this? 2881 je common_errNullObject # yes, fail 2882 movl offObject_clazz(%eax),%eax# eax<- thisPtr->clazz 2883 movl %eax,OUT_ARG0(%esp) # arg0<- class 2884 movl offGlue_methodClassDex(%ecx),%eax # eax<- methodClassDex 2885 movl offGlue_method(%ecx),%ecx # ecx<- method 2886 movl %eax,OUT_ARG3(%esp) # arg3<- dex 2887 movzwl 2(rPC),%eax # eax<- BBBB 2888 movl %ecx,OUT_ARG2(%esp) # arg2<- method 2889 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB 2890 SPILL(rPC) 2891 jmp .LOP_INVOKE_INTERFACE_continue 2892 2893/* ------------------------------ */ 2894 .balign 64 2895.L_OP_UNUSED_73: /* 0x73 */ 2896/* File: x86/OP_UNUSED_73.S */ 2897/* File: x86/unused.S */ 2898 jmp common_abort 2899 2900 2901/* ------------------------------ */ 2902 .balign 64 2903.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 2904/* File: x86/OP_INVOKE_VIRTUAL_RANGE.S */ 2905/* File: x86/OP_INVOKE_VIRTUAL.S */ 2906 2907 /* 2908 * Handle a virtual method call. 2909 * 2910 * for: invoke-virtual, invoke-virtual/range 2911 */ 2912 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 2913 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 2914 GET_GLUE(%eax) 2915 movzwl 2(rPC),%ecx # ecx<- BBBB 2916 movl offGlue_methodClassDex(%eax),%eax # eax<- pDvmDex 2917 EXPORT_PC() 2918 movl offDvmDex_pResMethods(%eax),%eax # eax<- pDvmDex->pResMethods 2919 movl (%eax,%ecx,4),%eax # eax<- resolved baseMethod 2920 testl %eax,%eax # already resolved? 2921 jne .LOP_INVOKE_VIRTUAL_RANGE_continue # yes, continue 2922 GET_GLUE(%eax) 2923 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 2924 movl offGlue_method(%eax),%eax # eax<- glue->method 2925 SPILL(rPC) 2926 jmp .LOP_INVOKE_VIRTUAL_RANGE_more 2927 2928 2929/* ------------------------------ */ 2930 .balign 64 2931.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 2932/* File: x86/OP_INVOKE_SUPER_RANGE.S */ 2933/* File: x86/OP_INVOKE_SUPER.S */ 2934 /* 2935 * Handle a "super" method call. 2936 * 2937 * for: invoke-super, invoke-super/range 2938 */ 2939 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 2940 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 2941 GET_GLUE(rINST_FULL) 2942 movzwl 2(rPC),%eax # eax<- BBBB 2943 movl offGlue_methodClassDex(rINST_FULL),%ecx # ecx<- pDvmDex 2944 EXPORT_PC() 2945 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods 2946 movl (%ecx,%eax,4),%ecx # ecx<- resolved baseMethod 2947 movl offGlue_method(rINST_FULL),%eax # eax<- method 2948 movzwl 4(rPC),rINST_FULL # rINST_FULL<- GFED or CCCC 2949 .if (!1) 2950 andl $0xf,rINST_FULL # rINST_FULL<- D (or stays CCCC) 2951 .endif 2952 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- "this" ptr 2953 testl rINST_FULL,rINST_FULL # null "this"? 2954 je common_errNullObject # yes, throw 2955 movl offMethod_clazz(%eax),%eax # eax<- method->clazz 2956 testl %ecx,%ecx # already resolved? 2957 jne .LOP_INVOKE_SUPER_RANGE_continue # yes - go on 2958 jmp .LOP_INVOKE_SUPER_RANGE_resolve 2959 2960 2961/* ------------------------------ */ 2962 .balign 64 2963.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 2964/* File: x86/OP_INVOKE_DIRECT_RANGE.S */ 2965/* File: x86/OP_INVOKE_DIRECT.S */ 2966 /* 2967 * Handle a direct method call. 2968 * 2969 * (We could defer the "is 'this' pointer null" test to the common 2970 * method invocation code, and use a flag to indicate that static 2971 * calls don't count. If we do this as part of copying the arguments 2972 * out we could avoiding loading the first arg twice.) 2973 * 2974 * for: invoke-direct, invoke-direct/range 2975 */ 2976 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 2977 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 2978 GET_GLUE(%ecx) 2979 movzwl 2(rPC),%eax # eax<- BBBB 2980 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex 2981 EXPORT_PC() 2982 SPILL(rPC) 2983 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods 2984 movzwl 4(rPC),rPC # rPC<- GFED or CCCC 2985 movl (%ecx,%eax,4),%eax # eax<- resolved methodToCall 2986 .if (!1) 2987 andl $0xf,rPC # rPC<- D (or stays CCCC) 2988 .endif 2989 testl %eax,%eax # already resolved? 2990 GET_VREG(%ecx,rPC) # ecx<- "this" ptr 2991 je .LOP_INVOKE_DIRECT_RANGE_resolve # not resolved, do it now 2992.LOP_INVOKE_DIRECT_RANGE_finish: 2993 UNSPILL(rPC) 2994 testl %ecx,%ecx # null "this"? 2995 jne common_invokeMethodRange # no, continue on 2996 jmp common_errNullObject 2997 2998 2999/* ------------------------------ */ 3000 .balign 64 3001.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3002/* File: x86/OP_INVOKE_STATIC_RANGE.S */ 3003/* File: x86/OP_INVOKE_STATIC.S */ 3004 /* 3005 * Handle a static method call. 3006 * 3007 * for: invoke-static, invoke-static/range 3008 */ 3009 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3010 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3011 GET_GLUE(%ecx) 3012 movzwl 2(rPC),%eax # eax<- BBBB 3013 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex 3014 EXPORT_PC() 3015 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods 3016 movl (%ecx,%eax,4),%eax # eax<- resolved methodToCall 3017 testl %eax,%eax 3018 jne common_invokeMethodRange 3019 GET_GLUE(%ecx) 3020 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 3021 movzwl 2(rPC),%eax 3022 movl offMethod_clazz(%ecx),%ecx# ecx<- method->clazz 3023 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB 3024 movl %ecx,OUT_ARG0(%esp) # arg0<- clazz 3025 jmp .LOP_INVOKE_STATIC_RANGE_continue 3026 3027 3028/* ------------------------------ */ 3029 .balign 64 3030.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3031/* File: x86/OP_INVOKE_INTERFACE_RANGE.S */ 3032/* File: x86/OP_INVOKE_INTERFACE.S */ 3033 /* 3034 * Handle an interface method call. 3035 * 3036 * for: invoke-interface, invoke-interface/range 3037 */ 3038 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3039 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3040 movzwl 4(rPC),%eax # eax<- FEDC or CCCC 3041 GET_GLUE(%ecx) 3042 .if (!1) 3043 andl $0xf,%eax # eax<- C (or stays CCCC) 3044 .endif 3045 GET_VREG(%eax,%eax) # eax<- "this" 3046 EXPORT_PC() 3047 testl %eax,%eax # null this? 3048 je common_errNullObject # yes, fail 3049 movl offObject_clazz(%eax),%eax# eax<- thisPtr->clazz 3050 movl %eax,OUT_ARG0(%esp) # arg0<- class 3051 movl offGlue_methodClassDex(%ecx),%eax # eax<- methodClassDex 3052 movl offGlue_method(%ecx),%ecx # ecx<- method 3053 movl %eax,OUT_ARG3(%esp) # arg3<- dex 3054 movzwl 2(rPC),%eax # eax<- BBBB 3055 movl %ecx,OUT_ARG2(%esp) # arg2<- method 3056 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB 3057 SPILL(rPC) 3058 jmp .LOP_INVOKE_INTERFACE_RANGE_continue 3059 3060 3061/* ------------------------------ */ 3062 .balign 64 3063.L_OP_UNUSED_79: /* 0x79 */ 3064/* File: x86/OP_UNUSED_79.S */ 3065/* File: x86/unused.S */ 3066 jmp common_abort 3067 3068 3069/* ------------------------------ */ 3070 .balign 64 3071.L_OP_UNUSED_7A: /* 0x7a */ 3072/* File: x86/OP_UNUSED_7A.S */ 3073/* File: x86/unused.S */ 3074 jmp common_abort 3075 3076 3077/* ------------------------------ */ 3078 .balign 64 3079.L_OP_NEG_INT: /* 0x7b */ 3080/* File: x86/OP_NEG_INT.S */ 3081/* File: x86/unop.S */ 3082 /* 3083 * Generic 32-bit unary operation. Provide an "instr" line that 3084 * specifies an instruction that performs "result = op eax". 3085 */ 3086 /* unop vA, vB */ 3087 movzbl rINST_HI,%ecx # ecx<- A+ 3088 sarl $12,rINST_FULL # rINST_FULL<- B 3089 GET_VREG(%eax,rINST_FULL) # eax<- vB 3090 andb $0xf,%cl # ecx<- A 3091 FETCH_INST_WORD(1) 3092 ADVANCE_PC(1) 3093 3094 3095 negl %eax 3096 SET_VREG(%eax,%ecx) 3097 GOTO_NEXT 3098 3099 3100/* ------------------------------ */ 3101 .balign 64 3102.L_OP_NOT_INT: /* 0x7c */ 3103/* File: x86/OP_NOT_INT.S */ 3104/* File: x86/unop.S */ 3105 /* 3106 * Generic 32-bit unary operation. Provide an "instr" line that 3107 * specifies an instruction that performs "result = op eax". 3108 */ 3109 /* unop vA, vB */ 3110 movzbl rINST_HI,%ecx # ecx<- A+ 3111 sarl $12,rINST_FULL # rINST_FULL<- B 3112 GET_VREG(%eax,rINST_FULL) # eax<- vB 3113 andb $0xf,%cl # ecx<- A 3114 FETCH_INST_WORD(1) 3115 ADVANCE_PC(1) 3116 3117 3118 notl %eax 3119 SET_VREG(%eax,%ecx) 3120 GOTO_NEXT 3121 3122 3123/* ------------------------------ */ 3124 .balign 64 3125.L_OP_NEG_LONG: /* 0x7d */ 3126/* File: x86/OP_NEG_LONG.S */ 3127 /* unop vA, vB */ 3128 movzbl rINST_HI,%ecx # ecx<- BA 3129 sarl $4,%ecx # ecx<- B 3130 movzbl rINST_HI,rINST_FULL # ecx<- BA 3131 andb $0xf,rINST_LO # rINST_FULL<- A 3132 GET_VREG_WORD(%eax,%ecx,0) # eax<- v[B+0] 3133 GET_VREG_WORD(%ecx,%ecx,1) # ecx<- v[B+1] 3134 negl %eax 3135 adcl $0,%ecx 3136 negl %ecx 3137 SET_VREG_WORD(%eax,rINST_FULL,0) # v[A+0]<- eax 3138 SET_VREG_WORD(%ecx,rINST_FULL,1) # v[A+1]<- ecx 3139 FETCH_INST_WORD(1) 3140 ADVANCE_PC(1) 3141 GOTO_NEXT 3142 3143/* ------------------------------ */ 3144 .balign 64 3145.L_OP_NOT_LONG: /* 0x7e */ 3146/* File: x86/OP_NOT_LONG.S */ 3147 /* unop vA, vB */ 3148 movzbl rINST_HI,%ecx # ecx<- BA 3149 sarl $4,%ecx # ecx<- B 3150 movzbl rINST_HI,rINST_FULL # ecx<- BA 3151 andb $0xf,rINST_LO # rINST_FULL<- A 3152 GET_VREG_WORD(%eax,%ecx,0) # eax<- v[B+0] 3153 GET_VREG_WORD(%ecx,%ecx,1) # ecx<- v[B+1] 3154 notl %eax 3155 notl %ecx 3156 SET_VREG_WORD(%eax,rINST_FULL,0) # v[A+0]<- eax 3157 SET_VREG_WORD(%ecx,rINST_FULL,1) # v[A+1]<- ecx 3158 FETCH_INST_WORD(1) 3159 ADVANCE_PC(1) 3160 GOTO_NEXT 3161 3162/* ------------------------------ */ 3163 .balign 64 3164.L_OP_NEG_FLOAT: /* 0x7f */ 3165/* File: x86/OP_NEG_FLOAT.S */ 3166/* File: x86/fpcvt.S */ 3167 /* 3168 * Generic 32-bit FP conversion operation. 3169 */ 3170 /* unop vA, vB */ 3171 movzbl rINST_HI,%ecx # ecx<- A+ 3172 sarl $12,rINST_FULL # rINST_FULL<- B 3173 flds (rFP,rINST_FULL,4) # %st0<- vB 3174 andb $0xf,%cl # ecx<- A 3175 FETCH_INST_WORD(1) 3176 ADVANCE_PC(1) 3177 fchs 3178 fstps (rFP,%ecx,4) # vA<- %st0 3179 GOTO_NEXT 3180 3181 3182/* ------------------------------ */ 3183 .balign 64 3184.L_OP_NEG_DOUBLE: /* 0x80 */ 3185/* File: x86/OP_NEG_DOUBLE.S */ 3186/* File: x86/fpcvt.S */ 3187 /* 3188 * Generic 32-bit FP conversion operation. 3189 */ 3190 /* unop vA, vB */ 3191 movzbl rINST_HI,%ecx # ecx<- A+ 3192 sarl $12,rINST_FULL # rINST_FULL<- B 3193 fldl (rFP,rINST_FULL,4) # %st0<- vB 3194 andb $0xf,%cl # ecx<- A 3195 FETCH_INST_WORD(1) 3196 ADVANCE_PC(1) 3197 fchs 3198 fstpl (rFP,%ecx,4) # vA<- %st0 3199 GOTO_NEXT 3200 3201 3202/* ------------------------------ */ 3203 .balign 64 3204.L_OP_INT_TO_LONG: /* 0x81 */ 3205/* File: x86/OP_INT_TO_LONG.S */ 3206 /* int to long vA, vB */ 3207 movzbl rINST_HI,%ecx # ecx<- +A 3208 sarl $12,rINST_FULL # rINST_FULL<- B 3209 GET_VREG(%eax,rINST_FULL) # eax<- vB 3210 SPILL(rPC) # will step on edx later 3211 andb $0xf,%cl # ecx<- A 3212 cltd # edx:eax<- sssssssBBBBBBBB 3213 SET_VREG_WORD(%edx,%ecx,1) # v[A+1]<- edx/rPC 3214 UNSPILL(rPC) 3215 SET_VREG_WORD(%eax,%ecx,0) # v[A+0]<- %eax 3216 FETCH_INST_WORD(1) 3217 ADVANCE_PC(1) 3218 GOTO_NEXT 3219 3220/* ------------------------------ */ 3221 .balign 64 3222.L_OP_INT_TO_FLOAT: /* 0x82 */ 3223/* File: x86/OP_INT_TO_FLOAT.S */ 3224/* File: x86/fpcvt.S */ 3225 /* 3226 * Generic 32-bit FP conversion operation. 3227 */ 3228 /* unop vA, vB */ 3229 movzbl rINST_HI,%ecx # ecx<- A+ 3230 sarl $12,rINST_FULL # rINST_FULL<- B 3231 fildl (rFP,rINST_FULL,4) # %st0<- vB 3232 andb $0xf,%cl # ecx<- A 3233 FETCH_INST_WORD(1) 3234 ADVANCE_PC(1) 3235 3236 fstps (rFP,%ecx,4) # vA<- %st0 3237 GOTO_NEXT 3238 3239 3240/* ------------------------------ */ 3241 .balign 64 3242.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3243/* File: x86/OP_INT_TO_DOUBLE.S */ 3244/* File: x86/fpcvt.S */ 3245 /* 3246 * Generic 32-bit FP conversion operation. 3247 */ 3248 /* unop vA, vB */ 3249 movzbl rINST_HI,%ecx # ecx<- A+ 3250 sarl $12,rINST_FULL # rINST_FULL<- B 3251 fildl (rFP,rINST_FULL,4) # %st0<- vB 3252 andb $0xf,%cl # ecx<- A 3253 FETCH_INST_WORD(1) 3254 ADVANCE_PC(1) 3255 3256 fstpl (rFP,%ecx,4) # vA<- %st0 3257 GOTO_NEXT 3258 3259 3260/* ------------------------------ */ 3261 .balign 64 3262.L_OP_LONG_TO_INT: /* 0x84 */ 3263/* File: x86/OP_LONG_TO_INT.S */ 3264/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3265/* File: x86/OP_MOVE.S */ 3266 /* for move, move-object, long-to-int */ 3267 /* op vA, vB */ 3268 movzbl rINST_HI,%eax # eax<- BA 3269 andb $0xf,%al # eax<- A 3270 shrl $12,rINST_FULL # rINST_FULL<- B 3271 GET_VREG(%ecx,rINST_FULL) 3272 FETCH_INST_WORD(1) 3273 ADVANCE_PC(1) 3274 SET_VREG(%ecx,%eax) # fp[A]<-fp[B] 3275 GOTO_NEXT 3276 3277 3278/* ------------------------------ */ 3279 .balign 64 3280.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3281/* File: x86/OP_LONG_TO_FLOAT.S */ 3282/* File: x86/fpcvt.S */ 3283 /* 3284 * Generic 32-bit FP conversion operation. 3285 */ 3286 /* unop vA, vB */ 3287 movzbl rINST_HI,%ecx # ecx<- A+ 3288 sarl $12,rINST_FULL # rINST_FULL<- B 3289 fildll (rFP,rINST_FULL,4) # %st0<- vB 3290 andb $0xf,%cl # ecx<- A 3291 FETCH_INST_WORD(1) 3292 ADVANCE_PC(1) 3293 3294 fstps (rFP,%ecx,4) # vA<- %st0 3295 GOTO_NEXT 3296 3297 3298/* ------------------------------ */ 3299 .balign 64 3300.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3301/* File: x86/OP_LONG_TO_DOUBLE.S */ 3302/* File: x86/fpcvt.S */ 3303 /* 3304 * Generic 32-bit FP conversion operation. 3305 */ 3306 /* unop vA, vB */ 3307 movzbl rINST_HI,%ecx # ecx<- A+ 3308 sarl $12,rINST_FULL # rINST_FULL<- B 3309 fildll (rFP,rINST_FULL,4) # %st0<- vB 3310 andb $0xf,%cl # ecx<- A 3311 FETCH_INST_WORD(1) 3312 ADVANCE_PC(1) 3313 3314 fstpl (rFP,%ecx,4) # vA<- %st0 3315 GOTO_NEXT 3316 3317 3318/* ------------------------------ */ 3319 .balign 64 3320.L_OP_FLOAT_TO_INT: /* 0x87 */ 3321/* File: x86/OP_FLOAT_TO_INT.S */ 3322/* File: x86/cvtfp_int.S */ 3323/* On fp to int conversions, Java requires that 3324 * if the result > maxint, it should be clamped to maxint. If it is less 3325 * than minint, it should be clamped to minint. If it is a nan, the result 3326 * should be zero. Further, the rounding mode is to truncate. This model 3327 * differs from what is delivered normally via the x86 fpu, so we have 3328 * to play some games. 3329 */ 3330 /* float/double to int/long vA, vB */ 3331 movzbl rINST_HI,%ecx # ecx<- A+ 3332 sarl $12,rINST_FULL # rINST_FULL<- B 3333 .if 0 3334 fldl (rFP,rINST_FULL,4) # %st0<- vB 3335 .else 3336 flds (rFP,rINST_FULL,4) # %st0<- vB 3337 .endif 3338 ftst 3339 fnstcw LOCAL0_OFFSET(%ebp) # remember original rounding mode 3340 movzwl LOCAL0_OFFSET(%ebp),%eax 3341 movb $0xc,%ah 3342 movw %ax,LOCAL0_OFFSET+2(%ebp) 3343 fldcw LOCAL0_OFFSET+2(%ebp) # set "to zero" rounding mode 3344 FETCH_INST_WORD(1) 3345 andb $0xf,%cl # ecx<- A 3346 .if 0 3347 fistpll (rFP,%ecx,4) # convert and store 3348 .else 3349 fistpl (rFP,%ecx,4) # convert and store 3350 .endif 3351 fldcw LOCAL0_OFFSET(%ebp) # restore previous rounding mode 3352 jmp .LOP_FLOAT_TO_INT_continue 3353 3354 3355/* ------------------------------ */ 3356 .balign 64 3357.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3358/* File: x86/OP_FLOAT_TO_LONG.S */ 3359/* File: x86/cvtfp_int.S */ 3360/* On fp to int conversions, Java requires that 3361 * if the result > maxint, it should be clamped to maxint. If it is less 3362 * than minint, it should be clamped to minint. If it is a nan, the result 3363 * should be zero. Further, the rounding mode is to truncate. This model 3364 * differs from what is delivered normally via the x86 fpu, so we have 3365 * to play some games. 3366 */ 3367 /* float/double to int/long vA, vB */ 3368 movzbl rINST_HI,%ecx # ecx<- A+ 3369 sarl $12,rINST_FULL # rINST_FULL<- B 3370 .if 0 3371 fldl (rFP,rINST_FULL,4) # %st0<- vB 3372 .else 3373 flds (rFP,rINST_FULL,4) # %st0<- vB 3374 .endif 3375 ftst 3376 fnstcw LOCAL0_OFFSET(%ebp) # remember original rounding mode 3377 movzwl LOCAL0_OFFSET(%ebp),%eax 3378 movb $0xc,%ah 3379 movw %ax,LOCAL0_OFFSET+2(%ebp) 3380 fldcw LOCAL0_OFFSET+2(%ebp) # set "to zero" rounding mode 3381 FETCH_INST_WORD(1) 3382 andb $0xf,%cl # ecx<- A 3383 .if 1 3384 fistpll (rFP,%ecx,4) # convert and store 3385 .else 3386 fistpl (rFP,%ecx,4) # convert and store 3387 .endif 3388 fldcw LOCAL0_OFFSET(%ebp) # restore previous rounding mode 3389 jmp .LOP_FLOAT_TO_LONG_continue 3390 3391 3392/* ------------------------------ */ 3393 .balign 64 3394.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3395/* File: x86/OP_FLOAT_TO_DOUBLE.S */ 3396/* File: x86/fpcvt.S */ 3397 /* 3398 * Generic 32-bit FP conversion operation. 3399 */ 3400 /* unop vA, vB */ 3401 movzbl rINST_HI,%ecx # ecx<- A+ 3402 sarl $12,rINST_FULL # rINST_FULL<- B 3403 flds (rFP,rINST_FULL,4) # %st0<- vB 3404 andb $0xf,%cl # ecx<- A 3405 FETCH_INST_WORD(1) 3406 ADVANCE_PC(1) 3407 3408 fstpl (rFP,%ecx,4) # vA<- %st0 3409 GOTO_NEXT 3410 3411 3412/* ------------------------------ */ 3413 .balign 64 3414.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3415/* File: x86/OP_DOUBLE_TO_INT.S */ 3416/* File: x86/cvtfp_int.S */ 3417/* On fp to int conversions, Java requires that 3418 * if the result > maxint, it should be clamped to maxint. If it is less 3419 * than minint, it should be clamped to minint. If it is a nan, the result 3420 * should be zero. Further, the rounding mode is to truncate. This model 3421 * differs from what is delivered normally via the x86 fpu, so we have 3422 * to play some games. 3423 */ 3424 /* float/double to int/long vA, vB */ 3425 movzbl rINST_HI,%ecx # ecx<- A+ 3426 sarl $12,rINST_FULL # rINST_FULL<- B 3427 .if 1 3428 fldl (rFP,rINST_FULL,4) # %st0<- vB 3429 .else 3430 flds (rFP,rINST_FULL,4) # %st0<- vB 3431 .endif 3432 ftst 3433 fnstcw LOCAL0_OFFSET(%ebp) # remember original rounding mode 3434 movzwl LOCAL0_OFFSET(%ebp),%eax 3435 movb $0xc,%ah 3436 movw %ax,LOCAL0_OFFSET+2(%ebp) 3437 fldcw LOCAL0_OFFSET+2(%ebp) # set "to zero" rounding mode 3438 FETCH_INST_WORD(1) 3439 andb $0xf,%cl # ecx<- A 3440 .if 0 3441 fistpll (rFP,%ecx,4) # convert and store 3442 .else 3443 fistpl (rFP,%ecx,4) # convert and store 3444 .endif 3445 fldcw LOCAL0_OFFSET(%ebp) # restore previous rounding mode 3446 jmp .LOP_DOUBLE_TO_INT_continue 3447 3448 3449/* ------------------------------ */ 3450 .balign 64 3451.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3452/* File: x86/OP_DOUBLE_TO_LONG.S */ 3453/* File: x86/cvtfp_int.S */ 3454/* On fp to int conversions, Java requires that 3455 * if the result > maxint, it should be clamped to maxint. If it is less 3456 * than minint, it should be clamped to minint. If it is a nan, the result 3457 * should be zero. Further, the rounding mode is to truncate. This model 3458 * differs from what is delivered normally via the x86 fpu, so we have 3459 * to play some games. 3460 */ 3461 /* float/double to int/long vA, vB */ 3462 movzbl rINST_HI,%ecx # ecx<- A+ 3463 sarl $12,rINST_FULL # rINST_FULL<- B 3464 .if 1 3465 fldl (rFP,rINST_FULL,4) # %st0<- vB 3466 .else 3467 flds (rFP,rINST_FULL,4) # %st0<- vB 3468 .endif 3469 ftst 3470 fnstcw LOCAL0_OFFSET(%ebp) # remember original rounding mode 3471 movzwl LOCAL0_OFFSET(%ebp),%eax 3472 movb $0xc,%ah 3473 movw %ax,LOCAL0_OFFSET+2(%ebp) 3474 fldcw LOCAL0_OFFSET+2(%ebp) # set "to zero" rounding mode 3475 FETCH_INST_WORD(1) 3476 andb $0xf,%cl # ecx<- A 3477 .if 1 3478 fistpll (rFP,%ecx,4) # convert and store 3479 .else 3480 fistpl (rFP,%ecx,4) # convert and store 3481 .endif 3482 fldcw LOCAL0_OFFSET(%ebp) # restore previous rounding mode 3483 jmp .LOP_DOUBLE_TO_LONG_continue 3484 3485 3486/* ------------------------------ */ 3487 .balign 64 3488.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3489/* File: x86/OP_DOUBLE_TO_FLOAT.S */ 3490/* File: x86/fpcvt.S */ 3491 /* 3492 * Generic 32-bit FP conversion operation. 3493 */ 3494 /* unop vA, vB */ 3495 movzbl rINST_HI,%ecx # ecx<- A+ 3496 sarl $12,rINST_FULL # rINST_FULL<- B 3497 fldl (rFP,rINST_FULL,4) # %st0<- vB 3498 andb $0xf,%cl # ecx<- A 3499 FETCH_INST_WORD(1) 3500 ADVANCE_PC(1) 3501 3502 fstps (rFP,%ecx,4) # vA<- %st0 3503 GOTO_NEXT 3504 3505 3506/* ------------------------------ */ 3507 .balign 64 3508.L_OP_INT_TO_BYTE: /* 0x8d */ 3509/* File: x86/OP_INT_TO_BYTE.S */ 3510/* File: x86/unop.S */ 3511 /* 3512 * Generic 32-bit unary operation. Provide an "instr" line that 3513 * specifies an instruction that performs "result = op eax". 3514 */ 3515 /* unop vA, vB */ 3516 movzbl rINST_HI,%ecx # ecx<- A+ 3517 sarl $12,rINST_FULL # rINST_FULL<- B 3518 GET_VREG(%eax,rINST_FULL) # eax<- vB 3519 andb $0xf,%cl # ecx<- A 3520 FETCH_INST_WORD(1) 3521 ADVANCE_PC(1) 3522 3523 3524 movsbl %al,%eax 3525 SET_VREG(%eax,%ecx) 3526 GOTO_NEXT 3527 3528 3529/* ------------------------------ */ 3530 .balign 64 3531.L_OP_INT_TO_CHAR: /* 0x8e */ 3532/* File: x86/OP_INT_TO_CHAR.S */ 3533/* File: x86/unop.S */ 3534 /* 3535 * Generic 32-bit unary operation. Provide an "instr" line that 3536 * specifies an instruction that performs "result = op eax". 3537 */ 3538 /* unop vA, vB */ 3539 movzbl rINST_HI,%ecx # ecx<- A+ 3540 sarl $12,rINST_FULL # rINST_FULL<- B 3541 GET_VREG(%eax,rINST_FULL) # eax<- vB 3542 andb $0xf,%cl # ecx<- A 3543 FETCH_INST_WORD(1) 3544 ADVANCE_PC(1) 3545 3546 3547 movzwl %ax,%eax 3548 SET_VREG(%eax,%ecx) 3549 GOTO_NEXT 3550 3551 3552/* ------------------------------ */ 3553 .balign 64 3554.L_OP_INT_TO_SHORT: /* 0x8f */ 3555/* File: x86/OP_INT_TO_SHORT.S */ 3556/* File: x86/unop.S */ 3557 /* 3558 * Generic 32-bit unary operation. Provide an "instr" line that 3559 * specifies an instruction that performs "result = op eax". 3560 */ 3561 /* unop vA, vB */ 3562 movzbl rINST_HI,%ecx # ecx<- A+ 3563 sarl $12,rINST_FULL # rINST_FULL<- B 3564 GET_VREG(%eax,rINST_FULL) # eax<- vB 3565 andb $0xf,%cl # ecx<- A 3566 FETCH_INST_WORD(1) 3567 ADVANCE_PC(1) 3568 3569 3570 movswl %ax,%eax 3571 SET_VREG(%eax,%ecx) 3572 GOTO_NEXT 3573 3574 3575/* ------------------------------ */ 3576 .balign 64 3577.L_OP_ADD_INT: /* 0x90 */ 3578/* File: x86/OP_ADD_INT.S */ 3579/* File: x86/binop.S */ 3580 /* 3581 * Generic 32-bit binary operation. Provide an "instr" line that 3582 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)". 3583 * This could be an x86 instruction or a function call. (If the result 3584 * comes back in a register other than eax, you can override "result".) 3585 * 3586 * For: add-int, sub-int, and-int, or-int, 3587 * xor-int, shl-int, shr-int, ushr-int 3588 */ 3589 /* binop vAA, vBB, vCC */ 3590 movzbl 2(rPC),%eax # eax<- BB 3591 movzbl 3(rPC),%ecx # ecx<- CC 3592 GET_VREG(%eax,%eax) # eax<- vBB 3593 addl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax 3594 movzbl rINST_HI,%ecx # ecx<- AA 3595 FETCH_INST_WORD(2) 3596 ADVANCE_PC(2) 3597 SET_VREG(%eax,%ecx) 3598 GOTO_NEXT 3599 3600 3601/* ------------------------------ */ 3602 .balign 64 3603.L_OP_SUB_INT: /* 0x91 */ 3604/* File: x86/OP_SUB_INT.S */ 3605/* File: x86/binop.S */ 3606 /* 3607 * Generic 32-bit binary operation. Provide an "instr" line that 3608 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)". 3609 * This could be an x86 instruction or a function call. (If the result 3610 * comes back in a register other than eax, you can override "result".) 3611 * 3612 * For: add-int, sub-int, and-int, or-int, 3613 * xor-int, shl-int, shr-int, ushr-int 3614 */ 3615 /* binop vAA, vBB, vCC */ 3616 movzbl 2(rPC),%eax # eax<- BB 3617 movzbl 3(rPC),%ecx # ecx<- CC 3618 GET_VREG(%eax,%eax) # eax<- vBB 3619 subl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax 3620 movzbl rINST_HI,%ecx # ecx<- AA 3621 FETCH_INST_WORD(2) 3622 ADVANCE_PC(2) 3623 SET_VREG(%eax,%ecx) 3624 GOTO_NEXT 3625 3626 3627/* ------------------------------ */ 3628 .balign 64 3629.L_OP_MUL_INT: /* 0x92 */ 3630/* File: x86/OP_MUL_INT.S */ 3631 /* 3632 * 32-bit binary multiplication. 3633 */ 3634 /* mul vAA, vBB, vCC */ 3635 movzbl 2(rPC),%eax # eax<- BB 3636 movzbl 3(rPC),%ecx # ecx<- CC 3637 SPILL(rPC) 3638 GET_VREG(%eax,%eax) # eax<- vBB 3639 imull (rFP,%ecx,4),%eax # trashes rPC/edx 3640 UNSPILL(rPC) 3641 movzbl rINST_HI,%ecx # ecx<- AA 3642 FETCH_INST_WORD(2) 3643 ADVANCE_PC(2) 3644 SET_VREG(%eax,%ecx) 3645 GOTO_NEXT 3646 3647/* ------------------------------ */ 3648 .balign 64 3649.L_OP_DIV_INT: /* 0x93 */ 3650/* File: x86/OP_DIV_INT.S */ 3651/* File: x86/bindiv.S */ 3652 3653 /* 3654 * 32-bit binary div/rem operation. Handles special case of op0=minint and 3655 * op1=-1. 3656 */ 3657 /* binop vAA, vBB, vCC */ 3658 movzbl 2(rPC),%eax # eax<- BB 3659 movzbl 3(rPC),%ecx # ecx<- CC 3660 GET_VREG(%eax,%eax) # eax<- vBB 3661 GET_VREG(%ecx,%ecx) # eax<- vBB 3662 SPILL(rPC) 3663 cmpl $0,%ecx 3664 je common_errDivideByZero 3665 cmpl $-1,%ecx 3666 jne .LOP_DIV_INT_continue_div 3667 cmpl $0x80000000,%eax 3668 jne .LOP_DIV_INT_continue_div 3669 movl $0x80000000,%eax 3670 jmp .LOP_DIV_INT_finish_div 3671 3672 3673 3674/* ------------------------------ */ 3675 .balign 64 3676.L_OP_REM_INT: /* 0x94 */ 3677/* File: x86/OP_REM_INT.S */ 3678/* File: x86/bindiv.S */ 3679 3680 /* 3681 * 32-bit binary div/rem operation. Handles special case of op0=minint and 3682 * op1=-1. 3683 */ 3684 /* binop vAA, vBB, vCC */ 3685 movzbl 2(rPC),%eax # eax<- BB 3686 movzbl 3(rPC),%ecx # ecx<- CC 3687 GET_VREG(%eax,%eax) # eax<- vBB 3688 GET_VREG(%ecx,%ecx) # eax<- vBB 3689 SPILL(rPC) 3690 cmpl $0,%ecx 3691 je common_errDivideByZero 3692 cmpl $-1,%ecx 3693 jne .LOP_REM_INT_continue_div 3694 cmpl $0x80000000,%eax 3695 jne .LOP_REM_INT_continue_div 3696 movl $0,%edx 3697 jmp .LOP_REM_INT_finish_div 3698 3699 3700 3701/* ------------------------------ */ 3702 .balign 64 3703.L_OP_AND_INT: /* 0x95 */ 3704/* File: x86/OP_AND_INT.S */ 3705/* File: x86/binop.S */ 3706 /* 3707 * Generic 32-bit binary operation. Provide an "instr" line that 3708 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)". 3709 * This could be an x86 instruction or a function call. (If the result 3710 * comes back in a register other than eax, you can override "result".) 3711 * 3712 * For: add-int, sub-int, and-int, or-int, 3713 * xor-int, shl-int, shr-int, ushr-int 3714 */ 3715 /* binop vAA, vBB, vCC */ 3716 movzbl 2(rPC),%eax # eax<- BB 3717 movzbl 3(rPC),%ecx # ecx<- CC 3718 GET_VREG(%eax,%eax) # eax<- vBB 3719 andl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax 3720 movzbl rINST_HI,%ecx # ecx<- AA 3721 FETCH_INST_WORD(2) 3722 ADVANCE_PC(2) 3723 SET_VREG(%eax,%ecx) 3724 GOTO_NEXT 3725 3726 3727/* ------------------------------ */ 3728 .balign 64 3729.L_OP_OR_INT: /* 0x96 */ 3730/* File: x86/OP_OR_INT.S */ 3731/* File: x86/binop.S */ 3732 /* 3733 * Generic 32-bit binary operation. Provide an "instr" line that 3734 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)". 3735 * This could be an x86 instruction or a function call. (If the result 3736 * comes back in a register other than eax, you can override "result".) 3737 * 3738 * For: add-int, sub-int, and-int, or-int, 3739 * xor-int, shl-int, shr-int, ushr-int 3740 */ 3741 /* binop vAA, vBB, vCC */ 3742 movzbl 2(rPC),%eax # eax<- BB 3743 movzbl 3(rPC),%ecx # ecx<- CC 3744 GET_VREG(%eax,%eax) # eax<- vBB 3745 orl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax 3746 movzbl rINST_HI,%ecx # ecx<- AA 3747 FETCH_INST_WORD(2) 3748 ADVANCE_PC(2) 3749 SET_VREG(%eax,%ecx) 3750 GOTO_NEXT 3751 3752 3753/* ------------------------------ */ 3754 .balign 64 3755.L_OP_XOR_INT: /* 0x97 */ 3756/* File: x86/OP_XOR_INT.S */ 3757/* File: x86/binop.S */ 3758 /* 3759 * Generic 32-bit binary operation. Provide an "instr" line that 3760 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)". 3761 * This could be an x86 instruction or a function call. (If the result 3762 * comes back in a register other than eax, you can override "result".) 3763 * 3764 * For: add-int, sub-int, and-int, or-int, 3765 * xor-int, shl-int, shr-int, ushr-int 3766 */ 3767 /* binop vAA, vBB, vCC */ 3768 movzbl 2(rPC),%eax # eax<- BB 3769 movzbl 3(rPC),%ecx # ecx<- CC 3770 GET_VREG(%eax,%eax) # eax<- vBB 3771 xorl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax 3772 movzbl rINST_HI,%ecx # ecx<- AA 3773 FETCH_INST_WORD(2) 3774 ADVANCE_PC(2) 3775 SET_VREG(%eax,%ecx) 3776 GOTO_NEXT 3777 3778 3779/* ------------------------------ */ 3780 .balign 64 3781.L_OP_SHL_INT: /* 0x98 */ 3782/* File: x86/OP_SHL_INT.S */ 3783/* File: x86/binop1.S */ 3784 /* 3785 * Generic 32-bit binary operation in which both operands loaded to 3786 * registers (op0 in eax, op1 in ecx). 3787 */ 3788 /* binop vAA, vBB, vCC */ 3789 movzbl 2(rPC),%eax # eax<- BB 3790 movzbl 3(rPC),%ecx # ecx<- CC 3791 GET_VREG(%eax,%eax) # eax<- vBB 3792 GET_VREG(%ecx,%ecx) # eax<- vBB 3793 sall %cl,%eax # ex: addl %ecx,%eax 3794 movzbl rINST_HI,%ecx # tmp<- AA 3795 FETCH_INST_WORD(2) 3796 ADVANCE_PC(2) 3797 SET_VREG(%eax,%ecx) 3798 GOTO_NEXT 3799 3800 3801/* ------------------------------ */ 3802 .balign 64 3803.L_OP_SHR_INT: /* 0x99 */ 3804/* File: x86/OP_SHR_INT.S */ 3805/* File: x86/binop1.S */ 3806 /* 3807 * Generic 32-bit binary operation in which both operands loaded to 3808 * registers (op0 in eax, op1 in ecx). 3809 */ 3810 /* binop vAA, vBB, vCC */ 3811 movzbl 2(rPC),%eax # eax<- BB 3812 movzbl 3(rPC),%ecx # ecx<- CC 3813 GET_VREG(%eax,%eax) # eax<- vBB 3814 GET_VREG(%ecx,%ecx) # eax<- vBB 3815 sarl %cl,%eax # ex: addl %ecx,%eax 3816 movzbl rINST_HI,%ecx # tmp<- AA 3817 FETCH_INST_WORD(2) 3818 ADVANCE_PC(2) 3819 SET_VREG(%eax,%ecx) 3820 GOTO_NEXT 3821 3822 3823/* ------------------------------ */ 3824 .balign 64 3825.L_OP_USHR_INT: /* 0x9a */ 3826/* File: x86/OP_USHR_INT.S */ 3827/* File: x86/binop1.S */ 3828 /* 3829 * Generic 32-bit binary operation in which both operands loaded to 3830 * registers (op0 in eax, op1 in ecx). 3831 */ 3832 /* binop vAA, vBB, vCC */ 3833 movzbl 2(rPC),%eax # eax<- BB 3834 movzbl 3(rPC),%ecx # ecx<- CC 3835 GET_VREG(%eax,%eax) # eax<- vBB 3836 GET_VREG(%ecx,%ecx) # eax<- vBB 3837 shrl %cl,%eax # ex: addl %ecx,%eax 3838 movzbl rINST_HI,%ecx # tmp<- AA 3839 FETCH_INST_WORD(2) 3840 ADVANCE_PC(2) 3841 SET_VREG(%eax,%ecx) 3842 GOTO_NEXT 3843 3844 3845/* ------------------------------ */ 3846 .balign 64 3847.L_OP_ADD_LONG: /* 0x9b */ 3848/* File: x86/OP_ADD_LONG.S */ 3849/* File: x86/binopWide.S */ 3850 /* 3851 * Generic 64-bit binary operation. 3852 */ 3853 /* binop vAA, vBB, vCC */ 3854 3855 movzbl 2(rPC),%eax # eax<- BB 3856 movzbl 3(rPC),%ecx # ecx<- CC 3857 SPILL(rPC) 3858 GET_VREG_WORD(rPC,%eax,0) # rPC<- v[BB+0] 3859 GET_VREG_WORD(%eax,%eax,1) # eax<- v[BB+1] 3860 addl (rFP,%ecx,4),rPC # ex: addl (rFP,%ecx,4),rPC 3861 adcl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax 3862 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA 3863 SET_VREG_WORD(rPC,rINST_FULL,0) # v[AA+0] <- rPC 3864 UNSPILL(rPC) 3865 SET_VREG_WORD(%eax,rINST_FULL,1) # v[AA+1] <- eax 3866 FETCH_INST_WORD(2) 3867 ADVANCE_PC(2) 3868 GOTO_NEXT 3869 3870 3871/* ------------------------------ */ 3872 .balign 64 3873.L_OP_SUB_LONG: /* 0x9c */ 3874/* File: x86/OP_SUB_LONG.S */ 3875/* File: x86/binopWide.S */ 3876 /* 3877 * Generic 64-bit binary operation. 3878 */ 3879 /* binop vAA, vBB, vCC */ 3880 3881 movzbl 2(rPC),%eax # eax<- BB 3882 movzbl 3(rPC),%ecx # ecx<- CC 3883 SPILL(rPC) 3884 GET_VREG_WORD(rPC,%eax,0) # rPC<- v[BB+0] 3885 GET_VREG_WORD(%eax,%eax,1) # eax<- v[BB+1] 3886 subl (rFP,%ecx,4),rPC # ex: addl (rFP,%ecx,4),rPC 3887 sbbl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax 3888 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA 3889 SET_VREG_WORD(rPC,rINST_FULL,0) # v[AA+0] <- rPC 3890 UNSPILL(rPC) 3891 SET_VREG_WORD(%eax,rINST_FULL,1) # v[AA+1] <- eax 3892 FETCH_INST_WORD(2) 3893 ADVANCE_PC(2) 3894 GOTO_NEXT 3895 3896 3897/* ------------------------------ */ 3898 .balign 64 3899.L_OP_MUL_LONG: /* 0x9d */ 3900/* File: x86/OP_MUL_LONG.S */ 3901 /* 3902 * Signed 64-bit integer multiply. 3903 * 3904 * We could definately use more free registers for 3905 * this code. We must spill rPC (edx) because it 3906 * is used by imul. We'll also spill rINST (ebx), 3907 * giving us eax, ebc, ecx and edx as computational 3908 * temps. On top of that, we'll spill rIBASE (edi) 3909 * for use as the vB pointer and rFP (esi) for use 3910 * as the vC pointer. Yuck. 3911 */ 3912 /* mul-long vAA, vBB, vCC */ 3913 movzbl 2(rPC),%eax # eax<- B 3914 movzbl 3(rPC),%ecx # ecx<- C 3915 SPILL(rPC) 3916 SPILL(rIBASE) 3917 SPILL(rFP) 3918 SPILL(rINST_FULL) 3919 leal (rFP,%eax,4),rIBASE # rIBASE<- &v[B] 3920 leal (rFP,%ecx,4),rFP # rFP<- &v[C] 3921 movl 4(rIBASE),%ecx # ecx<- Bmsw 3922 imull (rFP),%ecx # ecx<- (Bmsw*Clsw) 3923 movl 4(rFP),%eax # eax<- Cmsw 3924 imull (rIBASE),%eax # eax<- (Cmsw*Blsw) 3925 addl %eax,%ecx # ecx<- (Bmsw*Clsw)+(Cmsw*Blsw) 3926 movl (rFP),%eax # eax<- Clsw 3927 mull (rIBASE) # eax<- (Clsw*Alsw) 3928 UNSPILL(rINST_FULL) 3929 UNSPILL(rFP) 3930 jmp .LOP_MUL_LONG_continue 3931 3932/* ------------------------------ */ 3933 .balign 64 3934.L_OP_DIV_LONG: /* 0x9e */ 3935/* File: x86/OP_DIV_LONG.S */ 3936 /* div vAA, vBB, vCC */ 3937 movzbl 3(rPC),%eax # eax<- CC 3938 movzbl 2(rPC),%ecx # ecx<- BB 3939 SPILL(rPC) 3940 GET_VREG_WORD(rPC,%eax,0) 3941 GET_VREG_WORD(%eax,%eax,1) 3942 movl rPC,OUT_ARG2(%esp) 3943 testl %eax,%eax 3944 je .LOP_DIV_LONG_check_zero 3945 cmpl $-1,%eax 3946 je .LOP_DIV_LONG_check_neg1 3947.LOP_DIV_LONG_notSpecial: 3948 GET_VREG_WORD(rPC,%ecx,0) 3949 GET_VREG_WORD(%ecx,%ecx,1) 3950.LOP_DIV_LONG_notSpecial1: 3951 movl %eax,OUT_ARG3(%esp) 3952 movl rPC,OUT_ARG0(%esp) 3953 movl %ecx,OUT_ARG1(%esp) 3954 jmp .LOP_DIV_LONG_continue 3955 3956/* ------------------------------ */ 3957 .balign 64 3958.L_OP_REM_LONG: /* 0x9f */ 3959/* File: x86/OP_REM_LONG.S */ 3960/* File: x86/OP_DIV_LONG.S */ 3961 /* div vAA, vBB, vCC */ 3962 movzbl 3(rPC),%eax # eax<- CC 3963 movzbl 2(rPC),%ecx # ecx<- BB 3964 SPILL(rPC) 3965 GET_VREG_WORD(rPC,%eax,0) 3966 GET_VREG_WORD(%eax,%eax,1) 3967 movl rPC,OUT_ARG2(%esp) 3968 testl %eax,%eax 3969 je .LOP_REM_LONG_check_zero 3970 cmpl $-1,%eax 3971 je .LOP_REM_LONG_check_neg1 3972.LOP_REM_LONG_notSpecial: 3973 GET_VREG_WORD(rPC,%ecx,0) 3974 GET_VREG_WORD(%ecx,%ecx,1) 3975.LOP_REM_LONG_notSpecial1: 3976 movl %eax,OUT_ARG3(%esp) 3977 movl rPC,OUT_ARG0(%esp) 3978 movl %ecx,OUT_ARG1(%esp) 3979 jmp .LOP_REM_LONG_continue 3980 3981 3982/* ------------------------------ */ 3983 .balign 64 3984.L_OP_AND_LONG: /* 0xa0 */ 3985/* File: x86/OP_AND_LONG.S */ 3986/* File: x86/binopWide.S */ 3987 /* 3988 * Generic 64-bit binary operation. 3989 */ 3990 /* binop vAA, vBB, vCC */ 3991 3992 movzbl 2(rPC),%eax # eax<- BB 3993 movzbl 3(rPC),%ecx # ecx<- CC 3994 SPILL(rPC) 3995 GET_VREG_WORD(rPC,%eax,0) # rPC<- v[BB+0] 3996 GET_VREG_WORD(%eax,%eax,1) # eax<- v[BB+1] 3997 andl (rFP,%ecx,4),rPC # ex: addl (rFP,%ecx,4),rPC 3998 andl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax 3999 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA 4000 SET_VREG_WORD(rPC,rINST_FULL,0) # v[AA+0] <- rPC 4001 UNSPILL(rPC) 4002 SET_VREG_WORD(%eax,rINST_FULL,1) # v[AA+1] <- eax 4003 FETCH_INST_WORD(2) 4004 ADVANCE_PC(2) 4005 GOTO_NEXT 4006 4007 4008/* ------------------------------ */ 4009 .balign 64 4010.L_OP_OR_LONG: /* 0xa1 */ 4011/* File: x86/OP_OR_LONG.S */ 4012/* File: x86/binopWide.S */ 4013 /* 4014 * Generic 64-bit binary operation. 4015 */ 4016 /* binop vAA, vBB, vCC */ 4017 4018 movzbl 2(rPC),%eax # eax<- BB 4019 movzbl 3(rPC),%ecx # ecx<- CC 4020 SPILL(rPC) 4021 GET_VREG_WORD(rPC,%eax,0) # rPC<- v[BB+0] 4022 GET_VREG_WORD(%eax,%eax,1) # eax<- v[BB+1] 4023 orl (rFP,%ecx,4),rPC # ex: addl (rFP,%ecx,4),rPC 4024 orl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax 4025 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA 4026 SET_VREG_WORD(rPC,rINST_FULL,0) # v[AA+0] <- rPC 4027 UNSPILL(rPC) 4028 SET_VREG_WORD(%eax,rINST_FULL,1) # v[AA+1] <- eax 4029 FETCH_INST_WORD(2) 4030 ADVANCE_PC(2) 4031 GOTO_NEXT 4032 4033 4034/* ------------------------------ */ 4035 .balign 64 4036.L_OP_XOR_LONG: /* 0xa2 */ 4037/* File: x86/OP_XOR_LONG.S */ 4038/* File: x86/binopWide.S */ 4039 /* 4040 * Generic 64-bit binary operation. 4041 */ 4042 /* binop vAA, vBB, vCC */ 4043 4044 movzbl 2(rPC),%eax # eax<- BB 4045 movzbl 3(rPC),%ecx # ecx<- CC 4046 SPILL(rPC) 4047 GET_VREG_WORD(rPC,%eax,0) # rPC<- v[BB+0] 4048 GET_VREG_WORD(%eax,%eax,1) # eax<- v[BB+1] 4049 xorl (rFP,%ecx,4),rPC # ex: addl (rFP,%ecx,4),rPC 4050 xorl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax 4051 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA 4052 SET_VREG_WORD(rPC,rINST_FULL,0) # v[AA+0] <- rPC 4053 UNSPILL(rPC) 4054 SET_VREG_WORD(%eax,rINST_FULL,1) # v[AA+1] <- eax 4055 FETCH_INST_WORD(2) 4056 ADVANCE_PC(2) 4057 GOTO_NEXT 4058 4059 4060/* ------------------------------ */ 4061 .balign 64 4062.L_OP_SHL_LONG: /* 0xa3 */ 4063/* File: x86/OP_SHL_LONG.S */ 4064 /* 4065 * Long integer shift. This is different from the generic 32/64-bit 4066 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4067 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4068 * 6 bits of the shift distance. x86 shifts automatically mask off 4069 * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31 4070 * case specially. 4071 */ 4072 /* shl-long vAA, vBB, vCC */ 4073 /* ecx gets shift count */ 4074 /* Need to spill edx */ 4075 /* rINST gets AA */ 4076 movzbl 2(rPC),%eax # eax<- BB 4077 movzbl 3(rPC),%ecx # ecx<- CC 4078 SPILL(rPC) # spill edx 4079 GET_VREG_WORD(%edx,%eax,1) # ecx<- v[BB+1] 4080 GET_VREG (%ecx,%ecx) # ecx<- vCC 4081 GET_VREG_WORD(%eax,%eax,0) # eax<- v[BB+0] 4082 shldl %eax,%edx 4083 sall %cl,%eax 4084 testb $32,%cl 4085 je 2f 4086 movl %eax,%edx 4087 xorl %eax,%eax 40882: 4089 movzbl rINST_HI,%ecx 4090 SET_VREG_WORD(%edx,%ecx,1) # v[AA+1]<- %edx 4091 UNSPILL(rPC) 4092 FETCH_INST_WORD(2) 4093 jmp .LOP_SHL_LONG_finish 4094 4095/* ------------------------------ */ 4096 .balign 64 4097.L_OP_SHR_LONG: /* 0xa4 */ 4098/* File: x86/OP_SHR_LONG.S */ 4099 /* 4100 * Long integer shift. This is different from the generic 32/64-bit 4101 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4102 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4103 * 6 bits of the shift distance. x86 shifts automatically mask off 4104 * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31 4105 * case specially. 4106 */ 4107 /* shr-long vAA, vBB, vCC */ 4108 /* ecx gets shift count */ 4109 /* Need to spill edx */ 4110 /* rINST gets AA */ 4111 movzbl 2(rPC),%eax # eax<- BB 4112 movzbl 3(rPC),%ecx # ecx<- CC 4113 SPILL(rPC) # spill edx 4114 GET_VREG_WORD(%edx,%eax,1) # edx<- v[BB+1] 4115 GET_VREG (%ecx,%ecx) # ecx<- vCC 4116 GET_VREG_WORD(%eax,%eax,0) # eax<- v[BB+0] 4117 shrdl %edx,%eax 4118 sarl %cl,%edx 4119 testb $32,%cl 4120 je 2f 4121 movl %edx,%eax 4122 sarl $31,%edx 41232: 4124 movzbl rINST_HI,%ecx 4125 SET_VREG_WORD(%edx,%ecx,1) # v[AA+1]<- edx 4126 UNSPILL(rPC) 4127 FETCH_INST_WORD(2) 4128 jmp .LOP_SHR_LONG_finish 4129 4130/* ------------------------------ */ 4131 .balign 64 4132.L_OP_USHR_LONG: /* 0xa5 */ 4133/* File: x86/OP_USHR_LONG.S */ 4134 /* 4135 * Long integer shift. This is different from the generic 32/64-bit 4136 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4137 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4138 * 6 bits of the shift distance. x86 shifts automatically mask off 4139 * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31 4140 * case specially. 4141 */ 4142 /* shr-long vAA, vBB, vCC */ 4143 /* ecx gets shift count */ 4144 /* Need to spill edx */ 4145 /* rINST gets AA */ 4146 movzbl 2(rPC),%eax # eax<- BB 4147 movzbl 3(rPC),%ecx # ecx<- CC 4148 SPILL(rPC) # spill edx 4149 GET_VREG_WORD(%edx,%eax,1) # edx<- v[BB+1] 4150 GET_VREG (%ecx,%ecx) # ecx<- vCC 4151 GET_VREG_WORD(%eax,%eax,0) # eax<- v[BB+0] 4152 shrdl %edx,%eax 4153 shrl %cl,%edx 4154 testb $32,%cl 4155 je 2f 4156 movl %edx,%eax 4157 xorl %edx,%edx 41582: 4159 movzbl rINST_HI,%ecx 4160 SET_VREG_WORD(%edx,%ecx,1) # v[BB+1]<- edx 4161 UNSPILL(rPC) 4162 jmp .LOP_USHR_LONG_finish 4163 4164/* ------------------------------ */ 4165 .balign 64 4166.L_OP_ADD_FLOAT: /* 0xa6 */ 4167/* File: x86/OP_ADD_FLOAT.S */ 4168/* File: x86/binflop.S */ 4169 /* 4170 * Generic 32-bit binary float operation. 4171 * 4172 * For: add-fp, sub-fp, mul-fp, div-fp 4173 */ 4174 /* binop vAA, vBB, vCC */ 4175 movzbl 2(rPC),%eax # eax<- CC 4176 movzbl 3(rPC),%ecx # ecx<- BB 4177 flds (rFP,%eax,4) # vCC to fp stack 4178 fadds (rFP,%ecx,4) # ex: faddp 4179 movzbl rINST_HI,%ecx # ecx<- AA 4180 FETCH_INST_WORD(2) 4181 ADVANCE_PC(2) 4182 fstps (rFP,%ecx,4) # %st to vAA 4183 GOTO_NEXT 4184 4185 4186/* ------------------------------ */ 4187 .balign 64 4188.L_OP_SUB_FLOAT: /* 0xa7 */ 4189/* File: x86/OP_SUB_FLOAT.S */ 4190/* File: x86/binflop.S */ 4191 /* 4192 * Generic 32-bit binary float operation. 4193 * 4194 * For: add-fp, sub-fp, mul-fp, div-fp 4195 */ 4196 /* binop vAA, vBB, vCC */ 4197 movzbl 2(rPC),%eax # eax<- CC 4198 movzbl 3(rPC),%ecx # ecx<- BB 4199 flds (rFP,%eax,4) # vCC to fp stack 4200 fsubs (rFP,%ecx,4) # ex: faddp 4201 movzbl rINST_HI,%ecx # ecx<- AA 4202 FETCH_INST_WORD(2) 4203 ADVANCE_PC(2) 4204 fstps (rFP,%ecx,4) # %st to vAA 4205 GOTO_NEXT 4206 4207 4208/* ------------------------------ */ 4209 .balign 64 4210.L_OP_MUL_FLOAT: /* 0xa8 */ 4211/* File: x86/OP_MUL_FLOAT.S */ 4212/* File: x86/binflop.S */ 4213 /* 4214 * Generic 32-bit binary float operation. 4215 * 4216 * For: add-fp, sub-fp, mul-fp, div-fp 4217 */ 4218 /* binop vAA, vBB, vCC */ 4219 movzbl 2(rPC),%eax # eax<- CC 4220 movzbl 3(rPC),%ecx # ecx<- BB 4221 flds (rFP,%eax,4) # vCC to fp stack 4222 fmuls (rFP,%ecx,4) # ex: faddp 4223 movzbl rINST_HI,%ecx # ecx<- AA 4224 FETCH_INST_WORD(2) 4225 ADVANCE_PC(2) 4226 fstps (rFP,%ecx,4) # %st to vAA 4227 GOTO_NEXT 4228 4229 4230/* ------------------------------ */ 4231 .balign 64 4232.L_OP_DIV_FLOAT: /* 0xa9 */ 4233/* File: x86/OP_DIV_FLOAT.S */ 4234/* File: x86/binflop.S */ 4235 /* 4236 * Generic 32-bit binary float operation. 4237 * 4238 * For: add-fp, sub-fp, mul-fp, div-fp 4239 */ 4240 /* binop vAA, vBB, vCC */ 4241 movzbl 2(rPC),%eax # eax<- CC 4242 movzbl 3(rPC),%ecx # ecx<- BB 4243 flds (rFP,%eax,4) # vCC to fp stack 4244 fdivs (rFP,%ecx,4) # ex: faddp 4245 movzbl rINST_HI,%ecx # ecx<- AA 4246 FETCH_INST_WORD(2) 4247 ADVANCE_PC(2) 4248 fstps (rFP,%ecx,4) # %st to vAA 4249 GOTO_NEXT 4250 4251 4252/* ------------------------------ */ 4253 .balign 64 4254.L_OP_REM_FLOAT: /* 0xaa */ 4255/* File: x86/OP_REM_FLOAT.S */ 4256 /* rem_float vAA, vBB, vCC */ 4257 movzbl 3(rPC),%ecx # ecx<- BB 4258 movzbl 2(rPC),%eax # eax<- CC 4259 flds (rFP,%ecx,4) # vCC to fp stack 4260 flds (rFP,%eax,4) # vCC to fp stack 4261 movzbl rINST_HI,%ecx # ecx<- AA 4262 FETCH_INST_WORD(2) 42631: 4264 fprem 4265 fstsw %ax 4266 sahf 4267 jp 1b 4268 fstp %st(1) 4269 ADVANCE_PC(2) 4270 fstps (rFP,%ecx,4) # %st to vAA 4271 GOTO_NEXT 4272 4273/* ------------------------------ */ 4274 .balign 64 4275.L_OP_ADD_DOUBLE: /* 0xab */ 4276/* File: x86/OP_ADD_DOUBLE.S */ 4277/* File: x86/binflop.S */ 4278 /* 4279 * Generic 32-bit binary float operation. 4280 * 4281 * For: add-fp, sub-fp, mul-fp, div-fp 4282 */ 4283 /* binop vAA, vBB, vCC */ 4284 movzbl 2(rPC),%eax # eax<- CC 4285 movzbl 3(rPC),%ecx # ecx<- BB 4286 fldl (rFP,%eax,4) # vCC to fp stack 4287 faddl (rFP,%ecx,4) # ex: faddp 4288 movzbl rINST_HI,%ecx # ecx<- AA 4289 FETCH_INST_WORD(2) 4290 ADVANCE_PC(2) 4291 fstpl (rFP,%ecx,4) # %st to vAA 4292 GOTO_NEXT 4293 4294 4295/* ------------------------------ */ 4296 .balign 64 4297.L_OP_SUB_DOUBLE: /* 0xac */ 4298/* File: x86/OP_SUB_DOUBLE.S */ 4299/* File: x86/binflop.S */ 4300 /* 4301 * Generic 32-bit binary float operation. 4302 * 4303 * For: add-fp, sub-fp, mul-fp, div-fp 4304 */ 4305 /* binop vAA, vBB, vCC */ 4306 movzbl 2(rPC),%eax # eax<- CC 4307 movzbl 3(rPC),%ecx # ecx<- BB 4308 fldl (rFP,%eax,4) # vCC to fp stack 4309 fsubl (rFP,%ecx,4) # ex: faddp 4310 movzbl rINST_HI,%ecx # ecx<- AA 4311 FETCH_INST_WORD(2) 4312 ADVANCE_PC(2) 4313 fstpl (rFP,%ecx,4) # %st to vAA 4314 GOTO_NEXT 4315 4316 4317/* ------------------------------ */ 4318 .balign 64 4319.L_OP_MUL_DOUBLE: /* 0xad */ 4320/* File: x86/OP_MUL_DOUBLE.S */ 4321/* File: x86/binflop.S */ 4322 /* 4323 * Generic 32-bit binary float operation. 4324 * 4325 * For: add-fp, sub-fp, mul-fp, div-fp 4326 */ 4327 /* binop vAA, vBB, vCC */ 4328 movzbl 2(rPC),%eax # eax<- CC 4329 movzbl 3(rPC),%ecx # ecx<- BB 4330 fldl (rFP,%eax,4) # vCC to fp stack 4331 fmull (rFP,%ecx,4) # ex: faddp 4332 movzbl rINST_HI,%ecx # ecx<- AA 4333 FETCH_INST_WORD(2) 4334 ADVANCE_PC(2) 4335 fstpl (rFP,%ecx,4) # %st to vAA 4336 GOTO_NEXT 4337 4338 4339/* ------------------------------ */ 4340 .balign 64 4341.L_OP_DIV_DOUBLE: /* 0xae */ 4342/* File: x86/OP_DIV_DOUBLE.S */ 4343/* File: x86/binflop.S */ 4344 /* 4345 * Generic 32-bit binary float operation. 4346 * 4347 * For: add-fp, sub-fp, mul-fp, div-fp 4348 */ 4349 /* binop vAA, vBB, vCC */ 4350 movzbl 2(rPC),%eax # eax<- CC 4351 movzbl 3(rPC),%ecx # ecx<- BB 4352 fldl (rFP,%eax,4) # vCC to fp stack 4353 fdivl (rFP,%ecx,4) # ex: faddp 4354 movzbl rINST_HI,%ecx # ecx<- AA 4355 FETCH_INST_WORD(2) 4356 ADVANCE_PC(2) 4357 fstpl (rFP,%ecx,4) # %st to vAA 4358 GOTO_NEXT 4359 4360 4361/* ------------------------------ */ 4362 .balign 64 4363.L_OP_REM_DOUBLE: /* 0xaf */ 4364/* File: x86/OP_REM_DOUBLE.S */ 4365 /* rem_float vAA, vBB, vCC */ 4366 movzbl 3(rPC),%ecx # ecx<- BB 4367 movzbl 2(rPC),%eax # eax<- CC 4368 fldl (rFP,%ecx,4) # vCC to fp stack 4369 fldl (rFP,%eax,4) # vCC to fp stack 4370 movzbl rINST_HI,%ecx # ecx<- AA 4371 FETCH_INST_WORD(2) 43721: 4373 fprem 4374 fstsw %ax 4375 sahf 4376 jp 1b 4377 fstp %st(1) 4378 ADVANCE_PC(2) 4379 fstpl (rFP,%ecx,4) # %st to vAA 4380 GOTO_NEXT 4381 4382/* ------------------------------ */ 4383 .balign 64 4384.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 4385/* File: x86/OP_ADD_INT_2ADDR.S */ 4386/* File: x86/binop2addr.S */ 4387 /* 4388 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 4389 * that specifies an instruction that performs "result = r0 op r1". 4390 * This could be an ARM instruction or a function call. (If the result 4391 * comes back in a register other than r0, you can override "result".) 4392 * 4393 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4394 * vCC (r1). Useful for integer division and modulus. 4395 * 4396 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 4397 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 4398 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 4399 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 4400 */ 4401 /* binop/2addr vA, vB */ 4402 movzx rINST_HI,%ecx # ecx<- A+ 4403 sarl $12,rINST_FULL # rINST_FULL<- B 4404 GET_VREG(%eax,rINST_FULL) # eax<- vB 4405 FETCH_INST_WORD(1) 4406 andb $0xf,%cl # ecx<- A 4407 addl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4) 4408 ADVANCE_PC(1) 4409 GOTO_NEXT 4410 4411 4412/* ------------------------------ */ 4413 .balign 64 4414.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 4415/* File: x86/OP_SUB_INT_2ADDR.S */ 4416/* File: x86/binop2addr.S */ 4417 /* 4418 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 4419 * that specifies an instruction that performs "result = r0 op r1". 4420 * This could be an ARM instruction or a function call. (If the result 4421 * comes back in a register other than r0, you can override "result".) 4422 * 4423 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4424 * vCC (r1). Useful for integer division and modulus. 4425 * 4426 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 4427 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 4428 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 4429 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 4430 */ 4431 /* binop/2addr vA, vB */ 4432 movzx rINST_HI,%ecx # ecx<- A+ 4433 sarl $12,rINST_FULL # rINST_FULL<- B 4434 GET_VREG(%eax,rINST_FULL) # eax<- vB 4435 FETCH_INST_WORD(1) 4436 andb $0xf,%cl # ecx<- A 4437 subl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4) 4438 ADVANCE_PC(1) 4439 GOTO_NEXT 4440 4441 4442/* ------------------------------ */ 4443 .balign 64 4444.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 4445/* File: x86/OP_MUL_INT_2ADDR.S */ 4446 /* mul vA, vB */ 4447 movzx rINST_HI,%ecx # ecx<- A+ 4448 sarl $12,rINST_FULL # rINST_FULL<- B 4449 GET_VREG(%eax,rINST_FULL) # eax<- vB 4450 andb $0xf,%cl # ecx<- A 4451 SPILL(rPC) 4452 imull (rFP,%ecx,4),%eax 4453 UNSPILL(rPC) 4454 SET_VREG(%eax,%ecx) 4455 FETCH_INST_WORD(1) 4456 ADVANCE_PC(1) 4457 GOTO_NEXT 4458 4459/* ------------------------------ */ 4460 .balign 64 4461.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 4462/* File: x86/OP_DIV_INT_2ADDR.S */ 4463/* File: x86/bindiv2addr.S */ 4464 /* 4465 * 32-bit binary div/rem operation. Handles special case of op0=minint and 4466 * op1=-1. 4467 */ 4468 /* div/rem/2addr vA, vB */ 4469 movzx rINST_HI,%ecx # eax<- BA 4470 sarl $4,%ecx # ecx<- B 4471 GET_VREG(%ecx,%ecx) # eax<- vBB 4472 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 4473 andb $0xf,rINST_LO # rINST_FULL<- A 4474 GET_VREG(%eax,rINST_FULL) # eax<- vBB 4475 SPILL(rPC) 4476 cmpl $0,%ecx 4477 je common_errDivideByZero 4478 cmpl $-1,%ecx 4479 jne .LOP_DIV_INT_2ADDR_continue_div2addr 4480 cmpl $0x80000000,%eax 4481 jne .LOP_DIV_INT_2ADDR_continue_div2addr 4482 movl $0x80000000,%eax 4483 jmp .LOP_DIV_INT_2ADDR_finish_div2addr 4484 4485 4486 4487/* ------------------------------ */ 4488 .balign 64 4489.L_OP_REM_INT_2ADDR: /* 0xb4 */ 4490/* File: x86/OP_REM_INT_2ADDR.S */ 4491/* File: x86/bindiv2addr.S */ 4492 /* 4493 * 32-bit binary div/rem operation. Handles special case of op0=minint and 4494 * op1=-1. 4495 */ 4496 /* div/rem/2addr vA, vB */ 4497 movzx rINST_HI,%ecx # eax<- BA 4498 sarl $4,%ecx # ecx<- B 4499 GET_VREG(%ecx,%ecx) # eax<- vBB 4500 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 4501 andb $0xf,rINST_LO # rINST_FULL<- A 4502 GET_VREG(%eax,rINST_FULL) # eax<- vBB 4503 SPILL(rPC) 4504 cmpl $0,%ecx 4505 je common_errDivideByZero 4506 cmpl $-1,%ecx 4507 jne .LOP_REM_INT_2ADDR_continue_div2addr 4508 cmpl $0x80000000,%eax 4509 jne .LOP_REM_INT_2ADDR_continue_div2addr 4510 movl $0,%edx 4511 jmp .LOP_REM_INT_2ADDR_finish_div2addr 4512 4513 4514 4515/* ------------------------------ */ 4516 .balign 64 4517.L_OP_AND_INT_2ADDR: /* 0xb5 */ 4518/* File: x86/OP_AND_INT_2ADDR.S */ 4519/* File: x86/binop2addr.S */ 4520 /* 4521 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 4522 * that specifies an instruction that performs "result = r0 op r1". 4523 * This could be an ARM instruction or a function call. (If the result 4524 * comes back in a register other than r0, you can override "result".) 4525 * 4526 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4527 * vCC (r1). Useful for integer division and modulus. 4528 * 4529 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 4530 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 4531 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 4532 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 4533 */ 4534 /* binop/2addr vA, vB */ 4535 movzx rINST_HI,%ecx # ecx<- A+ 4536 sarl $12,rINST_FULL # rINST_FULL<- B 4537 GET_VREG(%eax,rINST_FULL) # eax<- vB 4538 FETCH_INST_WORD(1) 4539 andb $0xf,%cl # ecx<- A 4540 andl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4) 4541 ADVANCE_PC(1) 4542 GOTO_NEXT 4543 4544 4545/* ------------------------------ */ 4546 .balign 64 4547.L_OP_OR_INT_2ADDR: /* 0xb6 */ 4548/* File: x86/OP_OR_INT_2ADDR.S */ 4549/* File: x86/binop2addr.S */ 4550 /* 4551 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 4552 * that specifies an instruction that performs "result = r0 op r1". 4553 * This could be an ARM instruction or a function call. (If the result 4554 * comes back in a register other than r0, you can override "result".) 4555 * 4556 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4557 * vCC (r1). Useful for integer division and modulus. 4558 * 4559 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 4560 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 4561 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 4562 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 4563 */ 4564 /* binop/2addr vA, vB */ 4565 movzx rINST_HI,%ecx # ecx<- A+ 4566 sarl $12,rINST_FULL # rINST_FULL<- B 4567 GET_VREG(%eax,rINST_FULL) # eax<- vB 4568 FETCH_INST_WORD(1) 4569 andb $0xf,%cl # ecx<- A 4570 orl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4) 4571 ADVANCE_PC(1) 4572 GOTO_NEXT 4573 4574 4575/* ------------------------------ */ 4576 .balign 64 4577.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 4578/* File: x86/OP_XOR_INT_2ADDR.S */ 4579/* File: x86/binop2addr.S */ 4580 /* 4581 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 4582 * that specifies an instruction that performs "result = r0 op r1". 4583 * This could be an ARM instruction or a function call. (If the result 4584 * comes back in a register other than r0, you can override "result".) 4585 * 4586 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4587 * vCC (r1). Useful for integer division and modulus. 4588 * 4589 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 4590 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 4591 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 4592 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 4593 */ 4594 /* binop/2addr vA, vB */ 4595 movzx rINST_HI,%ecx # ecx<- A+ 4596 sarl $12,rINST_FULL # rINST_FULL<- B 4597 GET_VREG(%eax,rINST_FULL) # eax<- vB 4598 FETCH_INST_WORD(1) 4599 andb $0xf,%cl # ecx<- A 4600 xorl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4) 4601 ADVANCE_PC(1) 4602 GOTO_NEXT 4603 4604 4605/* ------------------------------ */ 4606 .balign 64 4607.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 4608/* File: x86/OP_SHL_INT_2ADDR.S */ 4609/* File: x86/shop2addr.S */ 4610 /* 4611 * Generic 32-bit "shift/2addr" operation. 4612 */ 4613 /* shift/2addr vA, vB */ 4614 movzx rINST_HI,%ecx # eax<- BA 4615 sarl $4,%ecx # ecx<- B 4616 GET_VREG(%ecx,%ecx) # eax<- vBB 4617 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 4618 andb $0xf,rINST_LO # rINST_FULL<- A 4619 GET_VREG(%eax,rINST_FULL) # eax<- vAA 4620 sall %cl,%eax # ex: sarl %cl,%eax 4621 SET_VREG(%eax,rINST_FULL) 4622 FETCH_INST_WORD(1) 4623 ADVANCE_PC(1) 4624 GOTO_NEXT 4625 4626 4627/* ------------------------------ */ 4628 .balign 64 4629.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 4630/* File: x86/OP_SHR_INT_2ADDR.S */ 4631/* File: x86/shop2addr.S */ 4632 /* 4633 * Generic 32-bit "shift/2addr" operation. 4634 */ 4635 /* shift/2addr vA, vB */ 4636 movzx rINST_HI,%ecx # eax<- BA 4637 sarl $4,%ecx # ecx<- B 4638 GET_VREG(%ecx,%ecx) # eax<- vBB 4639 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 4640 andb $0xf,rINST_LO # rINST_FULL<- A 4641 GET_VREG(%eax,rINST_FULL) # eax<- vAA 4642 sarl %cl,%eax # ex: sarl %cl,%eax 4643 SET_VREG(%eax,rINST_FULL) 4644 FETCH_INST_WORD(1) 4645 ADVANCE_PC(1) 4646 GOTO_NEXT 4647 4648 4649/* ------------------------------ */ 4650 .balign 64 4651.L_OP_USHR_INT_2ADDR: /* 0xba */ 4652/* File: x86/OP_USHR_INT_2ADDR.S */ 4653/* File: x86/shop2addr.S */ 4654 /* 4655 * Generic 32-bit "shift/2addr" operation. 4656 */ 4657 /* shift/2addr vA, vB */ 4658 movzx rINST_HI,%ecx # eax<- BA 4659 sarl $4,%ecx # ecx<- B 4660 GET_VREG(%ecx,%ecx) # eax<- vBB 4661 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 4662 andb $0xf,rINST_LO # rINST_FULL<- A 4663 GET_VREG(%eax,rINST_FULL) # eax<- vAA 4664 shrl %cl,%eax # ex: sarl %cl,%eax 4665 SET_VREG(%eax,rINST_FULL) 4666 FETCH_INST_WORD(1) 4667 ADVANCE_PC(1) 4668 GOTO_NEXT 4669 4670 4671/* ------------------------------ */ 4672 .balign 64 4673.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 4674/* File: x86/OP_ADD_LONG_2ADDR.S */ 4675/* File: x86/binopWide2addr.S */ 4676 /* 4677 * Generic 64-bit binary operation. 4678 */ 4679 /* binop/2addr vA, vB */ 4680 movzbl rINST_HI,%ecx # ecx<- BA 4681 sarl $4,%ecx # ecx<- B 4682 GET_VREG_WORD(%eax,%ecx,0) # eax<- v[B+0] 4683 GET_VREG_WORD(%ecx,%ecx,1) # eax<- v[B+1] 4684 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 4685 andb $0xF,rINST_LO # rINST_FULL<- A 4686 addl %eax,(rFP,rINST_FULL,4) # example: addl %eax,(rFP,rINST_FULL,4) 4687 adcl %ecx,4(rFP,rINST_FULL,4) # example: adcl %ecx,4(rFP,rINST_FULL,4) 4688 FETCH_INST_WORD(1) 4689 ADVANCE_PC(1) 4690 GOTO_NEXT 4691 4692 4693/* ------------------------------ */ 4694 .balign 64 4695.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 4696/* File: x86/OP_SUB_LONG_2ADDR.S */ 4697/* File: x86/binopWide2addr.S */ 4698 /* 4699 * Generic 64-bit binary operation. 4700 */ 4701 /* binop/2addr vA, vB */ 4702 movzbl rINST_HI,%ecx # ecx<- BA 4703 sarl $4,%ecx # ecx<- B 4704 GET_VREG_WORD(%eax,%ecx,0) # eax<- v[B+0] 4705 GET_VREG_WORD(%ecx,%ecx,1) # eax<- v[B+1] 4706 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 4707 andb $0xF,rINST_LO # rINST_FULL<- A 4708 subl %eax,(rFP,rINST_FULL,4) # example: addl %eax,(rFP,rINST_FULL,4) 4709 sbbl %ecx,4(rFP,rINST_FULL,4) # example: adcl %ecx,4(rFP,rINST_FULL,4) 4710 FETCH_INST_WORD(1) 4711 ADVANCE_PC(1) 4712 GOTO_NEXT 4713 4714 4715/* ------------------------------ */ 4716 .balign 64 4717.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 4718/* File: x86/OP_MUL_LONG_2ADDR.S */ 4719 /* 4720 * Signed 64-bit integer multiply, 2-addr version 4721 * 4722 * We could definately use more free registers for 4723 * this code. We must spill rPC (edx) because it 4724 * is used by imul. We'll also spill rINST (ebx), 4725 * giving us eax, ebc, ecx and edx as computational 4726 * temps. On top of that, we'll spill rIBASE (edi) 4727 * for use as the vA pointer and rFP (esi) for use 4728 * as the vB pointer. Yuck. 4729 */ 4730 /* mul-long/2addr vA, vB */ 4731 movzbl rINST_HI,%eax # eax<- BA 4732 andb $0xf,%al # eax<- A 4733 sarl $12,rINST_FULL # rINST_FULL<- B 4734 SPILL(rPC) 4735 SPILL(rIBASE) 4736 SPILL(rFP) 4737 leal (rFP,%eax,4),rIBASE # rIBASE<- &v[A] 4738 leal (rFP,rINST_FULL,4),rFP # rFP<- &v[B] 4739 movl 4(rIBASE),%ecx # ecx<- Amsw 4740 imull (rFP),%ecx # ecx<- (Amsw*Blsw) 4741 movl 4(rFP),%eax # eax<- Bmsw 4742 imull (rIBASE),%eax # eax<- (Bmsw*Alsw) 4743 addl %eax,%ecx # ecx<- (Amsw*Blsw)+(Bmsw*Alsw) 4744 movl (rFP),%eax # eax<- Blsw 4745 mull (rIBASE) # eax<- (Blsw*Alsw) 4746 jmp .LOP_MUL_LONG_2ADDR_continue 4747 4748/* ------------------------------ */ 4749 .balign 64 4750.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 4751/* File: x86/OP_DIV_LONG_2ADDR.S */ 4752 /* div/2addr vA, vB */ 4753 movzbl rINST_HI,%eax 4754 shrl $4,%eax # eax<- B 4755 movzbl rINST_HI,rINST_FULL 4756 andb $0xf,rINST_LO # rINST_FULL<- A 4757 SPILL(rPC) 4758 GET_VREG_WORD(rPC,%eax,0) 4759 GET_VREG_WORD(%eax,%eax,1) 4760 movl rPC,OUT_ARG2(%esp) 4761 testl %eax,%eax 4762 je .LOP_DIV_LONG_2ADDR_check_zero 4763 cmpl $-1,%eax 4764 je .LOP_DIV_LONG_2ADDR_check_neg1 4765.LOP_DIV_LONG_2ADDR_notSpecial: 4766 GET_VREG_WORD(rPC,rINST_FULL,0) 4767 GET_VREG_WORD(%ecx,rINST_FULL,1) 4768.LOP_DIV_LONG_2ADDR_notSpecial1: 4769 jmp .LOP_DIV_LONG_2ADDR_continue 4770 4771/* ------------------------------ */ 4772 .balign 64 4773.L_OP_REM_LONG_2ADDR: /* 0xbf */ 4774/* File: x86/OP_REM_LONG_2ADDR.S */ 4775/* File: x86/OP_DIV_LONG_2ADDR.S */ 4776 /* div/2addr vA, vB */ 4777 movzbl rINST_HI,%eax 4778 shrl $4,%eax # eax<- B 4779 movzbl rINST_HI,rINST_FULL 4780 andb $0xf,rINST_LO # rINST_FULL<- A 4781 SPILL(rPC) 4782 GET_VREG_WORD(rPC,%eax,0) 4783 GET_VREG_WORD(%eax,%eax,1) 4784 movl rPC,OUT_ARG2(%esp) 4785 testl %eax,%eax 4786 je .LOP_REM_LONG_2ADDR_check_zero 4787 cmpl $-1,%eax 4788 je .LOP_REM_LONG_2ADDR_check_neg1 4789.LOP_REM_LONG_2ADDR_notSpecial: 4790 GET_VREG_WORD(rPC,rINST_FULL,0) 4791 GET_VREG_WORD(%ecx,rINST_FULL,1) 4792.LOP_REM_LONG_2ADDR_notSpecial1: 4793 jmp .LOP_REM_LONG_2ADDR_continue 4794 4795 4796/* ------------------------------ */ 4797 .balign 64 4798.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 4799/* File: x86/OP_AND_LONG_2ADDR.S */ 4800/* File: x86/binopWide2addr.S */ 4801 /* 4802 * Generic 64-bit binary operation. 4803 */ 4804 /* binop/2addr vA, vB */ 4805 movzbl rINST_HI,%ecx # ecx<- BA 4806 sarl $4,%ecx # ecx<- B 4807 GET_VREG_WORD(%eax,%ecx,0) # eax<- v[B+0] 4808 GET_VREG_WORD(%ecx,%ecx,1) # eax<- v[B+1] 4809 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 4810 andb $0xF,rINST_LO # rINST_FULL<- A 4811 andl %eax,(rFP,rINST_FULL,4) # example: addl %eax,(rFP,rINST_FULL,4) 4812 andl %ecx,4(rFP,rINST_FULL,4) # example: adcl %ecx,4(rFP,rINST_FULL,4) 4813 FETCH_INST_WORD(1) 4814 ADVANCE_PC(1) 4815 GOTO_NEXT 4816 4817 4818/* ------------------------------ */ 4819 .balign 64 4820.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 4821/* File: x86/OP_OR_LONG_2ADDR.S */ 4822/* File: x86/binopWide2addr.S */ 4823 /* 4824 * Generic 64-bit binary operation. 4825 */ 4826 /* binop/2addr vA, vB */ 4827 movzbl rINST_HI,%ecx # ecx<- BA 4828 sarl $4,%ecx # ecx<- B 4829 GET_VREG_WORD(%eax,%ecx,0) # eax<- v[B+0] 4830 GET_VREG_WORD(%ecx,%ecx,1) # eax<- v[B+1] 4831 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 4832 andb $0xF,rINST_LO # rINST_FULL<- A 4833 orl %eax,(rFP,rINST_FULL,4) # example: addl %eax,(rFP,rINST_FULL,4) 4834 orl %ecx,4(rFP,rINST_FULL,4) # example: adcl %ecx,4(rFP,rINST_FULL,4) 4835 FETCH_INST_WORD(1) 4836 ADVANCE_PC(1) 4837 GOTO_NEXT 4838 4839 4840/* ------------------------------ */ 4841 .balign 64 4842.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 4843/* File: x86/OP_XOR_LONG_2ADDR.S */ 4844/* File: x86/binopWide2addr.S */ 4845 /* 4846 * Generic 64-bit binary operation. 4847 */ 4848 /* binop/2addr vA, vB */ 4849 movzbl rINST_HI,%ecx # ecx<- BA 4850 sarl $4,%ecx # ecx<- B 4851 GET_VREG_WORD(%eax,%ecx,0) # eax<- v[B+0] 4852 GET_VREG_WORD(%ecx,%ecx,1) # eax<- v[B+1] 4853 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 4854 andb $0xF,rINST_LO # rINST_FULL<- A 4855 xorl %eax,(rFP,rINST_FULL,4) # example: addl %eax,(rFP,rINST_FULL,4) 4856 xorl %ecx,4(rFP,rINST_FULL,4) # example: adcl %ecx,4(rFP,rINST_FULL,4) 4857 FETCH_INST_WORD(1) 4858 ADVANCE_PC(1) 4859 GOTO_NEXT 4860 4861 4862/* ------------------------------ */ 4863 .balign 64 4864.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 4865/* File: x86/OP_SHL_LONG_2ADDR.S */ 4866 /* 4867 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 4868 * 32-bit shift distance. 4869 */ 4870 /* shl-long/2addr vA, vB */ 4871 /* ecx gets shift count */ 4872 /* Need to spill edx */ 4873 /* rINST gets AA */ 4874 movzbl rINST_HI,%ecx # ecx<- BA 4875 movzbl rINST_HI,rINST_FULL # rINST_HI<- BA 4876 andb $0xf,rINST_LO # rINST_FULL<- A 4877 GET_VREG_WORD(%eax,rINST_FULL,0) # eax<- v[AA+0] 4878 sarl $4,%ecx # ecx<- B 4879 SPILL(rPC) 4880 GET_VREG_WORD(%edx,rINST_FULL,1) # edx<- v[AA+1] 4881 GET_VREG(%ecx,%ecx) # ecx<- vBB 4882 shldl %eax,%edx 4883 sall %cl,%eax 4884 testb $32,%cl 4885 je 2f 4886 movl %eax,%edx 4887 xorl %eax,%eax 48882: 4889 SET_VREG_WORD(%edx,rINST_FULL,1) # v[AA+1]<- edx 4890 UNSPILL(rPC) 4891 jmp .LOP_SHL_LONG_2ADDR_finish 4892 4893/* ------------------------------ */ 4894 .balign 64 4895.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 4896/* File: x86/OP_SHR_LONG_2ADDR.S */ 4897 /* 4898 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 4899 * 32-bit shift distance. 4900 */ 4901 /* shl-long/2addr vA, vB */ 4902 /* ecx gets shift count */ 4903 /* Need to spill edx */ 4904 /* rINST gets AA */ 4905 movzbl rINST_HI,%ecx # ecx<- BA 4906 movzbl rINST_HI,rINST_FULL # rINST_HI<- BA 4907 andb $0xf,rINST_LO # rINST_FULL<- A 4908 GET_VREG_WORD(%eax,rINST_FULL,0) # eax<- v[AA+0] 4909 sarl $4,%ecx # ecx<- B 4910 SPILL(rPC) 4911 GET_VREG_WORD(%edx,rINST_FULL,1) # edx<- v[AA+1] 4912 GET_VREG(%ecx,%ecx) # ecx<- vBB 4913 shrdl %edx,%eax 4914 sarl %cl,%edx 4915 testb $32,%cl 4916 je 2f 4917 movl %edx,%eax 4918 sarl $31,%edx 49192: 4920 SET_VREG_WORD(%edx,rINST_FULL,1) # v[AA+1]<- edx 4921 UNSPILL(rPC) 4922 jmp .LOP_SHR_LONG_2ADDR_finish 4923 4924/* ------------------------------ */ 4925 .balign 64 4926.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 4927/* File: x86/OP_USHR_LONG_2ADDR.S */ 4928 /* 4929 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 4930 * 32-bit shift distance. 4931 */ 4932 /* shl-long/2addr vA, vB */ 4933 /* ecx gets shift count */ 4934 /* Need to spill edx */ 4935 /* rINST gets AA */ 4936 movzbl rINST_HI,%ecx # ecx<- BA 4937 movzbl rINST_HI,rINST_FULL # rINST_HI<- BA 4938 andb $0xf,rINST_LO # rINST_FULL<- A 4939 GET_VREG_WORD(%eax,rINST_FULL,0) # eax<- v[AA+0] 4940 sarl $4,%ecx # ecx<- B 4941 SPILL(rPC) 4942 GET_VREG_WORD(%edx,rINST_FULL,1) # edx<- v[AA+1] 4943 GET_VREG(%ecx,%ecx) # ecx<- vBB 4944 shrdl %edx,%eax 4945 shrl %cl,%edx 4946 testb $32,%cl 4947 je 2f 4948 movl %edx,%eax 4949 xorl %edx,%edx 49502: 4951 SET_VREG_WORD(%edx,rINST_FULL,1) # v[AA+1]<- edx 4952 UNSPILL(rPC) 4953 jmp .LOP_USHR_LONG_2ADDR_finish 4954 4955/* ------------------------------ */ 4956 .balign 64 4957.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 4958/* File: x86/OP_ADD_FLOAT_2ADDR.S */ 4959/* File: x86/binflop2addr.S */ 4960 /* 4961 * Generic 32-bit binary float operation. 4962 * 4963 * For: add-fp, sub-fp, mul-fp, div-fp 4964 */ 4965 4966 /* binop/2addr vA, vB */ 4967 movzx rINST_HI,%ecx # ecx<- A+ 4968 andb $0xf,%cl # ecx<- A 4969 flds (rFP,%ecx,4) # vAA to fp stack 4970 sarl $12,rINST_FULL # rINST_FULL<- B 4971 fadds (rFP,rINST_FULL,4) # ex: faddp 4972 FETCH_INST_WORD(1) 4973 ADVANCE_PC(1) 4974 fstps (rFP,%ecx,4) # %st to vA 4975 GOTO_NEXT 4976 4977 4978/* ------------------------------ */ 4979 .balign 64 4980.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 4981/* File: x86/OP_SUB_FLOAT_2ADDR.S */ 4982/* File: x86/binflop2addr.S */ 4983 /* 4984 * Generic 32-bit binary float operation. 4985 * 4986 * For: add-fp, sub-fp, mul-fp, div-fp 4987 */ 4988 4989 /* binop/2addr vA, vB */ 4990 movzx rINST_HI,%ecx # ecx<- A+ 4991 andb $0xf,%cl # ecx<- A 4992 flds (rFP,%ecx,4) # vAA to fp stack 4993 sarl $12,rINST_FULL # rINST_FULL<- B 4994 fsubs (rFP,rINST_FULL,4) # ex: faddp 4995 FETCH_INST_WORD(1) 4996 ADVANCE_PC(1) 4997 fstps (rFP,%ecx,4) # %st to vA 4998 GOTO_NEXT 4999 5000 5001/* ------------------------------ */ 5002 .balign 64 5003.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 5004/* File: x86/OP_MUL_FLOAT_2ADDR.S */ 5005/* File: x86/binflop2addr.S */ 5006 /* 5007 * Generic 32-bit binary float operation. 5008 * 5009 * For: add-fp, sub-fp, mul-fp, div-fp 5010 */ 5011 5012 /* binop/2addr vA, vB */ 5013 movzx rINST_HI,%ecx # ecx<- A+ 5014 andb $0xf,%cl # ecx<- A 5015 flds (rFP,%ecx,4) # vAA to fp stack 5016 sarl $12,rINST_FULL # rINST_FULL<- B 5017 fmuls (rFP,rINST_FULL,4) # ex: faddp 5018 FETCH_INST_WORD(1) 5019 ADVANCE_PC(1) 5020 fstps (rFP,%ecx,4) # %st to vA 5021 GOTO_NEXT 5022 5023 5024/* ------------------------------ */ 5025 .balign 64 5026.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 5027/* File: x86/OP_DIV_FLOAT_2ADDR.S */ 5028/* File: x86/binflop2addr.S */ 5029 /* 5030 * Generic 32-bit binary float operation. 5031 * 5032 * For: add-fp, sub-fp, mul-fp, div-fp 5033 */ 5034 5035 /* binop/2addr vA, vB */ 5036 movzx rINST_HI,%ecx # ecx<- A+ 5037 andb $0xf,%cl # ecx<- A 5038 flds (rFP,%ecx,4) # vAA to fp stack 5039 sarl $12,rINST_FULL # rINST_FULL<- B 5040 fdivs (rFP,rINST_FULL,4) # ex: faddp 5041 FETCH_INST_WORD(1) 5042 ADVANCE_PC(1) 5043 fstps (rFP,%ecx,4) # %st to vA 5044 GOTO_NEXT 5045 5046 5047/* ------------------------------ */ 5048 .balign 64 5049.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 5050/* File: x86/OP_REM_FLOAT_2ADDR.S */ 5051 /* rem_float/2addr vA, vB */ 5052 movzx rINST_HI,%ecx # ecx<- A+ 5053 sarl $12,rINST_FULL # rINST_FULL<- B 5054 flds (rFP,rINST_FULL,4) # vBB to fp stack 5055 andb $0xf,%cl # ecx<- A 5056 flds (rFP,%ecx,4) # vAA to fp stack 5057 FETCH_INST_WORD(1) 50581: 5059 fprem 5060 fstsw %ax 5061 sahf 5062 jp 1b 5063 fstp %st(1) 5064 ADVANCE_PC(1) 5065 fstps (rFP,%ecx,4) # %st to vA 5066 GOTO_NEXT 5067 5068/* ------------------------------ */ 5069 .balign 64 5070.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 5071/* File: x86/OP_ADD_DOUBLE_2ADDR.S */ 5072/* File: x86/binflop2addr.S */ 5073 /* 5074 * Generic 32-bit binary float operation. 5075 * 5076 * For: add-fp, sub-fp, mul-fp, div-fp 5077 */ 5078 5079 /* binop/2addr vA, vB */ 5080 movzx rINST_HI,%ecx # ecx<- A+ 5081 andb $0xf,%cl # ecx<- A 5082 fldl (rFP,%ecx,4) # vAA to fp stack 5083 sarl $12,rINST_FULL # rINST_FULL<- B 5084 faddl (rFP,rINST_FULL,4) # ex: faddp 5085 FETCH_INST_WORD(1) 5086 ADVANCE_PC(1) 5087 fstpl (rFP,%ecx,4) # %st to vA 5088 GOTO_NEXT 5089 5090 5091/* ------------------------------ */ 5092 .balign 64 5093.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 5094/* File: x86/OP_SUB_DOUBLE_2ADDR.S */ 5095/* File: x86/binflop2addr.S */ 5096 /* 5097 * Generic 32-bit binary float operation. 5098 * 5099 * For: add-fp, sub-fp, mul-fp, div-fp 5100 */ 5101 5102 /* binop/2addr vA, vB */ 5103 movzx rINST_HI,%ecx # ecx<- A+ 5104 andb $0xf,%cl # ecx<- A 5105 fldl (rFP,%ecx,4) # vAA to fp stack 5106 sarl $12,rINST_FULL # rINST_FULL<- B 5107 fsubl (rFP,rINST_FULL,4) # ex: faddp 5108 FETCH_INST_WORD(1) 5109 ADVANCE_PC(1) 5110 fstpl (rFP,%ecx,4) # %st to vA 5111 GOTO_NEXT 5112 5113 5114/* ------------------------------ */ 5115 .balign 64 5116.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 5117/* File: x86/OP_MUL_DOUBLE_2ADDR.S */ 5118/* File: x86/binflop2addr.S */ 5119 /* 5120 * Generic 32-bit binary float operation. 5121 * 5122 * For: add-fp, sub-fp, mul-fp, div-fp 5123 */ 5124 5125 /* binop/2addr vA, vB */ 5126 movzx rINST_HI,%ecx # ecx<- A+ 5127 andb $0xf,%cl # ecx<- A 5128 fldl (rFP,%ecx,4) # vAA to fp stack 5129 sarl $12,rINST_FULL # rINST_FULL<- B 5130 fmull (rFP,rINST_FULL,4) # ex: faddp 5131 FETCH_INST_WORD(1) 5132 ADVANCE_PC(1) 5133 fstpl (rFP,%ecx,4) # %st to vA 5134 GOTO_NEXT 5135 5136 5137/* ------------------------------ */ 5138 .balign 64 5139.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 5140/* File: x86/OP_DIV_DOUBLE_2ADDR.S */ 5141/* File: x86/binflop2addr.S */ 5142 /* 5143 * Generic 32-bit binary float operation. 5144 * 5145 * For: add-fp, sub-fp, mul-fp, div-fp 5146 */ 5147 5148 /* binop/2addr vA, vB */ 5149 movzx rINST_HI,%ecx # ecx<- A+ 5150 andb $0xf,%cl # ecx<- A 5151 fldl (rFP,%ecx,4) # vAA to fp stack 5152 sarl $12,rINST_FULL # rINST_FULL<- B 5153 fdivl (rFP,rINST_FULL,4) # ex: faddp 5154 FETCH_INST_WORD(1) 5155 ADVANCE_PC(1) 5156 fstpl (rFP,%ecx,4) # %st to vA 5157 GOTO_NEXT 5158 5159 5160/* ------------------------------ */ 5161 .balign 64 5162.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 5163/* File: x86/OP_REM_DOUBLE_2ADDR.S */ 5164 /* rem_float/2addr vA, vB */ 5165 movzx rINST_HI,%ecx # ecx<- A+ 5166 sarl $12,rINST_FULL # rINST_FULL<- B 5167 fldl (rFP,rINST_FULL,4) # vBB to fp stack 5168 andb $0xf,%cl # ecx<- A 5169 fldl (rFP,%ecx,4) # vAA to fp stack 5170 FETCH_INST_WORD(1) 51711: 5172 fprem 5173 fstsw %ax 5174 sahf 5175 jp 1b 5176 fstp %st(1) 5177 ADVANCE_PC(1) 5178 fstpl (rFP,%ecx,4) # %st to vA 5179 GOTO_NEXT 5180 5181/* ------------------------------ */ 5182 .balign 64 5183.L_OP_ADD_INT_LIT16: /* 0xd0 */ 5184/* File: x86/OP_ADD_INT_LIT16.S */ 5185/* File: x86/binopLit16.S */ 5186 /* 5187 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 5188 * that specifies an instruction that performs "result = eax op ecx". 5189 * This could be an x86 instruction or a function call. (If the result 5190 * comes back in a register other than eax, you can override "result".) 5191 * 5192 * For: add-int/lit16, rsub-int, 5193 * and-int/lit16, or-int/lit16, xor-int/lit16 5194 */ 5195 /* binop/lit16 vA, vB, #+CCCC */ 5196 movzbl rINST_HI,%eax # eax<- 000000BA 5197 sarl $4,%eax # eax<- B 5198 GET_VREG(%eax,%eax) # eax<- vB 5199 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5200 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 5201 andb $0xf,rINST_LO # rINST_FULL<- A 5202 addl %ecx,%eax # for example: addl %ecx, %eax 5203 SET_VREG(%eax,rINST_FULL) 5204 FETCH_INST_WORD(2) 5205 ADVANCE_PC(2) 5206 GOTO_NEXT 5207 5208 5209/* ------------------------------ */ 5210 .balign 64 5211.L_OP_RSUB_INT: /* 0xd1 */ 5212/* File: x86/OP_RSUB_INT.S */ 5213/* File: x86/binopLit16.S */ 5214 /* 5215 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 5216 * that specifies an instruction that performs "result = eax op ecx". 5217 * This could be an x86 instruction or a function call. (If the result 5218 * comes back in a register other than eax, you can override "result".) 5219 * 5220 * For: add-int/lit16, rsub-int, 5221 * and-int/lit16, or-int/lit16, xor-int/lit16 5222 */ 5223 /* binop/lit16 vA, vB, #+CCCC */ 5224 movzbl rINST_HI,%eax # eax<- 000000BA 5225 sarl $4,%eax # eax<- B 5226 GET_VREG(%eax,%eax) # eax<- vB 5227 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5228 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 5229 andb $0xf,rINST_LO # rINST_FULL<- A 5230 subl %eax,%ecx # for example: addl %ecx, %eax 5231 SET_VREG(%ecx,rINST_FULL) 5232 FETCH_INST_WORD(2) 5233 ADVANCE_PC(2) 5234 GOTO_NEXT 5235 5236 5237/* ------------------------------ */ 5238 .balign 64 5239.L_OP_MUL_INT_LIT16: /* 0xd2 */ 5240/* File: x86/OP_MUL_INT_LIT16.S */ 5241 /* mul/lit16 vA, vB, #+CCCC */ 5242 /* Need A in rINST_FULL, ssssCCCC in ecx, vB in eax */ 5243 movzbl rINST_HI,%eax # eax<- 000000BA 5244 sarl $4,%eax # eax<- B 5245 GET_VREG(%eax,%eax) # eax<- vB 5246 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5247 SPILL(rPC) 5248 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 5249 andb $0xf,rINST_LO # rINST_FULL<- A 5250 imull %ecx,%eax # trashes rPC 5251 UNSPILL(rPC) 5252 SET_VREG(%eax,rINST_FULL) 5253 FETCH_INST_WORD(2) 5254 ADVANCE_PC(2) 5255 GOTO_NEXT 5256 5257/* ------------------------------ */ 5258 .balign 64 5259.L_OP_DIV_INT_LIT16: /* 0xd3 */ 5260/* File: x86/OP_DIV_INT_LIT16.S */ 5261/* File: x86/bindivLit16.S */ 5262 /* 5263 * 32-bit binary div/rem operation. Handles special case of op0=minint and 5264 * op1=-1. 5265 */ 5266 /* div/rem/lit16 vA, vB, #+CCCC */ 5267 /* Need A in rINST_FULL, ssssCCCC in ecx, vB in eax */ 5268 movzbl rINST_HI,%eax # eax<- 000000BA 5269 sarl $4,%eax # eax<- B 5270 GET_VREG(%eax,%eax) # eax<- vB 5271 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5272 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 5273 andb $0xf,rINST_LO # rINST_FULL<- A 5274 SPILL(rPC) 5275 cmpl $0,%ecx 5276 je common_errDivideByZero 5277 cmpl $-1,%ecx 5278 jne .LOP_DIV_INT_LIT16_continue_div 5279 cmpl $0x80000000,%eax 5280 jne .LOP_DIV_INT_LIT16_continue_div 5281 movl $0x80000000,%eax 5282 jmp .LOP_DIV_INT_LIT16_finish_div 5283 5284 5285 5286/* ------------------------------ */ 5287 .balign 64 5288.L_OP_REM_INT_LIT16: /* 0xd4 */ 5289/* File: x86/OP_REM_INT_LIT16.S */ 5290/* File: x86/bindivLit16.S */ 5291 /* 5292 * 32-bit binary div/rem operation. Handles special case of op0=minint and 5293 * op1=-1. 5294 */ 5295 /* div/rem/lit16 vA, vB, #+CCCC */ 5296 /* Need A in rINST_FULL, ssssCCCC in ecx, vB in eax */ 5297 movzbl rINST_HI,%eax # eax<- 000000BA 5298 sarl $4,%eax # eax<- B 5299 GET_VREG(%eax,%eax) # eax<- vB 5300 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5301 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 5302 andb $0xf,rINST_LO # rINST_FULL<- A 5303 SPILL(rPC) 5304 cmpl $0,%ecx 5305 je common_errDivideByZero 5306 cmpl $-1,%ecx 5307 jne .LOP_REM_INT_LIT16_continue_div 5308 cmpl $0x80000000,%eax 5309 jne .LOP_REM_INT_LIT16_continue_div 5310 movl $0,%edx 5311 jmp .LOP_REM_INT_LIT16_finish_div 5312 5313 5314 5315/* ------------------------------ */ 5316 .balign 64 5317.L_OP_AND_INT_LIT16: /* 0xd5 */ 5318/* File: x86/OP_AND_INT_LIT16.S */ 5319/* File: x86/binopLit16.S */ 5320 /* 5321 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 5322 * that specifies an instruction that performs "result = eax op ecx". 5323 * This could be an x86 instruction or a function call. (If the result 5324 * comes back in a register other than eax, you can override "result".) 5325 * 5326 * For: add-int/lit16, rsub-int, 5327 * and-int/lit16, or-int/lit16, xor-int/lit16 5328 */ 5329 /* binop/lit16 vA, vB, #+CCCC */ 5330 movzbl rINST_HI,%eax # eax<- 000000BA 5331 sarl $4,%eax # eax<- B 5332 GET_VREG(%eax,%eax) # eax<- vB 5333 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5334 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 5335 andb $0xf,rINST_LO # rINST_FULL<- A 5336 andl %ecx,%eax # for example: addl %ecx, %eax 5337 SET_VREG(%eax,rINST_FULL) 5338 FETCH_INST_WORD(2) 5339 ADVANCE_PC(2) 5340 GOTO_NEXT 5341 5342 5343/* ------------------------------ */ 5344 .balign 64 5345.L_OP_OR_INT_LIT16: /* 0xd6 */ 5346/* File: x86/OP_OR_INT_LIT16.S */ 5347/* File: x86/binopLit16.S */ 5348 /* 5349 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 5350 * that specifies an instruction that performs "result = eax op ecx". 5351 * This could be an x86 instruction or a function call. (If the result 5352 * comes back in a register other than eax, you can override "result".) 5353 * 5354 * For: add-int/lit16, rsub-int, 5355 * and-int/lit16, or-int/lit16, xor-int/lit16 5356 */ 5357 /* binop/lit16 vA, vB, #+CCCC */ 5358 movzbl rINST_HI,%eax # eax<- 000000BA 5359 sarl $4,%eax # eax<- B 5360 GET_VREG(%eax,%eax) # eax<- vB 5361 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5362 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 5363 andb $0xf,rINST_LO # rINST_FULL<- A 5364 orl %ecx,%eax # for example: addl %ecx, %eax 5365 SET_VREG(%eax,rINST_FULL) 5366 FETCH_INST_WORD(2) 5367 ADVANCE_PC(2) 5368 GOTO_NEXT 5369 5370 5371/* ------------------------------ */ 5372 .balign 64 5373.L_OP_XOR_INT_LIT16: /* 0xd7 */ 5374/* File: x86/OP_XOR_INT_LIT16.S */ 5375/* File: x86/binopLit16.S */ 5376 /* 5377 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 5378 * that specifies an instruction that performs "result = eax op ecx". 5379 * This could be an x86 instruction or a function call. (If the result 5380 * comes back in a register other than eax, you can override "result".) 5381 * 5382 * For: add-int/lit16, rsub-int, 5383 * and-int/lit16, or-int/lit16, xor-int/lit16 5384 */ 5385 /* binop/lit16 vA, vB, #+CCCC */ 5386 movzbl rINST_HI,%eax # eax<- 000000BA 5387 sarl $4,%eax # eax<- B 5388 GET_VREG(%eax,%eax) # eax<- vB 5389 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5390 movzbl rINST_HI,rINST_FULL # rINST_FULL<- BA 5391 andb $0xf,rINST_LO # rINST_FULL<- A 5392 xor %ecx,%eax # for example: addl %ecx, %eax 5393 SET_VREG(%eax,rINST_FULL) 5394 FETCH_INST_WORD(2) 5395 ADVANCE_PC(2) 5396 GOTO_NEXT 5397 5398 5399/* ------------------------------ */ 5400 .balign 64 5401.L_OP_ADD_INT_LIT8: /* 0xd8 */ 5402/* File: x86/OP_ADD_INT_LIT8.S */ 5403/* File: x86/binopLit8.S */ 5404 /* 5405 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5406 * that specifies an instruction that performs "result = eax op ecx". 5407 * This could be an x86 instruction or a function call. (If the result 5408 * comes back in a register other than r0, you can override "result".) 5409 * 5410 * For: add-int/lit8, rsub-int/lit8 5411 * and-int/lit8, or-int/lit8, xor-int/lit8, 5412 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5413 */ 5414 /* binop/lit8 vAA, vBB, #+CC */ 5415 movzbl 2(rPC),%eax # eax<- BB 5416 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5417 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA 5418 GET_VREG (%eax,%eax) # eax<- rBB 5419 addl %ecx,%eax # ex: addl %ecx,%eax 5420 SET_VREG (%eax,rINST_FULL) 5421 FETCH_INST_WORD(2) 5422 ADVANCE_PC(2) 5423 GOTO_NEXT 5424 5425 5426/* ------------------------------ */ 5427 .balign 64 5428.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 5429/* File: x86/OP_RSUB_INT_LIT8.S */ 5430/* File: x86/binopLit8.S */ 5431 /* 5432 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5433 * that specifies an instruction that performs "result = eax op ecx". 5434 * This could be an x86 instruction or a function call. (If the result 5435 * comes back in a register other than r0, you can override "result".) 5436 * 5437 * For: add-int/lit8, rsub-int/lit8 5438 * and-int/lit8, or-int/lit8, xor-int/lit8, 5439 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5440 */ 5441 /* binop/lit8 vAA, vBB, #+CC */ 5442 movzbl 2(rPC),%eax # eax<- BB 5443 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5444 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA 5445 GET_VREG (%eax,%eax) # eax<- rBB 5446 subl %eax,%ecx # ex: addl %ecx,%eax 5447 SET_VREG (%ecx,rINST_FULL) 5448 FETCH_INST_WORD(2) 5449 ADVANCE_PC(2) 5450 GOTO_NEXT 5451 5452 5453/* ------------------------------ */ 5454 .balign 64 5455.L_OP_MUL_INT_LIT8: /* 0xda */ 5456/* File: x86/OP_MUL_INT_LIT8.S */ 5457 /* mul/lit8 vAA, vBB, #+CC */ 5458 movzbl 2(rPC),%eax # eax<- BB 5459 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5460 SPILL(rPC) 5461 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA 5462 GET_VREG (%eax,%eax) # eax<- rBB 5463 imull %ecx,%eax # trashes rPC 5464 UNSPILL(rPC) 5465 SET_VREG (%eax,rINST_FULL) 5466 FETCH_INST_WORD(2) 5467 ADVANCE_PC(2) 5468 GOTO_NEXT 5469 5470/* ------------------------------ */ 5471 .balign 64 5472.L_OP_DIV_INT_LIT8: /* 0xdb */ 5473/* File: x86/OP_DIV_INT_LIT8.S */ 5474/* File: x86/bindivLit8.S */ 5475 /* 5476 * 32-bit div/rem "lit8" binary operation. Handles special case of 5477 * op0=minint & op1=-1 5478 */ 5479 /* div/rem/lit8 vAA, vBB, #+CC */ 5480 movzbl 2(rPC),%eax # eax<- BB 5481 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5482 GET_VREG (%eax,%eax) # eax<- rBB 5483 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA 5484 SPILL(rPC) 5485 cmpl $0,%ecx 5486 je common_errDivideByZero 5487 cmpl $0x80000000,%eax 5488 jne .LOP_DIV_INT_LIT8_continue_div 5489 cmpl $-1,%ecx 5490 jne .LOP_DIV_INT_LIT8_continue_div 5491 movl $0x80000000,%eax 5492 jmp .LOP_DIV_INT_LIT8_finish_div 5493 5494 5495 5496/* ------------------------------ */ 5497 .balign 64 5498.L_OP_REM_INT_LIT8: /* 0xdc */ 5499/* File: x86/OP_REM_INT_LIT8.S */ 5500/* File: x86/bindivLit8.S */ 5501 /* 5502 * 32-bit div/rem "lit8" binary operation. Handles special case of 5503 * op0=minint & op1=-1 5504 */ 5505 /* div/rem/lit8 vAA, vBB, #+CC */ 5506 movzbl 2(rPC),%eax # eax<- BB 5507 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5508 GET_VREG (%eax,%eax) # eax<- rBB 5509 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA 5510 SPILL(rPC) 5511 cmpl $0,%ecx 5512 je common_errDivideByZero 5513 cmpl $0x80000000,%eax 5514 jne .LOP_REM_INT_LIT8_continue_div 5515 cmpl $-1,%ecx 5516 jne .LOP_REM_INT_LIT8_continue_div 5517 movl $0,%edx 5518 jmp .LOP_REM_INT_LIT8_finish_div 5519 5520 5521 5522/* ------------------------------ */ 5523 .balign 64 5524.L_OP_AND_INT_LIT8: /* 0xdd */ 5525/* File: x86/OP_AND_INT_LIT8.S */ 5526/* File: x86/binopLit8.S */ 5527 /* 5528 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5529 * that specifies an instruction that performs "result = eax op ecx". 5530 * This could be an x86 instruction or a function call. (If the result 5531 * comes back in a register other than r0, you can override "result".) 5532 * 5533 * For: add-int/lit8, rsub-int/lit8 5534 * and-int/lit8, or-int/lit8, xor-int/lit8, 5535 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5536 */ 5537 /* binop/lit8 vAA, vBB, #+CC */ 5538 movzbl 2(rPC),%eax # eax<- BB 5539 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5540 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA 5541 GET_VREG (%eax,%eax) # eax<- rBB 5542 andl %ecx,%eax # ex: addl %ecx,%eax 5543 SET_VREG (%eax,rINST_FULL) 5544 FETCH_INST_WORD(2) 5545 ADVANCE_PC(2) 5546 GOTO_NEXT 5547 5548 5549/* ------------------------------ */ 5550 .balign 64 5551.L_OP_OR_INT_LIT8: /* 0xde */ 5552/* File: x86/OP_OR_INT_LIT8.S */ 5553/* File: x86/binopLit8.S */ 5554 /* 5555 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5556 * that specifies an instruction that performs "result = eax op ecx". 5557 * This could be an x86 instruction or a function call. (If the result 5558 * comes back in a register other than r0, you can override "result".) 5559 * 5560 * For: add-int/lit8, rsub-int/lit8 5561 * and-int/lit8, or-int/lit8, xor-int/lit8, 5562 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5563 */ 5564 /* binop/lit8 vAA, vBB, #+CC */ 5565 movzbl 2(rPC),%eax # eax<- BB 5566 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5567 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA 5568 GET_VREG (%eax,%eax) # eax<- rBB 5569 orl %ecx,%eax # ex: addl %ecx,%eax 5570 SET_VREG (%eax,rINST_FULL) 5571 FETCH_INST_WORD(2) 5572 ADVANCE_PC(2) 5573 GOTO_NEXT 5574 5575 5576/* ------------------------------ */ 5577 .balign 64 5578.L_OP_XOR_INT_LIT8: /* 0xdf */ 5579/* File: x86/OP_XOR_INT_LIT8.S */ 5580/* File: x86/binopLit8.S */ 5581 /* 5582 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5583 * that specifies an instruction that performs "result = eax op ecx". 5584 * This could be an x86 instruction or a function call. (If the result 5585 * comes back in a register other than r0, you can override "result".) 5586 * 5587 * For: add-int/lit8, rsub-int/lit8 5588 * and-int/lit8, or-int/lit8, xor-int/lit8, 5589 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5590 */ 5591 /* binop/lit8 vAA, vBB, #+CC */ 5592 movzbl 2(rPC),%eax # eax<- BB 5593 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5594 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA 5595 GET_VREG (%eax,%eax) # eax<- rBB 5596 xor %ecx,%eax # ex: addl %ecx,%eax 5597 SET_VREG (%eax,rINST_FULL) 5598 FETCH_INST_WORD(2) 5599 ADVANCE_PC(2) 5600 GOTO_NEXT 5601 5602 5603/* ------------------------------ */ 5604 .balign 64 5605.L_OP_SHL_INT_LIT8: /* 0xe0 */ 5606/* File: x86/OP_SHL_INT_LIT8.S */ 5607/* File: x86/binopLit8.S */ 5608 /* 5609 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5610 * that specifies an instruction that performs "result = eax op ecx". 5611 * This could be an x86 instruction or a function call. (If the result 5612 * comes back in a register other than r0, you can override "result".) 5613 * 5614 * For: add-int/lit8, rsub-int/lit8 5615 * and-int/lit8, or-int/lit8, xor-int/lit8, 5616 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5617 */ 5618 /* binop/lit8 vAA, vBB, #+CC */ 5619 movzbl 2(rPC),%eax # eax<- BB 5620 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5621 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA 5622 GET_VREG (%eax,%eax) # eax<- rBB 5623 sall %cl,%eax # ex: addl %ecx,%eax 5624 SET_VREG (%eax,rINST_FULL) 5625 FETCH_INST_WORD(2) 5626 ADVANCE_PC(2) 5627 GOTO_NEXT 5628 5629 5630/* ------------------------------ */ 5631 .balign 64 5632.L_OP_SHR_INT_LIT8: /* 0xe1 */ 5633/* File: x86/OP_SHR_INT_LIT8.S */ 5634/* File: x86/binopLit8.S */ 5635 /* 5636 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5637 * that specifies an instruction that performs "result = eax op ecx". 5638 * This could be an x86 instruction or a function call. (If the result 5639 * comes back in a register other than r0, you can override "result".) 5640 * 5641 * For: add-int/lit8, rsub-int/lit8 5642 * and-int/lit8, or-int/lit8, xor-int/lit8, 5643 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5644 */ 5645 /* binop/lit8 vAA, vBB, #+CC */ 5646 movzbl 2(rPC),%eax # eax<- BB 5647 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5648 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA 5649 GET_VREG (%eax,%eax) # eax<- rBB 5650 sarl %cl,%eax # ex: addl %ecx,%eax 5651 SET_VREG (%eax,rINST_FULL) 5652 FETCH_INST_WORD(2) 5653 ADVANCE_PC(2) 5654 GOTO_NEXT 5655 5656 5657/* ------------------------------ */ 5658 .balign 64 5659.L_OP_USHR_INT_LIT8: /* 0xe2 */ 5660/* File: x86/OP_USHR_INT_LIT8.S */ 5661/* File: x86/binopLit8.S */ 5662 /* 5663 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5664 * that specifies an instruction that performs "result = eax op ecx". 5665 * This could be an x86 instruction or a function call. (If the result 5666 * comes back in a register other than r0, you can override "result".) 5667 * 5668 * For: add-int/lit8, rsub-int/lit8 5669 * and-int/lit8, or-int/lit8, xor-int/lit8, 5670 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5671 */ 5672 /* binop/lit8 vAA, vBB, #+CC */ 5673 movzbl 2(rPC),%eax # eax<- BB 5674 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5675 movzx rINST_HI,rINST_FULL # rINST_FULL<- AA 5676 GET_VREG (%eax,%eax) # eax<- rBB 5677 shrl %cl,%eax # ex: addl %ecx,%eax 5678 SET_VREG (%eax,rINST_FULL) 5679 FETCH_INST_WORD(2) 5680 ADVANCE_PC(2) 5681 GOTO_NEXT 5682 5683 5684/* ------------------------------ */ 5685 .balign 64 5686.L_OP_IGET_VOLATILE: /* 0xe3 */ 5687 /* (stub) */ 5688 GET_GLUE(%ecx) 5689 SAVE_PC_TO_GLUE(%ecx) # only need to export these two 5690 SAVE_FP_TO_GLUE(%ecx) # only need to export these two 5691 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 5692 call dvmMterp_OP_IGET_VOLATILE # do the real work 5693 GET_GLUE(%ecx) 5694 LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values 5695 LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values 5696 FETCH_INST() 5697 GOTO_NEXT 5698/* ------------------------------ */ 5699 .balign 64 5700.L_OP_IPUT_VOLATILE: /* 0xe4 */ 5701 /* (stub) */ 5702 GET_GLUE(%ecx) 5703 SAVE_PC_TO_GLUE(%ecx) # only need to export these two 5704 SAVE_FP_TO_GLUE(%ecx) # only need to export these two 5705 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 5706 call dvmMterp_OP_IPUT_VOLATILE # do the real work 5707 GET_GLUE(%ecx) 5708 LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values 5709 LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values 5710 FETCH_INST() 5711 GOTO_NEXT 5712/* ------------------------------ */ 5713 .balign 64 5714.L_OP_SGET_VOLATILE: /* 0xe5 */ 5715 /* (stub) */ 5716 GET_GLUE(%ecx) 5717 SAVE_PC_TO_GLUE(%ecx) # only need to export these two 5718 SAVE_FP_TO_GLUE(%ecx) # only need to export these two 5719 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 5720 call dvmMterp_OP_SGET_VOLATILE # do the real work 5721 GET_GLUE(%ecx) 5722 LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values 5723 LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values 5724 FETCH_INST() 5725 GOTO_NEXT 5726/* ------------------------------ */ 5727 .balign 64 5728.L_OP_SPUT_VOLATILE: /* 0xe6 */ 5729 /* (stub) */ 5730 GET_GLUE(%ecx) 5731 SAVE_PC_TO_GLUE(%ecx) # only need to export these two 5732 SAVE_FP_TO_GLUE(%ecx) # only need to export these two 5733 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 5734 call dvmMterp_OP_SPUT_VOLATILE # do the real work 5735 GET_GLUE(%ecx) 5736 LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values 5737 LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values 5738 FETCH_INST() 5739 GOTO_NEXT 5740/* ------------------------------ */ 5741 .balign 64 5742.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ 5743 /* (stub) */ 5744 GET_GLUE(%ecx) 5745 SAVE_PC_TO_GLUE(%ecx) # only need to export these two 5746 SAVE_FP_TO_GLUE(%ecx) # only need to export these two 5747 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 5748 call dvmMterp_OP_IGET_OBJECT_VOLATILE # do the real work 5749 GET_GLUE(%ecx) 5750 LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values 5751 LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values 5752 FETCH_INST() 5753 GOTO_NEXT 5754/* ------------------------------ */ 5755 .balign 64 5756.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */ 5757 /* (stub) */ 5758 GET_GLUE(%ecx) 5759 SAVE_PC_TO_GLUE(%ecx) # only need to export these two 5760 SAVE_FP_TO_GLUE(%ecx) # only need to export these two 5761 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 5762 call dvmMterp_OP_IGET_WIDE_VOLATILE # do the real work 5763 GET_GLUE(%ecx) 5764 LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values 5765 LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values 5766 FETCH_INST() 5767 GOTO_NEXT 5768/* ------------------------------ */ 5769 .balign 64 5770.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */ 5771 /* (stub) */ 5772 GET_GLUE(%ecx) 5773 SAVE_PC_TO_GLUE(%ecx) # only need to export these two 5774 SAVE_FP_TO_GLUE(%ecx) # only need to export these two 5775 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 5776 call dvmMterp_OP_IPUT_WIDE_VOLATILE # do the real work 5777 GET_GLUE(%ecx) 5778 LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values 5779 LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values 5780 FETCH_INST() 5781 GOTO_NEXT 5782/* ------------------------------ */ 5783 .balign 64 5784.L_OP_SGET_WIDE_VOLATILE: /* 0xea */ 5785 /* (stub) */ 5786 GET_GLUE(%ecx) 5787 SAVE_PC_TO_GLUE(%ecx) # only need to export these two 5788 SAVE_FP_TO_GLUE(%ecx) # only need to export these two 5789 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 5790 call dvmMterp_OP_SGET_WIDE_VOLATILE # do the real work 5791 GET_GLUE(%ecx) 5792 LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values 5793 LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values 5794 FETCH_INST() 5795 GOTO_NEXT 5796/* ------------------------------ */ 5797 .balign 64 5798.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */ 5799 /* (stub) */ 5800 GET_GLUE(%ecx) 5801 SAVE_PC_TO_GLUE(%ecx) # only need to export these two 5802 SAVE_FP_TO_GLUE(%ecx) # only need to export these two 5803 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 5804 call dvmMterp_OP_SPUT_WIDE_VOLATILE # do the real work 5805 GET_GLUE(%ecx) 5806 LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values 5807 LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values 5808 FETCH_INST() 5809 GOTO_NEXT 5810/* ------------------------------ */ 5811 .balign 64 5812.L_OP_BREAKPOINT: /* 0xec */ 5813/* File: x86/OP_BREAKPOINT.S */ 5814/* File: x86/unused.S */ 5815 jmp common_abort 5816 5817 5818/* ------------------------------ */ 5819 .balign 64 5820.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 5821/* File: x86/OP_THROW_VERIFICATION_ERROR.S */ 5822 /* 5823 * Handle a throw-verification-error instruction. This throws an 5824 * exception for an error discovered during verification. The 5825 * exception is indicated by AA, with some detail provided by BBBB. 5826 */ 5827 /* op AA, ref@BBBB */ 5828 GET_GLUE(%ecx) 5829 movzwl 2(rPC),%eax # eax<- BBBB 5830 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 5831 EXPORT_PC() 5832 movzbl rINST_HI,rINST_FULL # rINST_FULL<- AA 5833 movl %eax,OUT_ARG2(%esp) # arg2<- BBBB 5834 movl rINST_FULL,OUT_ARG1(%esp) # arg1<- AA 5835 movl %ecx,OUT_ARG0(%esp) # arg0<- method 5836 SPILL(rPC) 5837 call dvmThrowVerificationError # call(method, kind, ref) 5838 UNSPILL(rPC) 5839 jmp common_exceptionThrown # handle exception 5840 5841/* ------------------------------ */ 5842 .balign 64 5843.L_OP_EXECUTE_INLINE: /* 0xee */ 5844/* File: x86/OP_EXECUTE_INLINE.S */ 5845 /* 5846 * Execute a "native inline" instruction. 5847 * 5848 * We will be calling through a function table: 5849 * 5850 * (*gDvmInlineOpsTable[opIndex].func)(arg0, arg1, arg2, arg3, pResult) 5851 * 5852 */ 5853 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 5854 GET_GLUE(%ecx) 5855 EXPORT_PC() 5856 movzwl 2(rPC),%eax # eax<- BBBB 5857 leal offGlue_retval(%ecx),%ecx # ecx<- & glue->retval 5858 movl %ecx,OUT_ARG4(%esp) 5859 sarl $12,rINST_FULL # rINST_FULL<- arg count (0-4) 5860 SPILL(rPC) 5861 call .LOP_EXECUTE_INLINE_continue # make call; will return after 5862 UNSPILL(rPC) 5863 testl %eax,%eax # successful? 5864 FETCH_INST_WORD(3) 5865 je common_exceptionThrown # no, handle exception 5866 ADVANCE_PC(3) 5867 GOTO_NEXT 5868 5869/* ------------------------------ */ 5870 .balign 64 5871.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ 5872 /* (stub) */ 5873 GET_GLUE(%ecx) 5874 SAVE_PC_TO_GLUE(%ecx) # only need to export these two 5875 SAVE_FP_TO_GLUE(%ecx) # only need to export these two 5876 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 5877 call dvmMterp_OP_EXECUTE_INLINE_RANGE # do the real work 5878 GET_GLUE(%ecx) 5879 LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values 5880 LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values 5881 FETCH_INST() 5882 GOTO_NEXT 5883/* ------------------------------ */ 5884 .balign 64 5885.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 5886/* File: x86/OP_INVOKE_DIRECT_EMPTY.S */ 5887 /* 5888 * invoke-direct-empty is a no-op in a "standard" interpreter. 5889 */ 5890 FETCH_INST_WORD(3) 5891 ADVANCE_PC(3) 5892 GOTO_NEXT 5893 5894/* ------------------------------ */ 5895 .balign 64 5896.L_OP_UNUSED_F1: /* 0xf1 */ 5897/* File: x86/OP_UNUSED_F1.S */ 5898/* File: x86/unused.S */ 5899 jmp common_abort 5900 5901 5902/* ------------------------------ */ 5903 .balign 64 5904.L_OP_IGET_QUICK: /* 0xf2 */ 5905/* File: x86/OP_IGET_QUICK.S */ 5906 /* For: iget-quick, iget-object-quick */ 5907 /* op vA, vB, offset@CCCC */ 5908 movzbl rINST_HI,%ecx # ecx<- BA 5909 sarl $4,%ecx # ecx<- B 5910 GET_VREG(%ecx,%ecx) # vB (object we're operating on) 5911 movzwl 2(rPC),%eax # eax<- field byte offset 5912 cmpl $0,%ecx # is object null? 5913 je common_errNullObject 5914 movl (%ecx,%eax,1),%eax 5915 movzbl rINST_HI,%ecx 5916 FETCH_INST_WORD(2) 5917 ADVANCE_PC(2) 5918 andb $0xf,%cl # rINST_FULL<- A 5919 SET_VREG (%eax,%ecx) # fp[A]<- result 5920 GOTO_NEXT 5921 5922/* ------------------------------ */ 5923 .balign 64 5924.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 5925/* File: x86/OP_IGET_WIDE_QUICK.S */ 5926 /* For: iget-wide-quick */ 5927 /* op vA, vB, offset@CCCC */ 5928 movzbl rINST_HI,%ecx # ecx<- BA 5929 sarl $4,%ecx # ecx<- B 5930 GET_VREG(%ecx,%ecx) # vB (object we're operating on) 5931 movzwl 2(rPC),%eax # eax<- field byte offset 5932 cmpl $0,%ecx # is object null? 5933 je common_errNullObject 5934 leal (%ecx,%eax,1),%eax # eax<- address of 64-bit source 5935 movl (%eax),%ecx # ecx<- lsw 5936 movl 4(%eax),%eax # eax<- msw 5937 movzbl rINST_HI,rINST_FULL 5938 andb $0xf,rINST_LO # rINST_FULL<- A 5939 SET_VREG_WORD(%ecx,rINST_FULL,0) # v[A+0]<- lsw 5940 SET_VREG_WORD(%eax,rINST_FULL,1) # v[A+1]<- msw 5941 FETCH_INST_WORD(2) 5942 ADVANCE_PC(2) 5943 GOTO_NEXT 5944 5945/* ------------------------------ */ 5946 .balign 64 5947.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 5948/* File: x86/OP_IGET_OBJECT_QUICK.S */ 5949/* File: x86/OP_IGET_QUICK.S */ 5950 /* For: iget-quick, iget-object-quick */ 5951 /* op vA, vB, offset@CCCC */ 5952 movzbl rINST_HI,%ecx # ecx<- BA 5953 sarl $4,%ecx # ecx<- B 5954 GET_VREG(%ecx,%ecx) # vB (object we're operating on) 5955 movzwl 2(rPC),%eax # eax<- field byte offset 5956 cmpl $0,%ecx # is object null? 5957 je common_errNullObject 5958 movl (%ecx,%eax,1),%eax 5959 movzbl rINST_HI,%ecx 5960 FETCH_INST_WORD(2) 5961 ADVANCE_PC(2) 5962 andb $0xf,%cl # rINST_FULL<- A 5963 SET_VREG (%eax,%ecx) # fp[A]<- result 5964 GOTO_NEXT 5965 5966 5967/* ------------------------------ */ 5968 .balign 64 5969.L_OP_IPUT_QUICK: /* 0xf5 */ 5970/* File: x86/OP_IPUT_QUICK.S */ 5971 /* For: iput-quick, iput-object-quick */ 5972 /* op vA, vB, offset@CCCC */ 5973 movzbl rINST_HI,%ecx # ecx<- BA 5974 sarl $4,%ecx # ecx<- B 5975 GET_VREG(%ecx,%ecx) # vB (object we're operating on) 5976 movzbl rINST_HI,rINST_FULL 5977 andb $0xf,rINST_LO # rINST_FULL<- A 5978 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 5979 movzwl 2(rPC),%eax # eax<- field byte offset 5980 testl %ecx,%ecx # is object null? 5981 je common_errNullObject 5982 movl rINST_FULL,(%ecx,%eax,1) 5983 FETCH_INST_WORD(2) 5984 ADVANCE_PC(2) 5985 GOTO_NEXT 5986 5987/* ------------------------------ */ 5988 .balign 64 5989.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 5990/* File: x86/OP_IPUT_WIDE_QUICK.S */ 5991 /* For: iput-wide-quick */ 5992 /* op vA, vB, offset@CCCC */ 5993 movzbl rINST_HI,%ecx # ecx<- BA 5994 sarl $4,%ecx # ecx<- B 5995 GET_VREG(%ecx,%ecx) # vB (object we're operating on) 5996 movzwl 2(rPC),%eax # eax<- field byte offset 5997 testl %ecx,%ecx # is object null? 5998 je common_errNullObject 5999 leal (%ecx,%eax,1),%ecx # ecx<- Address of 64-bit target 6000 movzbl rINST_HI,rINST_FULL 6001 andb $0xf,rINST_LO # rINST_FULL<- A 6002 GET_VREG_WORD(%eax,rINST_FULL,0) # eax<- lsw 6003 GET_VREG_WORD(rINST_FULL,rINST_FULL,1) # rINST_FULL<- msw 6004 movl %eax,(%ecx) 6005 movl rINST_FULL,4(%ecx) 6006 FETCH_INST_WORD(2) 6007 ADVANCE_PC(2) 6008 GOTO_NEXT 6009 6010/* ------------------------------ */ 6011 .balign 64 6012.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 6013/* File: x86/OP_IPUT_OBJECT_QUICK.S */ 6014/* File: x86/OP_IPUT_QUICK.S */ 6015 /* For: iput-quick, iput-object-quick */ 6016 /* op vA, vB, offset@CCCC */ 6017 movzbl rINST_HI,%ecx # ecx<- BA 6018 sarl $4,%ecx # ecx<- B 6019 GET_VREG(%ecx,%ecx) # vB (object we're operating on) 6020 movzbl rINST_HI,rINST_FULL 6021 andb $0xf,rINST_LO # rINST_FULL<- A 6022 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 6023 movzwl 2(rPC),%eax # eax<- field byte offset 6024 testl %ecx,%ecx # is object null? 6025 je common_errNullObject 6026 movl rINST_FULL,(%ecx,%eax,1) 6027 FETCH_INST_WORD(2) 6028 ADVANCE_PC(2) 6029 GOTO_NEXT 6030 6031 6032/* ------------------------------ */ 6033 .balign 64 6034.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 6035/* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */ 6036 /* 6037 * Handle an optimized virtual method call. 6038 * 6039 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 6040 */ 6041 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 6042 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 6043 movzwl 4(rPC),%eax # eax<- FEDC or CCCC 6044 movzwl 2(rPC),%ecx # ecx<- BBBB 6045 .if (!0) 6046 andl $0xf,%eax # eax<- C (or stays CCCC) 6047 .endif 6048 GET_VREG(%eax,%eax) # eax<- vC ("this" ptr) 6049 testl %eax,%eax # null? 6050 je common_errNullObject # yep, throw exception 6051 movl offObject_clazz(%eax),%eax # eax<- thisPtr->clazz 6052 movl offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable 6053 EXPORT_PC() # might throw later - get ready 6054 movl (%eax,%ecx,4),%eax # eax<- vtable[BBBB] 6055 jmp common_invokeMethodNoRange 6056 6057/* ------------------------------ */ 6058 .balign 64 6059.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 6060/* File: x86/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 6061/* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */ 6062 /* 6063 * Handle an optimized virtual method call. 6064 * 6065 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 6066 */ 6067 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 6068 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 6069 movzwl 4(rPC),%eax # eax<- FEDC or CCCC 6070 movzwl 2(rPC),%ecx # ecx<- BBBB 6071 .if (!1) 6072 andl $0xf,%eax # eax<- C (or stays CCCC) 6073 .endif 6074 GET_VREG(%eax,%eax) # eax<- vC ("this" ptr) 6075 testl %eax,%eax # null? 6076 je common_errNullObject # yep, throw exception 6077 movl offObject_clazz(%eax),%eax # eax<- thisPtr->clazz 6078 movl offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable 6079 EXPORT_PC() # might throw later - get ready 6080 movl (%eax,%ecx,4),%eax # eax<- vtable[BBBB] 6081 jmp common_invokeMethodRange 6082 6083 6084/* ------------------------------ */ 6085 .balign 64 6086.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 6087/* File: x86/OP_INVOKE_SUPER_QUICK.S */ 6088 /* 6089 * Handle an optimized "super" method call. 6090 * 6091 * for: [opt] invoke-super-quick, invoke-super-quick/range 6092 */ 6093 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 6094 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 6095 GET_GLUE(%ecx) 6096 movzwl 4(rPC),%eax # eax<- GFED or CCCC 6097 movl offGlue_method(%ecx),%ecx # ecx<- current method 6098 .if (!0) 6099 andl $0xf,%eax # eax<- D (or stays CCCC) 6100 .endif 6101 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6102 GET_VREG(%eax,%eax) # eax<- "this" 6103 movl offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super 6104 testl %eax,%eax # null "this"? 6105 je common_errNullObject # "this" is null, throw exception 6106 movzwl 2(rPC),%eax # eax<- BBBB 6107 movl offClassObject_vtable(%ecx),%ecx # ecx<- vtable 6108 EXPORT_PC() 6109 movl (%ecx,%eax,4),%eax # eax<- super->vtable[BBBB] 6110 jmp common_invokeMethodNoRange 6111 6112/* ------------------------------ */ 6113 .balign 64 6114.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 6115/* File: x86/OP_INVOKE_SUPER_QUICK_RANGE.S */ 6116/* File: x86/OP_INVOKE_SUPER_QUICK.S */ 6117 /* 6118 * Handle an optimized "super" method call. 6119 * 6120 * for: [opt] invoke-super-quick, invoke-super-quick/range 6121 */ 6122 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 6123 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 6124 GET_GLUE(%ecx) 6125 movzwl 4(rPC),%eax # eax<- GFED or CCCC 6126 movl offGlue_method(%ecx),%ecx # ecx<- current method 6127 .if (!1) 6128 andl $0xf,%eax # eax<- D (or stays CCCC) 6129 .endif 6130 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6131 GET_VREG(%eax,%eax) # eax<- "this" 6132 movl offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super 6133 testl %eax,%eax # null "this"? 6134 je common_errNullObject # "this" is null, throw exception 6135 movzwl 2(rPC),%eax # eax<- BBBB 6136 movl offClassObject_vtable(%ecx),%ecx # ecx<- vtable 6137 EXPORT_PC() 6138 movl (%ecx,%eax,4),%eax # eax<- super->vtable[BBBB] 6139 jmp common_invokeMethodRange 6140 6141 6142/* ------------------------------ */ 6143 .balign 64 6144.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ 6145 /* (stub) */ 6146 GET_GLUE(%ecx) 6147 SAVE_PC_TO_GLUE(%ecx) # only need to export these two 6148 SAVE_FP_TO_GLUE(%ecx) # only need to export these two 6149 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 6150 call dvmMterp_OP_IPUT_OBJECT_VOLATILE # do the real work 6151 GET_GLUE(%ecx) 6152 LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values 6153 LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values 6154 FETCH_INST() 6155 GOTO_NEXT 6156/* ------------------------------ */ 6157 .balign 64 6158.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ 6159 /* (stub) */ 6160 GET_GLUE(%ecx) 6161 SAVE_PC_TO_GLUE(%ecx) # only need to export these two 6162 SAVE_FP_TO_GLUE(%ecx) # only need to export these two 6163 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 6164 call dvmMterp_OP_SGET_OBJECT_VOLATILE # do the real work 6165 GET_GLUE(%ecx) 6166 LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values 6167 LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values 6168 FETCH_INST() 6169 GOTO_NEXT 6170/* ------------------------------ */ 6171 .balign 64 6172.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ 6173 /* (stub) */ 6174 GET_GLUE(%ecx) 6175 SAVE_PC_TO_GLUE(%ecx) # only need to export these two 6176 SAVE_FP_TO_GLUE(%ecx) # only need to export these two 6177 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 6178 call dvmMterp_OP_SPUT_OBJECT_VOLATILE # do the real work 6179 GET_GLUE(%ecx) 6180 LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values 6181 LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values 6182 FETCH_INST() 6183 GOTO_NEXT 6184/* ------------------------------ */ 6185 .balign 64 6186.L_OP_UNUSED_FF: /* 0xff */ 6187/* File: x86/OP_UNUSED_FF.S */ 6188/* File: x86/unused.S */ 6189 jmp common_abort 6190 6191 6192 6193 .balign 64 6194 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 6195 .global dvmAsmInstructionEnd 6196dvmAsmInstructionEnd: 6197 6198/* 6199 * =========================================================================== 6200 * Sister implementations 6201 * =========================================================================== 6202 */ 6203 .global dvmAsmSisterStart 6204 .type dvmAsmSisterStart, %function 6205 .text 6206 .balign 4 6207dvmAsmSisterStart: 6208 6209/* continuation for OP_CONST_STRING */ 6210 6211/* This is the less common path, so we'll redo some work 6212 here rather than force spills on the common path */ 6213.LOP_CONST_STRING_resolve: 6214 GET_GLUE(%eax) 6215 movl %ecx,rINST_FULL # rINST_FULL<- AA 6216 EXPORT_PC() 6217 movl offGlue_method(%eax),%eax # eax<- glue->method 6218 movzwl 2(rPC),%ecx # ecx<- BBBB 6219 movl offMethod_clazz(%eax),%eax 6220 SPILL(rPC) 6221 movl %ecx,OUT_ARG1(%esp) 6222 movl %eax,OUT_ARG0(%esp) 6223 call dvmResolveString # go resolve 6224 UNSPILL(rPC) 6225 testl %eax,%eax # failed? 6226 je common_exceptionThrown 6227 SET_VREG(%eax,rINST_FULL) 6228 FETCH_INST_WORD(2) 6229 ADVANCE_PC(2) 6230 GOTO_NEXT 6231 6232/* continuation for OP_CONST_STRING_JUMBO */ 6233 6234/* This is the less common path, so we'll redo some work 6235 here rather than force spills on the common path */ 6236.LOP_CONST_STRING_JUMBO_resolve: 6237 GET_GLUE(%eax) 6238 movl %ecx,rINST_FULL # rINST_FULL<- AA 6239 EXPORT_PC() 6240 movl offGlue_method(%eax),%eax # eax<- glue->method 6241 movl 2(rPC),%ecx # ecx<- BBBBBBBB 6242 movl offMethod_clazz(%eax),%eax 6243 SPILL(rPC) 6244 movl %ecx,OUT_ARG1(%esp) 6245 movl %eax,OUT_ARG0(%esp) 6246 call dvmResolveString # go resolve 6247 UNSPILL(rPC) 6248 testl %eax,%eax # failed? 6249 je common_exceptionThrown 6250 SET_VREG(%eax,rINST_FULL) 6251 FETCH_INST_WORD(3) 6252 ADVANCE_PC(3) 6253 GOTO_NEXT 6254 6255/* continuation for OP_CONST_CLASS */ 6256 6257/* This is the less common path, so we'll redo some work 6258 here rather than force spills on the common path */ 6259.LOP_CONST_CLASS_resolve: 6260 GET_GLUE(%eax) 6261 movl %ecx,rINST_FULL # rINST_FULL<- AA 6262 EXPORT_PC() 6263 movl offGlue_method(%eax),%eax # eax<- glue->method 6264 movl $1,OUT_ARG2(%esp) # true 6265 movzwl 2(rPC),%ecx # ecx<- BBBB 6266 movl offMethod_clazz(%eax),%eax 6267 SPILL(rPC) 6268 movl %ecx,OUT_ARG1(%esp) 6269 movl %eax,OUT_ARG0(%esp) 6270 call dvmResolveClass # go resolve 6271 UNSPILL(rPC) 6272 testl %eax,%eax # failed? 6273 je common_exceptionThrown 6274 SET_VREG(%eax,rINST_FULL) 6275 FETCH_INST_WORD(2) 6276 ADVANCE_PC(2) 6277 GOTO_NEXT 6278 6279/* continuation for OP_MONITOR_ENTER */ 6280 6281.LOP_MONITOR_ENTER_continue: 6282 SPILL(rPC) # have to - caller save 6283 movl %ecx,OUT_ARG0(%esp) 6284 movl %eax,OUT_ARG1(%esp) 6285 call dvmLockObject # dvmLockObject(self,object) 6286 UNSPILL(rPC) 6287#ifdef WITH_DEADLOCK_PREDICTION 6288 GET_GLUE(%ecx) 6289 movl offGlueSelf(%ecx),%ecx # ecx<- glue->self 6290 movl offThread_exception(%ecx),%eax 6291 testl %eax,%eax 6292 jne common_exceptionThrown 6293#endif 6294 ADVANCE_PC(1) 6295 GOTO_NEXT 6296 6297/* continuation for OP_MONITOR_EXIT */ 6298 6299.LOP_MONITOR_EXIT_continue: 6300 call dvmUnlockObject # unlock(self,obj) 6301 UNSPILL(rPC) 6302 FETCH_INST_WORD(1) 6303 testl %eax,%eax # success? 6304 ADVANCE_PC(1) 6305 je common_exceptionThrown # no, exception pending 6306 GOTO_NEXT 6307.LOP_MONITOR_EXIT_errNullObject: 6308 ADVANCE_PC(1) # advance before throw 6309 jmp common_errNullObject 6310 6311/* continuation for OP_CHECK_CAST */ 6312 6313 /* 6314 * Trivial test failed, need to perform full check. This is common. 6315 * ecx holds obj->clazz 6316 * eax holds class resolved from BBBB 6317 * rINST_FULL holds object 6318 */ 6319.LOP_CHECK_CAST_fullcheck: 6320 movl %eax,OUT_ARG1(%esp) 6321 movl %ecx,OUT_ARG0(%esp) 6322 SPILL(rPC) 6323 call dvmInstanceofNonTrivial # eax<- boolean result 6324 UNSPILL(rPC) 6325 testl %eax,%eax # failed? 6326 jne .LOP_CHECK_CAST_okay # no, success 6327 6328 # A cast has failed. We need to throw a ClassCastException with the 6329 # class of the object that failed to be cast. 6330 EXPORT_PC() 6331 movl offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz 6332 movl $.LstrClassCastException,%eax 6333 movl offClassObject_descriptor(%ecx),%ecx 6334 movl %eax,OUT_ARG0(%esp) # arg0<- message 6335 movl %ecx,OUT_ARG1(%esp) # arg1<- obj->clazz->descriptor 6336 SPILL(rPC) 6337 call dvmThrowExceptionWithClassMessage 6338 UNSPILL(rPC) 6339 jmp common_exceptionThrown 6340 6341 /* 6342 * Resolution required. This is the least-likely path, and we're 6343 * going to have to recreate some data. 6344 * 6345 * rINST_FULL holds object 6346 */ 6347.LOP_CHECK_CAST_resolve: 6348 GET_GLUE(%ecx) 6349 EXPORT_PC() 6350 movzwl 2(rPC),%eax # eax<- BBBB 6351 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 6352 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB 6353 movl offMethod_clazz(%ecx),%ecx # ecx<- metho->clazz 6354 movl $0,OUT_ARG2(%esp) # arg2<- false 6355 movl %ecx,OUT_ARG0(%esp) # arg0<- method->clazz 6356 SPILL(rPC) 6357 call dvmResolveClass # eax<- resolved ClassObject ptr 6358 UNSPILL(rPC) 6359 testl %eax,%eax # got null? 6360 je common_exceptionThrown # yes, handle exception 6361 movl offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz 6362 jmp .LOP_CHECK_CAST_resolved # pick up where we left off 6363 6364/* continuation for OP_INSTANCE_OF */ 6365 6366 /* 6367 * Trivial test failed, need to perform full check. This is common. 6368 * eax holds obj->clazz 6369 * ecx holds class resolved from BBBB 6370 * rINST_HI has BA 6371 * rPC already spilled 6372 */ 6373.LOP_INSTANCE_OF_fullcheck: 6374 movl %eax,OUT_ARG0(%esp) 6375 movl %ecx,OUT_ARG1(%esp) 6376 call dvmInstanceofNonTrivial # eax<- boolean result 6377 # fall through to OP_INSTANCE_OF_store 6378 6379 /* 6380 * eax holds boolean result 6381 * rINST_HI holds BA 6382 */ 6383.LOP_INSTANCE_OF_store: 6384 UNSPILL(rPC) 6385 movzbl rINST_HI,%ecx # ecx<- BA 6386 FETCH_INST_WORD(2) 6387 andb $0xf,%cl # ecl<- A 6388 ADVANCE_PC(2) 6389 SET_VREG(%eax,%ecx) # vA<- eax 6390 GOTO_NEXT 6391 6392 /* 6393 * Trivial test succeeded, save and bail. 6394 * r9 holds A 6395 */ 6396.LOP_INSTANCE_OF_trivial: 6397 UNSPILL(rPC) 6398 movzbl rINST_HI,%ecx # ecx<- BA 6399 FETCH_INST_WORD(2) 6400 andb $0xf,%cl # ecl<- A 6401 ADVANCE_PC(2) 6402 movl $1,%eax 6403 SET_VREG(%eax,%ecx) # vA<- true 6404 GOTO_NEXT 6405 6406 /* 6407 * Resolution required. This is the least-likely path. 6408 * 6409 * rPC holds BBBB 6410 * rINST_HI holds BA 6411 */ 6412.LOP_INSTANCE_OF_resolve: 6413 movl rPC,OUT_ARG1(%esp) # arg1<- BBBB 6414 GET_GLUE(%ecx) 6415 UNSPILL(rPC) 6416 movl offGlue_method(%ecx),%ecx 6417 movl $1,OUT_ARG2(%esp) # arg2<- true 6418 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6419 EXPORT_PC() 6420 movl %ecx,OUT_ARG0(%esp) # arg0<- method->clazz 6421 call dvmResolveClass # eax<- resolved ClassObject ptr 6422 UNSPILL(rPC) 6423 testl %eax,%eax # success? 6424 je common_exceptionThrown # no, handle exception 6425/* Now, we need to sync up with fast path. We need eax to 6426 * hold the obj->clazz, and ecx to hold the resolved class 6427 */ 6428 movl %eax,%ecx # ecx<- resolved class 6429 movzbl rINST_HI,%eax # eax<- BA 6430 sarl $4,%eax # eax<- B 6431 GET_VREG(%eax,%eax) # eax<- vB (obj) 6432 movl offObject_clazz(%eax),%eax # eax<- obj->clazz 6433 jmp .LOP_INSTANCE_OF_resolved 6434 6435/* continuation for OP_NEW_INSTANCE */ 6436 6437.LOP_NEW_INSTANCE_initialized: # on entry, ecx<- class 6438 /* TODO: remove test for interface/abstract, now done in verifier */ 6439 testl $(ACC_INTERFACE|ACC_ABSTRACT),offClassObject_accessFlags(%ecx) 6440 movl $ALLOC_DONT_TRACK,OUT_ARG1(%esp) 6441 jne .LOP_NEW_INSTANCE_abstract 6442.LOP_NEW_INSTANCE_finish: # ecx=class 6443 movl %ecx,OUT_ARG0(%esp) 6444 call dvmAllocObject # eax<- new object 6445 UNSPILL(rPC) 6446 movl rINST_FULL,%ecx 6447 FETCH_INST_WORD(2) 6448 testl %eax,%eax # success? 6449 je common_exceptionThrown # no, bail out 6450 SET_VREG(%eax,%ecx) 6451 ADVANCE_PC(2) 6452 GOTO_NEXT 6453 6454 /* 6455 * Class initialization required. 6456 * 6457 * ecx holds class object 6458 */ 6459.LOP_NEW_INSTANCE_needinit: 6460 SPILL_TMP(%ecx) # save object 6461 movl %ecx,OUT_ARG0(%esp) 6462 call dvmInitClass # initialize class 6463 UNSPILL_TMP(%ecx) # restore object 6464 testl %eax,%eax # success? 6465 jne .LOP_NEW_INSTANCE_initialized # success, continue 6466 UNSPILL(rPC) # failed, restore PC 6467 jmp common_exceptionThrown # go deal with init exception 6468 6469 /* 6470 * Resolution required. This is the least-likely path. 6471 * 6472 */ 6473.LOP_NEW_INSTANCE_resolve: 6474 GET_GLUE(%ecx) 6475 movzwl 2(rPC),%eax 6476 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 6477 movl %eax,OUT_ARG1(%esp) 6478 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6479 movl $0,OUT_ARG2(%esp) 6480 movl %ecx,OUT_ARG0(%esp) 6481 call dvmResolveClass # call(clazz,off,flags) 6482 movl %eax,%ecx # ecx<- resolved ClassObject ptr 6483 testl %ecx,%ecx # success? 6484 jne .LOP_NEW_INSTANCE_resolved # good to go 6485 UNSPILL(rPC) 6486 jmp common_exceptionThrown # no, handle exception 6487 6488 /* 6489 * TODO: remove this 6490 * We can't instantiate an abstract class or interface, so throw an 6491 * InstantiationError with the class descriptor as the message. 6492 * 6493 * ecx holds class object 6494 */ 6495.LOP_NEW_INSTANCE_abstract: 6496 movl offClassObject_descriptor(%ecx),%eax 6497 movl $.LstrInstantiationError,OUT_ARG0(%esp) 6498 movl %eax,OUT_ARG1(%esp) 6499 call dvmThrowExceptionWithClassMessage 6500 UNSPILL(rPC) 6501 jmp common_exceptionThrown 6502 6503/* continuation for OP_NEW_ARRAY */ 6504 6505 /* 6506 * Resolve class. (This is an uncommon case.) 6507 * ecx holds class (null here) 6508 * eax holds array length (vB) 6509 */ 6510.LOP_NEW_ARRAY_resolve: 6511 GET_GLUE(%ecx) 6512 SPILL_TMP(%eax) # save array length 6513 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 6514 movzwl 2(rPC),%eax # eax<- CCCC 6515 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6516 movl %eax,OUT_ARG1(%esp) 6517 movl $0,OUT_ARG2(%esp) 6518 movl %ecx,OUT_ARG0(%esp) 6519 SPILL(rPC) 6520 call dvmResolveClass # eax<- call(clazz,ref,flag) 6521 UNSPILL(rPC) 6522 movl %eax,%ecx 6523 UNSPILL_TMP(%eax) 6524 testl %ecx,%ecx # successful resolution? 6525 je common_exceptionThrown # no, bail. 6526# fall through to OP_NEW_ARRAY_finish 6527 6528 /* 6529 * Finish allocation 6530 * 6531 * ecx holds class 6532 * eax holds array length (vB) 6533 */ 6534.LOP_NEW_ARRAY_finish: 6535 movl %ecx,OUT_ARG0(%esp) 6536 movl %eax,OUT_ARG1(%esp) 6537 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) 6538 SPILL(rPC) 6539 call dvmAllocArrayByClass # eax<- call(clazz,length,flags) 6540 UNSPILL(rPC) 6541 testl %eax,%eax # failed? 6542 je common_exceptionThrown # yup - go handle 6543 movl rINST_FULL,%ecx 6544 FETCH_INST_WORD(2) 6545 SET_VREG(%eax,%ecx) 6546 ADVANCE_PC(2) 6547 GOTO_NEXT 6548 6549/* continuation for OP_FILLED_NEW_ARRAY */ 6550 6551.LOP_FILLED_NEW_ARRAY_more: 6552 movl offMethod_clazz(%eax),%eax # eax<- method->clazz 6553 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 6554 call dvmResolveClass # eax<- call(clazz,ref,flag) 6555 UNSPILL(rPC) 6556 testl %eax,%eax # null? 6557 je common_exceptionThrown # yes, handle it 6558 6559 # note: fall through to .LOP_FILLED_NEW_ARRAY_continue 6560 6561 /* 6562 * On entry: 6563 * eax holds array class [r0] 6564 * rINST_FULL holds AA or BB [r10] 6565 * ecx is scratch 6566 * rPC is valid, but has been spilled 6567 */ 6568.LOP_FILLED_NEW_ARRAY_continue: 6569 movl offClassObject_descriptor(%eax),%ecx # ecx<- arrayClass->descriptor 6570 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags 6571 movzbl 1(%ecx),%ecx # ecx<- descriptor[1] 6572 movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass 6573 cmpb $'I',%cl # supported? 6574 je 1f 6575 cmpb $'L',%cl 6576 je 1f 6577 cmpb $'[',%cl 6578 jne .LOP_FILLED_NEW_ARRAY_notimpl # no, not handled yet 65791: 6580 .if (!0) 6581 SPILL_TMP(rINST_FULL) # save copy, need "B" later 6582 sarl $4,rINST_FULL 6583 .endif 6584 movl rINST_FULL,OUT_ARG1(%esp) # arg1<- A or AA (length) 6585 call dvmAllocArrayByClass # eax<- call(arrayClass, length, flags) 6586 UNSPILL(rPC) 6587 GET_GLUE(%ecx) 6588 testl %eax,%eax # alloc successful? 6589 je common_exceptionThrown # no, handle exception 6590 movl %eax,offGlue_retval(%ecx) # retval.l<- new array 6591 movzwl 4(rPC),%ecx # ecx<- FEDC or CCCC 6592 leal offArrayObject_contents(%eax),%eax # eax<- newArray->contents 6593 6594/* at this point: 6595 * eax is pointer to tgt 6596 * rINST_FULL is length 6597 * ecx is FEDC or CCCC 6598 * TMP_SPILL is BA 6599 * rPC is valid, but spilled 6600 * We now need to copy values from registers into the array 6601 */ 6602 6603 .if 0 6604 # set up src pointer 6605 SPILL(rFP) # esi 6606 SPILL(rIBASE) # edi 6607 movl %eax,%edi # set up dst ptr 6608 leal (rFP,%ecx,4),%esi # set up src ptr 6609 movl rINST_FULL,%ecx # load count register 6610 FETCH_INST_WORD(3) 6611 rep 6612 movsd 6613 UNSPILL(rIBASE) 6614 UNSPILL(rFP) 6615 .else 6616 testl rINST_FULL,rINST_FULL 6617 je 4f 6618 UNSPILL_TMP(rPC) 6619 andl $0x0f,rPC # rPC<- 0000000A 6620 sall $16,rPC # rPC<- 000A0000 6621 orl %ecx,rPC # rpc<- 000AFEDC 66223: 6623 movl $0xf,%ecx 6624 andl rPC,%ecx # ecx<- next reg to load 6625 GET_VREG(%ecx,%ecx) 6626 shrl $4,rPC 6627 leal 4(%eax),%eax 6628 movl %ecx,-4(%eax) 6629 sub $1,rINST_FULL 6630 jne 3b 66314: 6632 UNSPILL(rPC) 6633 FETCH_INST_WORD(3) 6634 .endif 6635 6636 ADVANCE_PC(3) 6637 GOTO_NEXT 6638 6639 6640 /* 6641 * Throw an exception indicating that we have not implemented this 6642 * mode of filled-new-array. 6643 */ 6644.LOP_FILLED_NEW_ARRAY_notimpl: 6645 movl $.LstrInternalError,%eax 6646 movl %eax,OUT_ARG0(%esp) 6647 movl $.LstrFilledNewArrayNotImpl,%eax 6648 movl %eax,OUT_ARG1(%esp) 6649 call dvmThrowException 6650 UNSPILL(rPC) 6651 jmp common_exceptionThrown 6652 6653/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 6654 6655.LOP_FILLED_NEW_ARRAY_RANGE_more: 6656 movl offMethod_clazz(%eax),%eax # eax<- method->clazz 6657 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 6658 call dvmResolveClass # eax<- call(clazz,ref,flag) 6659 UNSPILL(rPC) 6660 testl %eax,%eax # null? 6661 je common_exceptionThrown # yes, handle it 6662 6663 # note: fall through to .LOP_FILLED_NEW_ARRAY_RANGE_continue 6664 6665 /* 6666 * On entry: 6667 * eax holds array class [r0] 6668 * rINST_FULL holds AA or BB [r10] 6669 * ecx is scratch 6670 * rPC is valid, but has been spilled 6671 */ 6672.LOP_FILLED_NEW_ARRAY_RANGE_continue: 6673 movl offClassObject_descriptor(%eax),%ecx # ecx<- arrayClass->descriptor 6674 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags 6675 movzbl 1(%ecx),%ecx # ecx<- descriptor[1] 6676 movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass 6677 cmpb $'I',%cl # supported? 6678 je 1f 6679 cmpb $'L',%cl 6680 je 1f 6681 cmpb $'[',%cl 6682 jne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl # no, not handled yet 66831: 6684 .if (!1) 6685 SPILL_TMP(rINST_FULL) # save copy, need "B" later 6686 sarl $4,rINST_FULL 6687 .endif 6688 movl rINST_FULL,OUT_ARG1(%esp) # arg1<- A or AA (length) 6689 call dvmAllocArrayByClass # eax<- call(arrayClass, length, flags) 6690 UNSPILL(rPC) 6691 GET_GLUE(%ecx) 6692 testl %eax,%eax # alloc successful? 6693 je common_exceptionThrown # no, handle exception 6694 movl %eax,offGlue_retval(%ecx) # retval.l<- new array 6695 movzwl 4(rPC),%ecx # ecx<- FEDC or CCCC 6696 leal offArrayObject_contents(%eax),%eax # eax<- newArray->contents 6697 6698/* at this point: 6699 * eax is pointer to tgt 6700 * rINST_FULL is length 6701 * ecx is FEDC or CCCC 6702 * TMP_SPILL is BA 6703 * rPC is valid, but spilled 6704 * We now need to copy values from registers into the array 6705 */ 6706 6707 .if 1 6708 # set up src pointer 6709 SPILL(rFP) # esi 6710 SPILL(rIBASE) # edi 6711 movl %eax,%edi # set up dst ptr 6712 leal (rFP,%ecx,4),%esi # set up src ptr 6713 movl rINST_FULL,%ecx # load count register 6714 FETCH_INST_WORD(3) 6715 rep 6716 movsd 6717 UNSPILL(rIBASE) 6718 UNSPILL(rFP) 6719 .else 6720 testl rINST_FULL,rINST_FULL 6721 je 4f 6722 UNSPILL_TMP(rPC) 6723 andl $0x0f,rPC # rPC<- 0000000A 6724 sall $16,rPC # rPC<- 000A0000 6725 orl %ecx,rPC # rpc<- 000AFEDC 67263: 6727 movl $0xf,%ecx 6728 andl rPC,%ecx # ecx<- next reg to load 6729 GET_VREG(%ecx,%ecx) 6730 shrl $4,rPC 6731 leal 4(%eax),%eax 6732 movl %ecx,-4(%eax) 6733 sub $1,rINST_FULL 6734 jne 3b 67354: 6736 UNSPILL(rPC) 6737 FETCH_INST_WORD(3) 6738 .endif 6739 6740 ADVANCE_PC(3) 6741 GOTO_NEXT 6742 6743 6744 /* 6745 * Throw an exception indicating that we have not implemented this 6746 * mode of filled-new-array. 6747 */ 6748.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 6749 movl $.LstrInternalError,%eax 6750 movl %eax,OUT_ARG0(%esp) 6751 movl $.LstrFilledNewArrayNotImpl,%eax 6752 movl %eax,OUT_ARG1(%esp) 6753 call dvmThrowException 6754 UNSPILL(rPC) 6755 jmp common_exceptionThrown 6756 6757/* continuation for OP_CMPL_FLOAT */ 6758 6759.LOP_CMPL_FLOAT_isNaN: 6760 movl $-1,%ecx 6761 jmp .LOP_CMPL_FLOAT_finish 6762 6763/* continuation for OP_CMPG_FLOAT */ 6764 6765.LOP_CMPG_FLOAT_isNaN: 6766 movl $1,%ecx 6767 jmp .LOP_CMPG_FLOAT_finish 6768 6769/* continuation for OP_CMPL_DOUBLE */ 6770 6771.LOP_CMPL_DOUBLE_isNaN: 6772 movl $-1,%ecx 6773 jmp .LOP_CMPL_DOUBLE_finish 6774 6775/* continuation for OP_CMPG_DOUBLE */ 6776 6777.LOP_CMPG_DOUBLE_isNaN: 6778 movl $1,%ecx 6779 jmp .LOP_CMPG_DOUBLE_finish 6780 6781/* continuation for OP_CMP_LONG */ 6782 6783.LOP_CMP_LONG_bigger: 6784 UNSPILL(rPC) 6785 movl $1,%ecx 6786 jmp .LOP_CMP_LONG_finish 6787.LOP_CMP_LONG_smaller: 6788 UNSPILL(rPC) 6789 movl $-1,%ecx 6790.LOP_CMP_LONG_finish: 6791 SET_VREG(%ecx,rINST_FULL) 6792 FETCH_INST_WORD(2) 6793 ADVANCE_PC(2) 6794 GOTO_NEXT 6795 6796/* continuation for OP_AGET_WIDE */ 6797 6798.LOP_AGET_WIDE_finish: 6799 leal offArrayObject_contents(%eax,%ecx,8),%eax 6800 movl (%eax),%ecx 6801 movl 4(%eax),%eax 6802 SET_VREG_WORD(%ecx,rINST_FULL,0) 6803 SET_VREG_WORD(%eax,rINST_FULL,1) 6804 FETCH_INST_WORD(2) 6805 ADVANCE_PC(2) 6806 GOTO_NEXT 6807 6808/* continuation for OP_APUT_WIDE */ 6809 6810.LOP_APUT_WIDE_finish: 6811 leal offArrayObject_contents(%eax,%ecx,8),%eax 6812 GET_VREG_WORD(%ecx,rINST_FULL,0) 6813 GET_VREG_WORD(rINST_FULL,rINST_FULL,1) 6814 movl rINST_FULL,4(%eax) 6815 FETCH_INST_WORD(2) 6816 movl %ecx,(%eax) 6817 ADVANCE_PC(2) 6818 GOTO_NEXT 6819 6820/* continuation for OP_APUT_OBJECT */ 6821 6822 /* On entry: 6823 * eax<- array object 6824 * ecx<- index 6825 * rINST_FULL<- vAA 6826 */ 6827.LOP_APUT_OBJECT_continue: 6828 leal offArrayObject_contents(%eax,%ecx,4),%ecx 6829 testl rINST_FULL,rINST_FULL # storing null reference? 6830 je .LOP_APUT_OBJECT_skip_check 6831 SPILL(rPC) 6832 SPILL_TMP(%ecx) 6833 movl offObject_clazz(%eax),%eax # eax<- arrayObj->clazz 6834 movl offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz 6835 movl %eax,OUT_ARG1(%esp) 6836 movl %ecx,OUT_ARG0(%esp) 6837 call dvmCanPutArrayElement # test object type vs. array type 6838 UNSPILL(rPC) 6839 UNSPILL_TMP(%ecx) 6840 testl %eax,%eax 6841 je common_errArrayStore 6842 6843.LOP_APUT_OBJECT_skip_check: 6844 movl rINST_FULL,(%ecx) 6845 FETCH_INST_WORD(2) 6846 ADVANCE_PC(2) 6847 GOTO_NEXT 6848 6849/* continuation for OP_IGET */ 6850 6851 6852.LOP_IGET_resolve: 6853 EXPORT_PC() 6854 SPILL(rPC) 6855 movl offGlue_method(rIBASE),rPC # rPC<- current method 6856 UNSPILL(rIBASE) 6857 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 6858 SPILL_TMP(%ecx) # save object pointer across call 6859 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 6860 call dvmResolveInstField # ... to dvmResolveInstField 6861 UNSPILL_TMP(%ecx) 6862 UNSPILL(rPC) 6863 testl %eax,%eax # ... which returns InstrField ptr 6864 jne .LOP_IGET_finish 6865 jmp common_exceptionThrown 6866 6867.LOP_IGET_finish: 6868 /* 6869 * Currently: 6870 * eax holds resolved field 6871 * ecx holds object 6872 * rIBASE is scratch, but needs to be unspilled 6873 * rINST_FULL holds A 6874 */ 6875 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 6876 UNSPILL(rIBASE) 6877 testl %ecx,%ecx # object null? 6878 je common_errNullObject # object was null 6879 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 6880 movl rINST_FULL,%eax # eax<- A 6881 FETCH_INST_WORD(2) 6882 SET_VREG(%ecx,%eax) 6883 ADVANCE_PC(2) 6884 GOTO_NEXT 6885 6886/* continuation for OP_IGET_WIDE */ 6887 6888 6889.LOP_IGET_WIDE_resolve: 6890 EXPORT_PC() 6891 SPILL(rPC) 6892 movl offGlue_method(rIBASE),rPC # rPC<- current method 6893 UNSPILL(rIBASE) 6894 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 6895 SPILL_TMP(%ecx) # save object pointer across call 6896 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 6897 call dvmResolveInstField # ... to dvmResolveInstField 6898 UNSPILL_TMP(%ecx) 6899 UNSPILL(rPC) 6900 testl %eax,%eax # ... which returns InstrField ptr 6901 jne .LOP_IGET_WIDE_finish 6902 jmp common_exceptionThrown 6903 6904.LOP_IGET_WIDE_finish: 6905 /* 6906 * Currently: 6907 * eax holds resolved field 6908 * ecx holds object 6909 * rIBASE is scratch, but needs to be unspilled 6910 * rINST_FULL holds A 6911 */ 6912 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 6913 UNSPILL(rIBASE) 6914 testl %ecx,%ecx # object null? 6915 je common_errNullObject # object was null 6916 leal (%ecx,%eax,1),%eax # eax<- address of field 6917 movl (%eax),%ecx # ecx<- lsw 6918 movl 4(%eax),%eax # eax<- msw 6919 SET_VREG_WORD(%ecx,rINST_FULL,0) 6920 SET_VREG_WORD(%eax,rINST_FULL,1) 6921 FETCH_INST_WORD(2) 6922 ADVANCE_PC(2) 6923 GOTO_NEXT 6924 6925/* continuation for OP_IGET_OBJECT */ 6926 6927 6928.LOP_IGET_OBJECT_resolve: 6929 EXPORT_PC() 6930 SPILL(rPC) 6931 movl offGlue_method(rIBASE),rPC # rPC<- current method 6932 UNSPILL(rIBASE) 6933 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 6934 SPILL_TMP(%ecx) # save object pointer across call 6935 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 6936 call dvmResolveInstField # ... to dvmResolveInstField 6937 UNSPILL_TMP(%ecx) 6938 UNSPILL(rPC) 6939 testl %eax,%eax # ... which returns InstrField ptr 6940 jne .LOP_IGET_OBJECT_finish 6941 jmp common_exceptionThrown 6942 6943.LOP_IGET_OBJECT_finish: 6944 /* 6945 * Currently: 6946 * eax holds resolved field 6947 * ecx holds object 6948 * rIBASE is scratch, but needs to be unspilled 6949 * rINST_FULL holds A 6950 */ 6951 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 6952 UNSPILL(rIBASE) 6953 testl %ecx,%ecx # object null? 6954 je common_errNullObject # object was null 6955 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 6956 movl rINST_FULL,%eax # eax<- A 6957 FETCH_INST_WORD(2) 6958 SET_VREG(%ecx,%eax) 6959 ADVANCE_PC(2) 6960 GOTO_NEXT 6961 6962/* continuation for OP_IGET_BOOLEAN */ 6963 6964 6965.LOP_IGET_BOOLEAN_resolve: 6966 EXPORT_PC() 6967 SPILL(rPC) 6968 movl offGlue_method(rIBASE),rPC # rPC<- current method 6969 UNSPILL(rIBASE) 6970 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 6971 SPILL_TMP(%ecx) # save object pointer across call 6972 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 6973 call dvmResolveInstField # ... to dvmResolveInstField 6974 UNSPILL_TMP(%ecx) 6975 UNSPILL(rPC) 6976 testl %eax,%eax # ... which returns InstrField ptr 6977 jne .LOP_IGET_BOOLEAN_finish 6978 jmp common_exceptionThrown 6979 6980.LOP_IGET_BOOLEAN_finish: 6981 /* 6982 * Currently: 6983 * eax holds resolved field 6984 * ecx holds object 6985 * rIBASE is scratch, but needs to be unspilled 6986 * rINST_FULL holds A 6987 */ 6988 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 6989 UNSPILL(rIBASE) 6990 testl %ecx,%ecx # object null? 6991 je common_errNullObject # object was null 6992 movzbl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 6993 movl rINST_FULL,%eax # eax<- A 6994 FETCH_INST_WORD(2) 6995 SET_VREG(%ecx,%eax) 6996 ADVANCE_PC(2) 6997 GOTO_NEXT 6998 6999/* continuation for OP_IGET_BYTE */ 7000 7001 7002.LOP_IGET_BYTE_resolve: 7003 EXPORT_PC() 7004 SPILL(rPC) 7005 movl offGlue_method(rIBASE),rPC # rPC<- current method 7006 UNSPILL(rIBASE) 7007 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7008 SPILL_TMP(%ecx) # save object pointer across call 7009 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7010 call dvmResolveInstField # ... to dvmResolveInstField 7011 UNSPILL_TMP(%ecx) 7012 UNSPILL(rPC) 7013 testl %eax,%eax # ... which returns InstrField ptr 7014 jne .LOP_IGET_BYTE_finish 7015 jmp common_exceptionThrown 7016 7017.LOP_IGET_BYTE_finish: 7018 /* 7019 * Currently: 7020 * eax holds resolved field 7021 * ecx holds object 7022 * rIBASE is scratch, but needs to be unspilled 7023 * rINST_FULL holds A 7024 */ 7025 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7026 UNSPILL(rIBASE) 7027 testl %ecx,%ecx # object null? 7028 je common_errNullObject # object was null 7029 movsbl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7030 movl rINST_FULL,%eax # eax<- A 7031 FETCH_INST_WORD(2) 7032 SET_VREG(%ecx,%eax) 7033 ADVANCE_PC(2) 7034 GOTO_NEXT 7035 7036/* continuation for OP_IGET_CHAR */ 7037 7038 7039.LOP_IGET_CHAR_resolve: 7040 EXPORT_PC() 7041 SPILL(rPC) 7042 movl offGlue_method(rIBASE),rPC # rPC<- current method 7043 UNSPILL(rIBASE) 7044 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7045 SPILL_TMP(%ecx) # save object pointer across call 7046 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7047 call dvmResolveInstField # ... to dvmResolveInstField 7048 UNSPILL_TMP(%ecx) 7049 UNSPILL(rPC) 7050 testl %eax,%eax # ... which returns InstrField ptr 7051 jne .LOP_IGET_CHAR_finish 7052 jmp common_exceptionThrown 7053 7054.LOP_IGET_CHAR_finish: 7055 /* 7056 * Currently: 7057 * eax holds resolved field 7058 * ecx holds object 7059 * rIBASE is scratch, but needs to be unspilled 7060 * rINST_FULL holds A 7061 */ 7062 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7063 UNSPILL(rIBASE) 7064 testl %ecx,%ecx # object null? 7065 je common_errNullObject # object was null 7066 movzwl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7067 movl rINST_FULL,%eax # eax<- A 7068 FETCH_INST_WORD(2) 7069 SET_VREG(%ecx,%eax) 7070 ADVANCE_PC(2) 7071 GOTO_NEXT 7072 7073/* continuation for OP_IGET_SHORT */ 7074 7075 7076.LOP_IGET_SHORT_resolve: 7077 EXPORT_PC() 7078 SPILL(rPC) 7079 movl offGlue_method(rIBASE),rPC # rPC<- current method 7080 UNSPILL(rIBASE) 7081 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7082 SPILL_TMP(%ecx) # save object pointer across call 7083 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7084 call dvmResolveInstField # ... to dvmResolveInstField 7085 UNSPILL_TMP(%ecx) 7086 UNSPILL(rPC) 7087 testl %eax,%eax # ... which returns InstrField ptr 7088 jne .LOP_IGET_SHORT_finish 7089 jmp common_exceptionThrown 7090 7091.LOP_IGET_SHORT_finish: 7092 /* 7093 * Currently: 7094 * eax holds resolved field 7095 * ecx holds object 7096 * rIBASE is scratch, but needs to be unspilled 7097 * rINST_FULL holds A 7098 */ 7099 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7100 UNSPILL(rIBASE) 7101 testl %ecx,%ecx # object null? 7102 je common_errNullObject # object was null 7103 movswl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7104 movl rINST_FULL,%eax # eax<- A 7105 FETCH_INST_WORD(2) 7106 SET_VREG(%ecx,%eax) 7107 ADVANCE_PC(2) 7108 GOTO_NEXT 7109 7110/* continuation for OP_IPUT */ 7111 7112 7113.LOP_IPUT_resolve: 7114 EXPORT_PC() 7115 SPILL(rPC) 7116 movl offGlue_method(rIBASE),rPC # rPC<- current method 7117 UNSPILL(rIBASE) 7118 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7119 SPILL_TMP(%ecx) # save object pointer across call 7120 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7121 call dvmResolveInstField # ... to dvmResolveInstField 7122 UNSPILL_TMP(%ecx) 7123 UNSPILL(rPC) 7124 testl %eax,%eax # ... which returns InstrField ptr 7125 jne .LOP_IPUT_finish 7126 jmp common_exceptionThrown 7127 7128.LOP_IPUT_finish: 7129 /* 7130 * Currently: 7131 * eax holds resolved field 7132 * ecx holds object 7133 * rIBASE is scratch, but needs to be unspilled 7134 * rINST_FULL holds A 7135 */ 7136 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 7137 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7138 UNSPILL(rIBASE) 7139 testl %ecx,%ecx # object null? 7140 je common_errNullObject # object was null 7141 movl rINST_FULL,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7142 FETCH_INST_WORD(2) 7143 ADVANCE_PC(2) 7144 GOTO_NEXT 7145 7146/* continuation for OP_IPUT_WIDE */ 7147 7148 7149.LOP_IPUT_WIDE_resolve: 7150 EXPORT_PC() 7151 SPILL(rPC) 7152 movl offGlue_method(rIBASE),rPC # rPC<- current method 7153 UNSPILL(rIBASE) 7154 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7155 SPILL_TMP(%ecx) # save object pointer across call 7156 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7157 call dvmResolveInstField # ... to dvmResolveInstField 7158 UNSPILL_TMP(%ecx) 7159 UNSPILL(rPC) 7160 testl %eax,%eax # ... which returns InstrField ptr 7161 jne .LOP_IPUT_WIDE_finish 7162 jmp common_exceptionThrown 7163 7164.LOP_IPUT_WIDE_finish: 7165 /* 7166 * Currently: 7167 * eax holds resolved field 7168 * ecx holds object 7169 * rIBASE is scratch, but needs to be unspilled 7170 * rINST_FULL holds A 7171 */ 7172 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7173 UNSPILL(rIBASE) 7174 testl %ecx,%ecx # object null? 7175 je common_errNullObject # object was null 7176 leal (%ecx,%eax,1),%eax # eax<- address of field 7177 GET_VREG_WORD(%ecx,rINST_FULL,0) # ecx<- lsw 7178 GET_VREG_WORD(rINST_FULL,rINST_FULL,1) # rINST_FULL<- msw 7179 movl rINST_FULL,4(%eax) 7180 FETCH_INST_WORD(2) 7181 movl %ecx,(%eax) 7182 ADVANCE_PC(2) 7183 GOTO_NEXT 7184 7185/* continuation for OP_IPUT_OBJECT */ 7186 7187 7188.LOP_IPUT_OBJECT_resolve: 7189 EXPORT_PC() 7190 SPILL(rPC) 7191 movl offGlue_method(rIBASE),rPC # rPC<- current method 7192 UNSPILL(rIBASE) 7193 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7194 SPILL_TMP(%ecx) # save object pointer across call 7195 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7196 call dvmResolveInstField # ... to dvmResolveInstField 7197 UNSPILL_TMP(%ecx) 7198 UNSPILL(rPC) 7199 testl %eax,%eax # ... which returns InstrField ptr 7200 jne .LOP_IPUT_OBJECT_finish 7201 jmp common_exceptionThrown 7202 7203.LOP_IPUT_OBJECT_finish: 7204 /* 7205 * Currently: 7206 * eax holds resolved field 7207 * ecx holds object 7208 * rIBASE is scratch, but needs to be unspilled 7209 * rINST_FULL holds A 7210 */ 7211 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 7212 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7213 UNSPILL(rIBASE) 7214 testl %ecx,%ecx # object null? 7215 je common_errNullObject # object was null 7216 movl rINST_FULL,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7217 FETCH_INST_WORD(2) 7218 ADVANCE_PC(2) 7219 GOTO_NEXT 7220 7221/* continuation for OP_IPUT_BOOLEAN */ 7222 7223 7224.LOP_IPUT_BOOLEAN_resolve: 7225 EXPORT_PC() 7226 SPILL(rPC) 7227 movl offGlue_method(rIBASE),rPC # rPC<- current method 7228 UNSPILL(rIBASE) 7229 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7230 SPILL_TMP(%ecx) # save object pointer across call 7231 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7232 call dvmResolveInstField # ... to dvmResolveInstField 7233 UNSPILL_TMP(%ecx) 7234 UNSPILL(rPC) 7235 testl %eax,%eax # ... which returns InstrField ptr 7236 jne .LOP_IPUT_BOOLEAN_finish 7237 jmp common_exceptionThrown 7238 7239.LOP_IPUT_BOOLEAN_finish: 7240 /* 7241 * Currently: 7242 * eax holds resolved field 7243 * ecx holds object 7244 * rIBASE is scratch, but needs to be unspilled 7245 * rINST_FULL holds A 7246 */ 7247 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 7248 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7249 UNSPILL(rIBASE) 7250 testl %ecx,%ecx # object null? 7251 je common_errNullObject # object was null 7252 movb rINST_LO,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7253 FETCH_INST_WORD(2) 7254 ADVANCE_PC(2) 7255 GOTO_NEXT 7256 7257/* continuation for OP_IPUT_BYTE */ 7258 7259 7260.LOP_IPUT_BYTE_resolve: 7261 EXPORT_PC() 7262 SPILL(rPC) 7263 movl offGlue_method(rIBASE),rPC # rPC<- current method 7264 UNSPILL(rIBASE) 7265 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7266 SPILL_TMP(%ecx) # save object pointer across call 7267 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7268 call dvmResolveInstField # ... to dvmResolveInstField 7269 UNSPILL_TMP(%ecx) 7270 UNSPILL(rPC) 7271 testl %eax,%eax # ... which returns InstrField ptr 7272 jne .LOP_IPUT_BYTE_finish 7273 jmp common_exceptionThrown 7274 7275.LOP_IPUT_BYTE_finish: 7276 /* 7277 * Currently: 7278 * eax holds resolved field 7279 * ecx holds object 7280 * rIBASE is scratch, but needs to be unspilled 7281 * rINST_FULL holds A 7282 */ 7283 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 7284 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7285 UNSPILL(rIBASE) 7286 testl %ecx,%ecx # object null? 7287 je common_errNullObject # object was null 7288 movb rINST_LO,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7289 FETCH_INST_WORD(2) 7290 ADVANCE_PC(2) 7291 GOTO_NEXT 7292 7293/* continuation for OP_IPUT_CHAR */ 7294 7295 7296.LOP_IPUT_CHAR_resolve: 7297 EXPORT_PC() 7298 SPILL(rPC) 7299 movl offGlue_method(rIBASE),rPC # rPC<- current method 7300 UNSPILL(rIBASE) 7301 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7302 SPILL_TMP(%ecx) # save object pointer across call 7303 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7304 call dvmResolveInstField # ... to dvmResolveInstField 7305 UNSPILL_TMP(%ecx) 7306 UNSPILL(rPC) 7307 testl %eax,%eax # ... which returns InstrField ptr 7308 jne .LOP_IPUT_CHAR_finish 7309 jmp common_exceptionThrown 7310 7311.LOP_IPUT_CHAR_finish: 7312 /* 7313 * Currently: 7314 * eax holds resolved field 7315 * ecx holds object 7316 * rIBASE is scratch, but needs to be unspilled 7317 * rINST_FULL holds A 7318 */ 7319 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 7320 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7321 UNSPILL(rIBASE) 7322 testl %ecx,%ecx # object null? 7323 je common_errNullObject # object was null 7324 movw rINST,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7325 FETCH_INST_WORD(2) 7326 ADVANCE_PC(2) 7327 GOTO_NEXT 7328 7329/* continuation for OP_IPUT_SHORT */ 7330 7331 7332.LOP_IPUT_SHORT_resolve: 7333 EXPORT_PC() 7334 SPILL(rPC) 7335 movl offGlue_method(rIBASE),rPC # rPC<- current method 7336 UNSPILL(rIBASE) 7337 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7338 SPILL_TMP(%ecx) # save object pointer across call 7339 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7340 call dvmResolveInstField # ... to dvmResolveInstField 7341 UNSPILL_TMP(%ecx) 7342 UNSPILL(rPC) 7343 testl %eax,%eax # ... which returns InstrField ptr 7344 jne .LOP_IPUT_SHORT_finish 7345 jmp common_exceptionThrown 7346 7347.LOP_IPUT_SHORT_finish: 7348 /* 7349 * Currently: 7350 * eax holds resolved field 7351 * ecx holds object 7352 * rIBASE is scratch, but needs to be unspilled 7353 * rINST_FULL holds A 7354 */ 7355 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 7356 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7357 UNSPILL(rIBASE) 7358 testl %ecx,%ecx # object null? 7359 je common_errNullObject # object was null 7360 movw rINST,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7361 FETCH_INST_WORD(2) 7362 ADVANCE_PC(2) 7363 GOTO_NEXT 7364 7365/* continuation for OP_SGET */ 7366 7367 /* 7368 * Go resolve the field 7369 */ 7370.LOP_SGET_resolve: 7371 GET_GLUE(%ecx) 7372 movzwl 2(rPC),%eax # eax<- field ref BBBB 7373 movl offGlue_method(%ecx),%ecx # ecx<- current method 7374 EXPORT_PC() # could throw, need to export 7375 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7376 SPILL(rPC) 7377 movl %eax,OUT_ARG1(%esp) 7378 movl %ecx,OUT_ARG0(%esp) 7379 call dvmResolveStaticField # eax<- resolved StaticField ptr 7380 UNSPILL(rPC) 7381 testl %eax,%eax 7382 jne .LOP_SGET_finish # success, continue 7383 jmp common_exceptionThrown # no, handle exception 7384 7385/* continuation for OP_SGET_WIDE */ 7386 7387 /* 7388 * Go resolve the field 7389 */ 7390.LOP_SGET_WIDE_resolve: 7391 GET_GLUE(%ecx) 7392 movzwl 2(rPC),%eax # eax<- field ref BBBB 7393 movl offGlue_method(%ecx),%ecx # ecx<- current method 7394 EXPORT_PC() # could throw, need to export 7395 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7396 SPILL(rPC) 7397 movl %eax,OUT_ARG1(%esp) 7398 movl %ecx,OUT_ARG0(%esp) 7399 call dvmResolveStaticField # eax<- resolved StaticField ptr 7400 UNSPILL(rPC) 7401 testl %eax,%eax 7402 jne .LOP_SGET_WIDE_finish # success, continue 7403 jmp common_exceptionThrown # no, handle exception 7404 7405/* continuation for OP_SGET_OBJECT */ 7406 7407 /* 7408 * Go resolve the field 7409 */ 7410.LOP_SGET_OBJECT_resolve: 7411 GET_GLUE(%ecx) 7412 movzwl 2(rPC),%eax # eax<- field ref BBBB 7413 movl offGlue_method(%ecx),%ecx # ecx<- current method 7414 EXPORT_PC() # could throw, need to export 7415 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7416 SPILL(rPC) 7417 movl %eax,OUT_ARG1(%esp) 7418 movl %ecx,OUT_ARG0(%esp) 7419 call dvmResolveStaticField # eax<- resolved StaticField ptr 7420 UNSPILL(rPC) 7421 testl %eax,%eax 7422 jne .LOP_SGET_OBJECT_finish # success, continue 7423 jmp common_exceptionThrown # no, handle exception 7424 7425/* continuation for OP_SGET_BOOLEAN */ 7426 7427 /* 7428 * Go resolve the field 7429 */ 7430.LOP_SGET_BOOLEAN_resolve: 7431 GET_GLUE(%ecx) 7432 movzwl 2(rPC),%eax # eax<- field ref BBBB 7433 movl offGlue_method(%ecx),%ecx # ecx<- current method 7434 EXPORT_PC() # could throw, need to export 7435 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7436 SPILL(rPC) 7437 movl %eax,OUT_ARG1(%esp) 7438 movl %ecx,OUT_ARG0(%esp) 7439 call dvmResolveStaticField # eax<- resolved StaticField ptr 7440 UNSPILL(rPC) 7441 testl %eax,%eax 7442 jne .LOP_SGET_BOOLEAN_finish # success, continue 7443 jmp common_exceptionThrown # no, handle exception 7444 7445/* continuation for OP_SGET_BYTE */ 7446 7447 /* 7448 * Go resolve the field 7449 */ 7450.LOP_SGET_BYTE_resolve: 7451 GET_GLUE(%ecx) 7452 movzwl 2(rPC),%eax # eax<- field ref BBBB 7453 movl offGlue_method(%ecx),%ecx # ecx<- current method 7454 EXPORT_PC() # could throw, need to export 7455 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7456 SPILL(rPC) 7457 movl %eax,OUT_ARG1(%esp) 7458 movl %ecx,OUT_ARG0(%esp) 7459 call dvmResolveStaticField # eax<- resolved StaticField ptr 7460 UNSPILL(rPC) 7461 testl %eax,%eax 7462 jne .LOP_SGET_BYTE_finish # success, continue 7463 jmp common_exceptionThrown # no, handle exception 7464 7465/* continuation for OP_SGET_CHAR */ 7466 7467 /* 7468 * Go resolve the field 7469 */ 7470.LOP_SGET_CHAR_resolve: 7471 GET_GLUE(%ecx) 7472 movzwl 2(rPC),%eax # eax<- field ref BBBB 7473 movl offGlue_method(%ecx),%ecx # ecx<- current method 7474 EXPORT_PC() # could throw, need to export 7475 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7476 SPILL(rPC) 7477 movl %eax,OUT_ARG1(%esp) 7478 movl %ecx,OUT_ARG0(%esp) 7479 call dvmResolveStaticField # eax<- resolved StaticField ptr 7480 UNSPILL(rPC) 7481 testl %eax,%eax 7482 jne .LOP_SGET_CHAR_finish # success, continue 7483 jmp common_exceptionThrown # no, handle exception 7484 7485/* continuation for OP_SGET_SHORT */ 7486 7487 /* 7488 * Go resolve the field 7489 */ 7490.LOP_SGET_SHORT_resolve: 7491 GET_GLUE(%ecx) 7492 movzwl 2(rPC),%eax # eax<- field ref BBBB 7493 movl offGlue_method(%ecx),%ecx # ecx<- current method 7494 EXPORT_PC() # could throw, need to export 7495 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7496 SPILL(rPC) 7497 movl %eax,OUT_ARG1(%esp) 7498 movl %ecx,OUT_ARG0(%esp) 7499 call dvmResolveStaticField # eax<- resolved StaticField ptr 7500 UNSPILL(rPC) 7501 testl %eax,%eax 7502 jne .LOP_SGET_SHORT_finish # success, continue 7503 jmp common_exceptionThrown # no, handle exception 7504 7505/* continuation for OP_SPUT */ 7506 7507 /* 7508 * Go resolve the field 7509 */ 7510.LOP_SPUT_resolve: 7511 GET_GLUE(%ecx) 7512 movzwl 2(rPC),%eax # eax<- field ref BBBB 7513 movl offGlue_method(%ecx),%ecx # ecx<- current method 7514 EXPORT_PC() # could throw, need to export 7515 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7516 SPILL(rPC) 7517 movl %eax,OUT_ARG1(%esp) 7518 movl %ecx,OUT_ARG0(%esp) 7519 call dvmResolveStaticField # eax<- resolved StaticField ptr 7520 UNSPILL(rPC) 7521 testl %eax,%eax 7522 jne .LOP_SPUT_finish # success, continue 7523 jmp common_exceptionThrown # no, handle exception 7524 7525/* continuation for OP_SPUT_WIDE */ 7526 7527 /* 7528 * Go resolve the field 7529 */ 7530.LOP_SPUT_WIDE_resolve: 7531 GET_GLUE(%ecx) 7532 movzwl 2(rPC),%eax # eax<- field ref BBBB 7533 movl offGlue_method(%ecx),%ecx # ecx<- current method 7534 EXPORT_PC() # could throw, need to export 7535 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7536 SPILL(rPC) 7537 movl %eax,OUT_ARG1(%esp) 7538 movl %ecx,OUT_ARG0(%esp) 7539 call dvmResolveStaticField # eax<- resolved StaticField ptr 7540 UNSPILL(rPC) 7541 testl %eax,%eax 7542 jne .LOP_SPUT_WIDE_finish # success, continue 7543 jmp common_exceptionThrown # no, handle exception 7544 7545/* continuation for OP_SPUT_OBJECT */ 7546 7547 /* 7548 * Go resolve the field 7549 */ 7550.LOP_SPUT_OBJECT_resolve: 7551 GET_GLUE(%ecx) 7552 movzwl 2(rPC),%eax # eax<- field ref BBBB 7553 movl offGlue_method(%ecx),%ecx # ecx<- current method 7554 EXPORT_PC() # could throw, need to export 7555 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7556 SPILL(rPC) 7557 movl %eax,OUT_ARG1(%esp) 7558 movl %ecx,OUT_ARG0(%esp) 7559 call dvmResolveStaticField # eax<- resolved StaticField ptr 7560 UNSPILL(rPC) 7561 testl %eax,%eax 7562 jne .LOP_SPUT_OBJECT_finish # success, continue 7563 jmp common_exceptionThrown # no, handle exception 7564 7565/* continuation for OP_SPUT_BOOLEAN */ 7566 7567 /* 7568 * Go resolve the field 7569 */ 7570.LOP_SPUT_BOOLEAN_resolve: 7571 GET_GLUE(%ecx) 7572 movzwl 2(rPC),%eax # eax<- field ref BBBB 7573 movl offGlue_method(%ecx),%ecx # ecx<- current method 7574 EXPORT_PC() # could throw, need to export 7575 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7576 SPILL(rPC) 7577 movl %eax,OUT_ARG1(%esp) 7578 movl %ecx,OUT_ARG0(%esp) 7579 call dvmResolveStaticField # eax<- resolved StaticField ptr 7580 UNSPILL(rPC) 7581 testl %eax,%eax 7582 jne .LOP_SPUT_BOOLEAN_finish # success, continue 7583 jmp common_exceptionThrown # no, handle exception 7584 7585/* continuation for OP_SPUT_BYTE */ 7586 7587 /* 7588 * Go resolve the field 7589 */ 7590.LOP_SPUT_BYTE_resolve: 7591 GET_GLUE(%ecx) 7592 movzwl 2(rPC),%eax # eax<- field ref BBBB 7593 movl offGlue_method(%ecx),%ecx # ecx<- current method 7594 EXPORT_PC() # could throw, need to export 7595 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7596 SPILL(rPC) 7597 movl %eax,OUT_ARG1(%esp) 7598 movl %ecx,OUT_ARG0(%esp) 7599 call dvmResolveStaticField # eax<- resolved StaticField ptr 7600 UNSPILL(rPC) 7601 testl %eax,%eax 7602 jne .LOP_SPUT_BYTE_finish # success, continue 7603 jmp common_exceptionThrown # no, handle exception 7604 7605/* continuation for OP_SPUT_CHAR */ 7606 7607 /* 7608 * Go resolve the field 7609 */ 7610.LOP_SPUT_CHAR_resolve: 7611 GET_GLUE(%ecx) 7612 movzwl 2(rPC),%eax # eax<- field ref BBBB 7613 movl offGlue_method(%ecx),%ecx # ecx<- current method 7614 EXPORT_PC() # could throw, need to export 7615 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7616 SPILL(rPC) 7617 movl %eax,OUT_ARG1(%esp) 7618 movl %ecx,OUT_ARG0(%esp) 7619 call dvmResolveStaticField # eax<- resolved StaticField ptr 7620 UNSPILL(rPC) 7621 testl %eax,%eax 7622 jne .LOP_SPUT_CHAR_finish # success, continue 7623 jmp common_exceptionThrown # no, handle exception 7624 7625/* continuation for OP_SPUT_SHORT */ 7626 7627 /* 7628 * Go resolve the field 7629 */ 7630.LOP_SPUT_SHORT_resolve: 7631 GET_GLUE(%ecx) 7632 movzwl 2(rPC),%eax # eax<- field ref BBBB 7633 movl offGlue_method(%ecx),%ecx # ecx<- current method 7634 EXPORT_PC() # could throw, need to export 7635 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7636 SPILL(rPC) 7637 movl %eax,OUT_ARG1(%esp) 7638 movl %ecx,OUT_ARG0(%esp) 7639 call dvmResolveStaticField # eax<- resolved StaticField ptr 7640 UNSPILL(rPC) 7641 testl %eax,%eax 7642 jne .LOP_SPUT_SHORT_finish # success, continue 7643 jmp common_exceptionThrown # no, handle exception 7644 7645/* continuation for OP_INVOKE_VIRTUAL */ 7646 7647 7648.LOP_INVOKE_VIRTUAL_more: 7649 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz 7650 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 7651 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags 7652 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7653 UNSPILL(rPC) 7654 testl %eax,%eax # got null? 7655 jne .LOP_INVOKE_VIRTUAL_continue # no, continue 7656 jmp common_exceptionThrown # yes, handle exception 7657 7658 /* At this point: 7659 * eax = resolved base method 7660 * ecx = scratch 7661 */ 7662.LOP_INVOKE_VIRTUAL_continue: 7663 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC 7664 .if (!0) 7665 andl $0xf,%ecx # ecx<- D (or stays CCCC) 7666 .endif 7667 GET_VREG(%ecx,%ecx) # ecx<- "this" 7668 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex 7669 testl %ecx,%ecx # null this? 7670 je common_errNullObject # go if so 7671 movl offObject_clazz(%ecx),%ecx # ecx<- thisPtr->clazz 7672 movl offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable 7673 movl (%ecx,%eax,4),%eax # eax<- vtable[methodIndex] 7674 jmp common_invokeMethodNoRange 7675 7676/* continuation for OP_INVOKE_SUPER */ 7677 7678 /* 7679 * At this point: 7680 * ecx = resolved base method [r0] 7681 * eax = method->clazz [r9] 7682 */ 7683.LOP_INVOKE_SUPER_continue: 7684 movl offClassObject_super(%eax),%eax # eax<- method->clazz->super 7685 movzwl offMethod_methodIndex(%ecx),%ecx # ecx<- baseMthod->methodIndex 7686 cmpl offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount) 7687 jae .LOP_INVOKE_SUPER_nsm # method not present in superclass 7688 movl offClassObject_vtable(%eax),%eax # eax<- ...clazz->super->vtable 7689 movl (%eax,%ecx,4),%eax # eax<- vtable[methodIndex] 7690 jmp common_invokeMethodNoRange 7691 7692 7693 /* At this point: 7694 * ecx = null (needs to be resolved base method) 7695 * eax = method->clazz 7696 */ 7697.LOP_INVOKE_SUPER_resolve: 7698 SPILL_TMP(%eax) # method->clazz 7699 movl %eax,OUT_ARG0(%esp) # arg0<- method->clazz 7700 movzwl 2(rPC),%ecx # ecx<- BBBB 7701 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- resolver method type 7702 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 7703 SPILL(rPC) 7704 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7705 UNSPILL(rPC) 7706 testl %eax,%eax # got null? 7707 movl %eax,%ecx # ecx<- resolved base method 7708 UNSPILL_TMP(%eax) # restore method->clazz 7709 jne .LOP_INVOKE_SUPER_continue # good to go - continue 7710 jmp common_exceptionThrown # handle exception 7711 7712 /* 7713 * Throw a NoSuchMethodError with the method name as the message. 7714 * ecx = resolved base method 7715 */ 7716.LOP_INVOKE_SUPER_nsm: 7717 movl offMethod_name(%ecx),%eax 7718 mov %eax,OUT_ARG1(%esp) 7719 jmp common_errNoSuchMethod 7720 7721/* continuation for OP_INVOKE_DIRECT */ 7722 7723 /* 7724 * On entry: 7725 * TMP_SPILL <- "this" register 7726 * Things a bit ugly on this path, but it's the less 7727 * frequent one. We'll have to do some reloading. 7728 */ 7729.LOP_INVOKE_DIRECT_resolve: 7730 SPILL_TMP(%ecx) 7731 GET_GLUE(%ecx) 7732 UNSPILL(rPC) 7733 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 7734 movzwl 2(rPC),%eax # reference (BBBB or CCCC) 7735 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7736 movl $METHOD_DIRECT,OUT_ARG2(%esp) 7737 movl %eax,OUT_ARG1(%esp) 7738 movl %ecx,OUT_ARG0(%esp) 7739 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7740 UNSPILL_TMP(%ecx) 7741 testl %eax,%eax 7742 jne .LOP_INVOKE_DIRECT_finish 7743 UNSPILL(rPC) 7744 jmp common_exceptionThrown 7745 7746/* continuation for OP_INVOKE_STATIC */ 7747 7748.LOP_INVOKE_STATIC_continue: 7749 movl $METHOD_STATIC,%eax 7750 movl %eax,OUT_ARG2(%esp) # arg2<- flags 7751 SPILL(rPC) 7752 call dvmResolveMethod # call(clazz,ref,flags) 7753 UNSPILL(rPC) 7754 testl %eax,%eax # got null? 7755 jne common_invokeMethodNoRange 7756 jmp common_exceptionThrown 7757 7758/* continuation for OP_INVOKE_INTERFACE */ 7759 7760.LOP_INVOKE_INTERFACE_continue: 7761 call dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex) 7762 UNSPILL(rPC) 7763 testl %eax,%eax 7764 je common_exceptionThrown 7765 jmp common_invokeMethodNoRange 7766 7767/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 7768 7769 7770.LOP_INVOKE_VIRTUAL_RANGE_more: 7771 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz 7772 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 7773 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags 7774 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7775 UNSPILL(rPC) 7776 testl %eax,%eax # got null? 7777 jne .LOP_INVOKE_VIRTUAL_RANGE_continue # no, continue 7778 jmp common_exceptionThrown # yes, handle exception 7779 7780 /* At this point: 7781 * eax = resolved base method 7782 * ecx = scratch 7783 */ 7784.LOP_INVOKE_VIRTUAL_RANGE_continue: 7785 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC 7786 .if (!1) 7787 andl $0xf,%ecx # ecx<- D (or stays CCCC) 7788 .endif 7789 GET_VREG(%ecx,%ecx) # ecx<- "this" 7790 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex 7791 testl %ecx,%ecx # null this? 7792 je common_errNullObject # go if so 7793 movl offObject_clazz(%ecx),%ecx # ecx<- thisPtr->clazz 7794 movl offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable 7795 movl (%ecx,%eax,4),%eax # eax<- vtable[methodIndex] 7796 jmp common_invokeMethodRange 7797 7798/* continuation for OP_INVOKE_SUPER_RANGE */ 7799 7800 /* 7801 * At this point: 7802 * ecx = resolved base method [r0] 7803 * eax = method->clazz [r9] 7804 */ 7805.LOP_INVOKE_SUPER_RANGE_continue: 7806 movl offClassObject_super(%eax),%eax # eax<- method->clazz->super 7807 movzwl offMethod_methodIndex(%ecx),%ecx # ecx<- baseMthod->methodIndex 7808 cmpl offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount) 7809 jae .LOP_INVOKE_SUPER_RANGE_nsm # method not present in superclass 7810 movl offClassObject_vtable(%eax),%eax # eax<- ...clazz->super->vtable 7811 movl (%eax,%ecx,4),%eax # eax<- vtable[methodIndex] 7812 jmp common_invokeMethodRange 7813 7814 7815 /* At this point: 7816 * ecx = null (needs to be resolved base method) 7817 * eax = method->clazz 7818 */ 7819.LOP_INVOKE_SUPER_RANGE_resolve: 7820 SPILL_TMP(%eax) # method->clazz 7821 movl %eax,OUT_ARG0(%esp) # arg0<- method->clazz 7822 movzwl 2(rPC),%ecx # ecx<- BBBB 7823 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- resolver method type 7824 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 7825 SPILL(rPC) 7826 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7827 UNSPILL(rPC) 7828 testl %eax,%eax # got null? 7829 movl %eax,%ecx # ecx<- resolved base method 7830 UNSPILL_TMP(%eax) # restore method->clazz 7831 jne .LOP_INVOKE_SUPER_RANGE_continue # good to go - continue 7832 jmp common_exceptionThrown # handle exception 7833 7834 /* 7835 * Throw a NoSuchMethodError with the method name as the message. 7836 * ecx = resolved base method 7837 */ 7838.LOP_INVOKE_SUPER_RANGE_nsm: 7839 movl offMethod_name(%ecx),%eax 7840 mov %eax,OUT_ARG1(%esp) 7841 jmp common_errNoSuchMethod 7842 7843/* continuation for OP_INVOKE_DIRECT_RANGE */ 7844 7845 /* 7846 * On entry: 7847 * TMP_SPILL <- "this" register 7848 * Things a bit ugly on this path, but it's the less 7849 * frequent one. We'll have to do some reloading. 7850 */ 7851.LOP_INVOKE_DIRECT_RANGE_resolve: 7852 SPILL_TMP(%ecx) 7853 GET_GLUE(%ecx) 7854 UNSPILL(rPC) 7855 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 7856 movzwl 2(rPC),%eax # reference (BBBB or CCCC) 7857 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7858 movl $METHOD_DIRECT,OUT_ARG2(%esp) 7859 movl %eax,OUT_ARG1(%esp) 7860 movl %ecx,OUT_ARG0(%esp) 7861 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7862 UNSPILL_TMP(%ecx) 7863 testl %eax,%eax 7864 jne .LOP_INVOKE_DIRECT_RANGE_finish 7865 UNSPILL(rPC) 7866 jmp common_exceptionThrown 7867 7868/* continuation for OP_INVOKE_STATIC_RANGE */ 7869 7870.LOP_INVOKE_STATIC_RANGE_continue: 7871 movl $METHOD_STATIC,%eax 7872 movl %eax,OUT_ARG2(%esp) # arg2<- flags 7873 SPILL(rPC) 7874 call dvmResolveMethod # call(clazz,ref,flags) 7875 UNSPILL(rPC) 7876 testl %eax,%eax # got null? 7877 jne common_invokeMethodRange 7878 jmp common_exceptionThrown 7879 7880/* continuation for OP_INVOKE_INTERFACE_RANGE */ 7881 7882.LOP_INVOKE_INTERFACE_RANGE_continue: 7883 call dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex) 7884 UNSPILL(rPC) 7885 testl %eax,%eax 7886 je common_exceptionThrown 7887 jmp common_invokeMethodRange 7888 7889/* continuation for OP_FLOAT_TO_INT */ 7890 7891 7892.LOP_FLOAT_TO_INT_continue: 7893 .if 0 7894 movl $0x80000000,%eax 7895 xorl 4(rFP,%ecx,4),%eax 7896 orl (rFP,%ecx,4),%eax 7897 .else 7898 cmpl $0x80000000,(rFP,%ecx,4) 7899 .endif 7900 je .LOP_FLOAT_TO_INT_special_case # fix up result 7901 7902.LOP_FLOAT_TO_INT_finish: 7903 ADVANCE_PC(1) 7904 GOTO_NEXT 7905 7906.LOP_FLOAT_TO_INT_special_case: 7907 fnstsw %ax 7908 sahf 7909 jp .LOP_FLOAT_TO_INT_isNaN 7910 adcl $-1,(rFP,%ecx,4) 7911 .if 0 7912 adcl $-1,4(rFP,%ecx,4) 7913 .endif 7914 jmp .LOP_FLOAT_TO_INT_finish 7915.LOP_FLOAT_TO_INT_isNaN: 7916 movl $0,(rFP,%ecx,4) 7917 .if 0 7918 movl $0,4(rFP,%ecx,4) 7919 .endif 7920 jmp .LOP_FLOAT_TO_INT_finish 7921 7922/* continuation for OP_FLOAT_TO_LONG */ 7923 7924 7925.LOP_FLOAT_TO_LONG_continue: 7926 .if 1 7927 movl $0x80000000,%eax 7928 xorl 4(rFP,%ecx,4),%eax 7929 orl (rFP,%ecx,4),%eax 7930 .else 7931 cmpl $0x80000000,(rFP,%ecx,4) 7932 .endif 7933 je .LOP_FLOAT_TO_LONG_special_case # fix up result 7934 7935.LOP_FLOAT_TO_LONG_finish: 7936 ADVANCE_PC(1) 7937 GOTO_NEXT 7938 7939.LOP_FLOAT_TO_LONG_special_case: 7940 fnstsw %ax 7941 sahf 7942 jp .LOP_FLOAT_TO_LONG_isNaN 7943 adcl $-1,(rFP,%ecx,4) 7944 .if 1 7945 adcl $-1,4(rFP,%ecx,4) 7946 .endif 7947 jmp .LOP_FLOAT_TO_LONG_finish 7948.LOP_FLOAT_TO_LONG_isNaN: 7949 movl $0,(rFP,%ecx,4) 7950 .if 1 7951 movl $0,4(rFP,%ecx,4) 7952 .endif 7953 jmp .LOP_FLOAT_TO_LONG_finish 7954 7955/* continuation for OP_DOUBLE_TO_INT */ 7956 7957 7958.LOP_DOUBLE_TO_INT_continue: 7959 .if 0 7960 movl $0x80000000,%eax 7961 xorl 4(rFP,%ecx,4),%eax 7962 orl (rFP,%ecx,4),%eax 7963 .else 7964 cmpl $0x80000000,(rFP,%ecx,4) 7965 .endif 7966 je .LOP_DOUBLE_TO_INT_special_case # fix up result 7967 7968.LOP_DOUBLE_TO_INT_finish: 7969 ADVANCE_PC(1) 7970 GOTO_NEXT 7971 7972.LOP_DOUBLE_TO_INT_special_case: 7973 fnstsw %ax 7974 sahf 7975 jp .LOP_DOUBLE_TO_INT_isNaN 7976 adcl $-1,(rFP,%ecx,4) 7977 .if 0 7978 adcl $-1,4(rFP,%ecx,4) 7979 .endif 7980 jmp .LOP_DOUBLE_TO_INT_finish 7981.LOP_DOUBLE_TO_INT_isNaN: 7982 movl $0,(rFP,%ecx,4) 7983 .if 0 7984 movl $0,4(rFP,%ecx,4) 7985 .endif 7986 jmp .LOP_DOUBLE_TO_INT_finish 7987 7988/* continuation for OP_DOUBLE_TO_LONG */ 7989 7990 7991.LOP_DOUBLE_TO_LONG_continue: 7992 .if 1 7993 movl $0x80000000,%eax 7994 xorl 4(rFP,%ecx,4),%eax 7995 orl (rFP,%ecx,4),%eax 7996 .else 7997 cmpl $0x80000000,(rFP,%ecx,4) 7998 .endif 7999 je .LOP_DOUBLE_TO_LONG_special_case # fix up result 8000 8001.LOP_DOUBLE_TO_LONG_finish: 8002 ADVANCE_PC(1) 8003 GOTO_NEXT 8004 8005.LOP_DOUBLE_TO_LONG_special_case: 8006 fnstsw %ax 8007 sahf 8008 jp .LOP_DOUBLE_TO_LONG_isNaN 8009 adcl $-1,(rFP,%ecx,4) 8010 .if 1 8011 adcl $-1,4(rFP,%ecx,4) 8012 .endif 8013 jmp .LOP_DOUBLE_TO_LONG_finish 8014.LOP_DOUBLE_TO_LONG_isNaN: 8015 movl $0,(rFP,%ecx,4) 8016 .if 1 8017 movl $0,4(rFP,%ecx,4) 8018 .endif 8019 jmp .LOP_DOUBLE_TO_LONG_finish 8020 8021/* continuation for OP_DIV_INT */ 8022.LOP_DIV_INT_continue_div: 8023 cltd 8024 idivl %ecx 8025.LOP_DIV_INT_finish_div: 8026 movzbl rINST_HI,%ecx # ecl<- AA 8027 SET_VREG(%eax,%ecx) 8028 UNSPILL(rPC) 8029 FETCH_INST_WORD(2) 8030 ADVANCE_PC(2) 8031 GOTO_NEXT 8032 8033/* continuation for OP_REM_INT */ 8034.LOP_REM_INT_continue_div: 8035 cltd 8036 idivl %ecx 8037.LOP_REM_INT_finish_div: 8038 movzbl rINST_HI,%ecx # ecl<- AA 8039 SET_VREG(%edx,%ecx) 8040 UNSPILL(rPC) 8041 FETCH_INST_WORD(2) 8042 ADVANCE_PC(2) 8043 GOTO_NEXT 8044 8045/* continuation for OP_MUL_LONG */ 8046 8047.LOP_MUL_LONG_continue: 8048 leal (%ecx,%edx),%edx # full result now in %edx:%eax 8049 movzbl rINST_HI,%ecx # ecx<- A 8050 movl %edx,4(rFP,%ecx,4) # v[B+1]<- %edx 8051 UNSPILL(rPC) # restore rPC/%edx 8052 FETCH_INST_WORD(2) 8053 UNSPILL(rIBASE) 8054 movl %eax,(rFP,%ecx,4) # v[B]<- %eax 8055 ADVANCE_PC(2) 8056 GOTO_NEXT 8057 8058/* continuation for OP_DIV_LONG */ 8059 8060.LOP_DIV_LONG_continue: 8061 call __divdi3 8062.LOP_DIV_LONG_finish: 8063 movzbl rINST_HI,%ecx 8064 SET_VREG_WORD(rPC,%ecx,1) 8065 UNSPILL(rPC) 8066 SET_VREG_WORD(%eax,%ecx,0) 8067 FETCH_INST_WORD(2) 8068 ADVANCE_PC(2) 8069 GOTO_NEXT 8070 8071.LOP_DIV_LONG_check_zero: 8072 testl rPC,rPC 8073 jne .LOP_DIV_LONG_notSpecial 8074 UNSPILL(rPC) 8075 jmp common_errDivideByZero 8076.LOP_DIV_LONG_check_neg1: 8077 testl rPC,%eax 8078 jne .LOP_DIV_LONG_notSpecial 8079 GET_VREG_WORD(rPC,%ecx,0) 8080 GET_VREG_WORD(%ecx,%ecx,1) 8081 testl rPC,rPC 8082 jne .LOP_DIV_LONG_notSpecial1 8083 cmpl $0x80000000,%ecx 8084 jne .LOP_DIV_LONG_notSpecial1 8085 /* minint / -1, return minint on div, 0 on rem */ 8086 xorl %eax,%eax 8087 movl $0x80000000,%edx 8088 jmp .LOP_DIV_LONG_finish 8089 8090/* continuation for OP_REM_LONG */ 8091 8092.LOP_REM_LONG_continue: 8093 call __moddi3 8094.LOP_REM_LONG_finish: 8095 movzbl rINST_HI,%ecx 8096 SET_VREG_WORD(rPC,%ecx,1) 8097 UNSPILL(rPC) 8098 SET_VREG_WORD(%eax,%ecx,0) 8099 FETCH_INST_WORD(2) 8100 ADVANCE_PC(2) 8101 GOTO_NEXT 8102 8103.LOP_REM_LONG_check_zero: 8104 testl rPC,rPC 8105 jne .LOP_REM_LONG_notSpecial 8106 UNSPILL(rPC) 8107 jmp common_errDivideByZero 8108.LOP_REM_LONG_check_neg1: 8109 testl rPC,%eax 8110 jne .LOP_REM_LONG_notSpecial 8111 GET_VREG_WORD(rPC,%ecx,0) 8112 GET_VREG_WORD(%ecx,%ecx,1) 8113 testl rPC,rPC 8114 jne .LOP_REM_LONG_notSpecial1 8115 cmpl $0x80000000,%ecx 8116 jne .LOP_REM_LONG_notSpecial1 8117 /* minint / -1, return minint on div, 0 on rem */ 8118 xorl %eax,%eax 8119 movl $0,%edx 8120 jmp .LOP_REM_LONG_finish 8121 8122/* continuation for OP_SHL_LONG */ 8123 8124.LOP_SHL_LONG_finish: 8125 SET_VREG_WORD(%eax,%ecx,0) # v[AA+0]<- %eax 8126 ADVANCE_PC(2) 8127 GOTO_NEXT 8128 8129/* continuation for OP_SHR_LONG */ 8130 8131 8132.LOP_SHR_LONG_finish: 8133 SET_VREG_WORD(%eax,%ecx,0) # v[AA+0]<- eax 8134 ADVANCE_PC(2) 8135 GOTO_NEXT 8136 8137/* continuation for OP_USHR_LONG */ 8138 8139 8140.LOP_USHR_LONG_finish: 8141 SET_VREG_WORD(%eax,%ecx,0) # v[BB+0]<- eax 8142 FETCH_INST_WORD(2) 8143 ADVANCE_PC(2) 8144 GOTO_NEXT 8145 8146/* continuation for OP_DIV_INT_2ADDR */ 8147.LOP_DIV_INT_2ADDR_continue_div2addr: 8148 cltd 8149 idivl %ecx 8150.LOP_DIV_INT_2ADDR_finish_div2addr: 8151 SET_VREG(%eax,rINST_FULL) 8152 UNSPILL(rPC) 8153 FETCH_INST_WORD(1) 8154 ADVANCE_PC(1) 8155 GOTO_NEXT 8156 8157/* continuation for OP_REM_INT_2ADDR */ 8158.LOP_REM_INT_2ADDR_continue_div2addr: 8159 cltd 8160 idivl %ecx 8161.LOP_REM_INT_2ADDR_finish_div2addr: 8162 SET_VREG(%edx,rINST_FULL) 8163 UNSPILL(rPC) 8164 FETCH_INST_WORD(1) 8165 ADVANCE_PC(1) 8166 GOTO_NEXT 8167 8168/* continuation for OP_MUL_LONG_2ADDR */ 8169 8170.LOP_MUL_LONG_2ADDR_continue: 8171 leal (%ecx,%edx),%edx # full result now in %edx:%eax 8172 movl %edx,4(rIBASE) # v[A+1]<- %edx 8173 UNSPILL(rPC) # restore rPC/%edx 8174 FETCH_INST_WORD(1) 8175 movl %eax,(rIBASE) # v[A]<- %eax 8176 UNSPILL(rFP) 8177 UNSPILL(rIBASE) 8178 ADVANCE_PC(1) 8179 GOTO_NEXT 8180 8181/* continuation for OP_DIV_LONG_2ADDR */ 8182 8183.LOP_DIV_LONG_2ADDR_continue: 8184 movl %eax,OUT_ARG3(%esp) 8185 movl rPC,OUT_ARG0(%esp) 8186 movl %ecx,OUT_ARG1(%esp) 8187 call __divdi3 8188.LOP_DIV_LONG_2ADDR_finish: 8189 movl rINST_FULL,%ecx 8190 SET_VREG_WORD(rPC,%ecx,1) 8191 UNSPILL(rPC) 8192 SET_VREG_WORD(%eax,%ecx,0) 8193 FETCH_INST_WORD(1) 8194 ADVANCE_PC(1) 8195 GOTO_NEXT 8196 8197.LOP_DIV_LONG_2ADDR_check_zero: 8198 testl rPC,rPC 8199 jne .LOP_DIV_LONG_2ADDR_notSpecial 8200 UNSPILL(rPC) 8201 jmp common_errDivideByZero 8202.LOP_DIV_LONG_2ADDR_check_neg1: 8203 testl rPC,%eax 8204 jne .LOP_DIV_LONG_2ADDR_notSpecial 8205 GET_VREG_WORD(rPC,rINST_FULL,0) 8206 GET_VREG_WORD(%ecx,rINST_FULL,1) 8207 testl rPC,rPC 8208 jne .LOP_DIV_LONG_2ADDR_notSpecial1 8209 cmpl $0x80000000,%ecx 8210 jne .LOP_DIV_LONG_2ADDR_notSpecial1 8211 /* minint / -1, return minint on div, 0 on rem */ 8212 xorl %eax,%eax 8213 movl $0x80000000,%edx 8214 jmp .LOP_DIV_LONG_2ADDR_finish 8215 8216/* continuation for OP_REM_LONG_2ADDR */ 8217 8218.LOP_REM_LONG_2ADDR_continue: 8219 movl %eax,OUT_ARG3(%esp) 8220 movl rPC,OUT_ARG0(%esp) 8221 movl %ecx,OUT_ARG1(%esp) 8222 call __moddi3 8223.LOP_REM_LONG_2ADDR_finish: 8224 movl rINST_FULL,%ecx 8225 SET_VREG_WORD(rPC,%ecx,1) 8226 UNSPILL(rPC) 8227 SET_VREG_WORD(%eax,%ecx,0) 8228 FETCH_INST_WORD(1) 8229 ADVANCE_PC(1) 8230 GOTO_NEXT 8231 8232.LOP_REM_LONG_2ADDR_check_zero: 8233 testl rPC,rPC 8234 jne .LOP_REM_LONG_2ADDR_notSpecial 8235 UNSPILL(rPC) 8236 jmp common_errDivideByZero 8237.LOP_REM_LONG_2ADDR_check_neg1: 8238 testl rPC,%eax 8239 jne .LOP_REM_LONG_2ADDR_notSpecial 8240 GET_VREG_WORD(rPC,rINST_FULL,0) 8241 GET_VREG_WORD(%ecx,rINST_FULL,1) 8242 testl rPC,rPC 8243 jne .LOP_REM_LONG_2ADDR_notSpecial1 8244 cmpl $0x80000000,%ecx 8245 jne .LOP_REM_LONG_2ADDR_notSpecial1 8246 /* minint / -1, return minint on div, 0 on rem */ 8247 xorl %eax,%eax 8248 movl $0,%edx 8249 jmp .LOP_REM_LONG_2ADDR_finish 8250 8251/* continuation for OP_SHL_LONG_2ADDR */ 8252 8253 8254.LOP_SHL_LONG_2ADDR_finish: 8255 SET_VREG_WORD(%eax,rINST_FULL,0) # v[AA+0]<- eax 8256 FETCH_INST_WORD(1) 8257 ADVANCE_PC(1) 8258 GOTO_NEXT 8259 8260/* continuation for OP_SHR_LONG_2ADDR */ 8261 8262 8263.LOP_SHR_LONG_2ADDR_finish: 8264 SET_VREG_WORD(%eax,rINST_FULL,0) # v[AA+0]<- eax 8265 FETCH_INST_WORD(1) 8266 ADVANCE_PC(1) 8267 GOTO_NEXT 8268 8269/* continuation for OP_USHR_LONG_2ADDR */ 8270 8271 8272.LOP_USHR_LONG_2ADDR_finish: 8273 SET_VREG_WORD(%eax,rINST_FULL,0) # v[AA+0]<- eax 8274 FETCH_INST_WORD(1) 8275 ADVANCE_PC(1) 8276 GOTO_NEXT 8277 8278/* continuation for OP_DIV_INT_LIT16 */ 8279.LOP_DIV_INT_LIT16_continue_div: 8280 cltd 8281 idivl %ecx 8282.LOP_DIV_INT_LIT16_finish_div: 8283 SET_VREG(%eax,rINST_FULL) 8284 UNSPILL(rPC) 8285 FETCH_INST_WORD(2) 8286 ADVANCE_PC(2) 8287 GOTO_NEXT 8288 8289/* continuation for OP_REM_INT_LIT16 */ 8290.LOP_REM_INT_LIT16_continue_div: 8291 cltd 8292 idivl %ecx 8293.LOP_REM_INT_LIT16_finish_div: 8294 SET_VREG(%edx,rINST_FULL) 8295 UNSPILL(rPC) 8296 FETCH_INST_WORD(2) 8297 ADVANCE_PC(2) 8298 GOTO_NEXT 8299 8300/* continuation for OP_DIV_INT_LIT8 */ 8301.LOP_DIV_INT_LIT8_continue_div: 8302 cltd 8303 idivl %ecx 8304.LOP_DIV_INT_LIT8_finish_div: 8305 SET_VREG(%eax,rINST_FULL) 8306 UNSPILL(rPC) 8307 FETCH_INST_WORD(2) 8308 ADVANCE_PC(2) 8309 GOTO_NEXT 8310 8311/* continuation for OP_REM_INT_LIT8 */ 8312.LOP_REM_INT_LIT8_continue_div: 8313 cltd 8314 idivl %ecx 8315.LOP_REM_INT_LIT8_finish_div: 8316 SET_VREG(%edx,rINST_FULL) 8317 UNSPILL(rPC) 8318 FETCH_INST_WORD(2) 8319 ADVANCE_PC(2) 8320 GOTO_NEXT 8321 8322/* continuation for OP_EXECUTE_INLINE */ 8323 8324.LOP_EXECUTE_INLINE_continue: 8325 /* 8326 * Extract args, call function. 8327 * ecx = #of args (0-4) 8328 * eax = call index 8329 * @esp = return addr 8330 * esp is -4 from normal 8331 * 8332 * Go ahead and load all 4 args, even if not used. 8333 */ 8334 movzwl 4(rPC),rPC 8335 8336 movl $0xf,%ecx 8337 andl rPC,%ecx 8338 GET_VREG(%ecx,%ecx) 8339 sarl $4,rPC 8340 movl %ecx,4+OUT_ARG0(%esp) 8341 8342 movl $0xf,%ecx 8343 andl rPC,%ecx 8344 GET_VREG(%ecx,%ecx) 8345 sarl $4,rPC 8346 movl %ecx,4+OUT_ARG1(%esp) 8347 8348 movl $0xf,%ecx 8349 andl rPC,%ecx 8350 GET_VREG(%ecx,%ecx) 8351 sarl $4,rPC 8352 movl %ecx,4+OUT_ARG2(%esp) 8353 8354 movl $0xf,%ecx 8355 andl rPC,%ecx 8356 GET_VREG(%ecx,%ecx) 8357 sarl $4,rPC 8358 movl %ecx,4+OUT_ARG3(%esp) 8359 8360 sall $4,%eax # index *= sizeof(table entry) 8361 jmp *gDvmInlineOpsTable(%eax) 8362 # will return to caller of .LOP_EXECUTE_INLINE_continue 8363 8364 .size dvmAsmSisterStart, .-dvmAsmSisterStart 8365 .global dvmAsmSisterEnd 8366dvmAsmSisterEnd: 8367 8368/* File: x86/entry.S */ 8369/* 8370 * Copyright (C) 2008 The Android Open Source Project 8371 * 8372 * Licensed under the Apache License, Version 2.0 (the "License"); 8373 * you may not use this file except in compliance with the License. 8374 * You may obtain a copy of the License at 8375 * 8376 * http://www.apache.org/licenses/LICENSE-2.0 8377 * 8378 * Unless required by applicable law or agreed to in writing, software 8379 * distributed under the License is distributed on an "AS IS" BASIS, 8380 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8381 * See the License for the specific language governing permissions and 8382 * limitations under the License. 8383 */ 8384 8385 8386 .text 8387 .global dvmMterpStdRun 8388 .type dvmMterpStdRun, %function 8389/* 8390 * bool dvmMterpStdRun(MterpGlue* glue) 8391 * 8392 * Interpreter entry point. Returns changeInterp. 8393 * 8394 */ 8395dvmMterpStdRun: 8396 push %ebp 8397 movl %esp,%ebp 8398 push %edi 8399 push %esi 8400 push %ebx 8401 8402/* at this point, stack is misaligned by 1 word 8403 We're allocating spill space for 6 words, plus 8404 outgoing argument (5 words) and local variables 8405 (4 words) - 15 words or 60 bytes total. See 8406 diagram in header.S 8407*/ 8408 subl $60,%esp 8409 8410/* Set up "named" registers */ 8411 movl IN_ARG0(%ebp),%ecx 8412 movl %ecx,rGLUE_SPILL(%ebp) 8413 LOAD_PC_FROM_GLUE(%ecx) 8414 LOAD_FP_FROM_GLUE(%ecx) 8415 movl $dvmAsmInstructionStart,rIBASE 8416 8417/* Remember %esp for future "longjmp" */ 8418 movl %esp,offGlue_bailPtr(%ecx) 8419 8420/* How to start? */ 8421 movb offGlue_entryPoint(%ecx),%al 8422 8423/* Normal start? */ 8424 cmpb $kInterpEntryInstr,%al 8425 jne .Lnot_instr 8426 8427 /* Normal case: start executing the instruction at rPC */ 8428 FETCH_INST() 8429 GOTO_NEXT 8430 8431.Lnot_instr: 8432 /* Reset to normal case */ 8433 movb $kInterpEntryInstr,offGlue_entryPoint(%ecx) 8434 cmpb $kInterpEntryReturn,%al 8435 je common_returnFromMethod 8436 cmpb $kInterpEntryThrow,%al 8437 je common_exceptionThrown 8438 movzx %al,%eax 8439 movl %eax,OUT_ARG1(%esp) 8440 movl $.LstrBadEntryPoint,OUT_ARG0(%esp) 8441 call printf 8442 call dvmAbort 8443 /* Not reached */ 8444 8445 8446 .global dvmMterpStdBail 8447 .type dvmMterpStdBail, %function 8448/* 8449 * void dvmMterpStdBail(MterpGlue* glue, bool changeInterp) 8450 * 8451 * Restore the stack pointer and PC from the save point established on entry. 8452 * This is essentially the same as a longjmp, but should be cheaper. The 8453 * last instruction causes us to return to whoever called dvmMterpStdRun. 8454 * 8455 * We're not going to build a standard frame here, so the arg accesses will 8456 * look a little strange. 8457 * 8458 * On entry: 8459 * esp+4 (arg0) MterpGlue* glue 8460 * esp+8 (arg1) bool changeInterp 8461 */ 8462dvmMterpStdBail: 8463 movl 4(%esp),%ecx # grab glue 8464 movl 8(%esp),%eax # changeInterp to return reg 8465 movl offGlue_bailPtr(%ecx),%esp # Stack back to normal 8466 addl $60,%esp # Strip dvmMterpStdRun's frame 8467 pop %ebx 8468 pop %esi 8469 pop %edi 8470 pop %ebp 8471 ret # return to dvmMterpStdRun's caller 8472 8473 8474/* 8475 * Strings 8476 */ 8477 .section .rodata 8478.LstrBadEntryPoint: 8479 .asciz "Bad entry point %d\n" 8480 8481/* File: x86/footer.S */ 8482/* 8483 * Copyright (C) 2008 The Android Open Source Project 8484 * 8485 * Licensed under the Apache License, Version 2.0 (the "License"); 8486 * you may not use this file except in compliance with the License. 8487 * You may obtain a copy of the License at 8488 * 8489 * http://www.apache.org/licenses/LICENSE-2.0 8490 * 8491 * Unless required by applicable law or agreed to in writing, software 8492 * distributed under the License is distributed on an "AS IS" BASIS, 8493 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8494 * See the License for the specific language governing permissions and 8495 * limitations under the License. 8496 */ 8497/* 8498 * Common subroutines and data. 8499 */ 8500 8501/* 8502 * Common code when a backwards branch is taken 8503 * 8504 * On entry: 8505 * ebx (a.k.a. rINST_FULL) -> PC adjustment in 16-bit words 8506 */ 8507common_backwardBranch: 8508 GET_GLUE(%ecx) 8509 call common_periodicChecks # Note: expects rPC to be preserved 8510 ADVANCE_PC_INDEXED(rINST_FULL) 8511 FETCH_INST() 8512 GOTO_NEXT 8513 8514 8515 8516/* 8517 * Common code for method invocation with range. 8518 * 8519 * On entry: 8520 * eax = Method* methodToCall 8521 * rINST trashed, must reload 8522 */ 8523 8524common_invokeMethodRange: 8525.LinvokeNewRange: 8526 8527 /* 8528 * prepare to copy args to "outs" area of current frame 8529 */ 8530 8531 movzbl 1(rPC),rINST_FULL # rINST_FULL<- AA 8532 movzwl 4(rPC), %ecx # %ecx<- CCCC 8533 SPILL(rPC) 8534 SAVEAREA_FROM_FP(%edx,rFP) # %edx<- &StackSaveArea 8535 test rINST_FULL, rINST_FULL 8536 movl rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA 8537 jz .LinvokeArgsDone # no args; jump to args done 8538 8539 8540 /* 8541 * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, %edx=&outs (&stackSaveArea) 8542 * (very few methods have > 10 args; could unroll for common cases) 8543 */ 8544 8545 movl %ebx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- save %ebx 8546 lea (rFP, %ecx, 4), %ecx # %ecx<- &vCCCC 8547 shll $2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset 8548 subl LOCAL0_OFFSET(%ebp), %edx # %edx<- update &outs 8549 shrl $2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset 85501: 8551 movl (%ecx), %ebx # %ebx<- vCCCC 8552 lea 4(%ecx), %ecx # %ecx<- &vCCCC++ 8553 subl $1, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- LOCAL0_OFFSET-- 8554 movl %ebx, (%edx) # *outs<- vCCCC 8555 lea 4(%edx), %edx # outs++ 8556 jne 1b # loop if count (LOCAL0_OFFSET(%ebp)) not zero 8557 movl LOCAL1_OFFSET(%ebp), %ebx # %ebx<- restore %ebx 8558 jmp .LinvokeArgsDone # continue 8559 8560 /* 8561 * %eax is "Method* methodToCall", the method we're trying to call 8562 * prepare to copy args to "outs" area of current frame 8563 */ 8564 8565common_invokeMethodNoRange: 8566.LinvokeNewNoRange: 8567 movzbl 1(rPC),rINST_FULL # rINST_FULL<- BA 8568 SPILL(rPC) 8569 movl rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA 8570 shrl $4, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- B 8571 je .LinvokeArgsDone # no args; jump to args done 8572 movzwl 4(rPC), %ecx # %ecx<- GFED 8573 SAVEAREA_FROM_FP(%edx,rFP) # %edx<- &StackSaveArea 8574 8575 /* 8576 * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs 8577 */ 8578 8579.LinvokeNonRange: 8580 cmp $2, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 2 8581 movl %ecx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- GFED 8582 jl 1f # handle 1 arg 8583 je 2f # handle 2 args 8584 cmp $4, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 4 8585 jl 3f # handle 3 args 8586 je 4f # handle 4 args 85875: 8588 andl $15, rINST_FULL # rINST<- A 8589 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 8590 movl (rFP, rINST_FULL, 4), %ecx # %ecx<- vA 8591 movl %ecx, (%edx) # *outs<- vA 8592 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 85934: 8594 shr $12, %ecx # %ecx<- G 8595 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 8596 movl (rFP, %ecx, 4), %ecx # %ecx<- vG 8597 movl %ecx, (%edx) # *outs<- vG 8598 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 85993: 8600 and $0x0f00, %ecx # %ecx<- 0F00 8601 shr $8, %ecx # %ecx<- F 8602 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 8603 movl (rFP, %ecx, 4), %ecx # %ecx<- vF 8604 movl %ecx, (%edx) # *outs<- vF 8605 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 86062: 8607 and $0x00f0, %ecx # %ecx<- 00E0 8608 shr $4, %ecx # %ecx<- E 8609 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 8610 movl (rFP, %ecx, 4), %ecx # %ecx<- vE 8611 movl %ecx, (%edx) # *outs<- vE 8612 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 86131: 8614 and $0x000f, %ecx # %ecx<- 000D 8615 movl (rFP, %ecx, 4), %ecx # %ecx<- vD 8616 movl %ecx, -4(%edx) # *--outs<- vD 86170: 8618 8619 /* 8620 * %eax is "Method* methodToCall", the method we're trying to call 8621 * find space for the new stack frame, check for overflow 8622 */ 8623 8624.LinvokeArgsDone: 8625 movzwl offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize 8626 movzwl offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize 8627 movl %eax, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- methodToCall 8628 shl $2, %edx # %edx<- update offset 8629 SAVEAREA_FROM_FP(%eax,rFP) # %eax<- &StackSaveArea 8630 subl %edx, %eax # %eax<- newFP; (old savearea - regsSize) 8631 GET_GLUE(%edx) # %edx<- pMterpGlue 8632 movl %eax, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- &outs 8633 subl $sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP) 8634 movl offGlue_interpStackEnd(%edx), %edx # %edx<- glue->interpStackEnd 8635 movl %edx, LOCAL2_OFFSET(%ebp) # LOCAL2_OFFSET<- glue->interpStackEnd 8636 shl $2, %ecx # %ecx<- update offset for outsSize 8637 movl %eax, %edx # %edx<- newSaveArea 8638 sub %ecx, %eax # %eax<- bottom; (newSaveArea - outsSize) 8639 cmp LOCAL2_OFFSET(%ebp), %eax # compare interpStackEnd and bottom 8640 movl LOCAL0_OFFSET(%ebp), %eax # %eax<- restore methodToCall 8641 jl .LstackOverflow # handle frame overflow 8642 8643 /* 8644 * set up newSaveArea 8645 */ 8646 8647#ifdef EASY_GDB 8648 SAVEAREA_FROM_FP(%ecx,rFP) # %ecx<- &StackSaveArea 8649 movl %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs 8650#endif 8651 movl rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP 8652 movl rPC_SPILL(%ebp), %ecx 8653 movl %ecx, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC 8654 testl $ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call 8655 movl %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call 8656 jne .LinvokeNative # handle native call 8657 8658 /* 8659 * Update "glue" values for the new method 8660 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp 8661 */ 8662 8663 movl offMethod_clazz(%eax), %edx # %edx<- method->clazz 8664 GET_GLUE(%ecx) # %ecx<- pMterpGlue 8665 movl offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex 8666 movl %eax, offGlue_method(%ecx) # glue->method<- methodToCall 8667 movl %edx, offGlue_methodClassDex(%ecx) # glue->methodClassDex<- method->clazz->pDvmDex 8668 movl offMethod_insns(%eax), rPC # rPC<- methodToCall->insns 8669 movl offGlue_self(%ecx), %eax # %eax<- glue->self 8670 movl LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP 8671 movl rFP, offThread_curFrame(%eax) # glue->self->curFrame<- newFP 8672 FETCH_INST() 8673 GOTO_NEXT # jump to methodToCall->insns 8674 8675 /* 8676 * Prep for the native call 8677 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea 8678 */ 8679 8680.LinvokeNative: 8681 GET_GLUE(%ecx) # %ecx<- pMterpGlue 8682 movl %eax, OUT_ARG1(%esp) # push parameter methodToCall 8683 movl offGlue_self(%ecx), %ecx # %ecx<- glue->self 8684 movl offThread_jniLocal_topCookie(%ecx), %eax # %eax<- self->localRef->... 8685 movl %eax, offStackSaveArea_localRefCookie(%edx) # newSaveArea->localRefCookie<- top 8686 movl %edx, OUT_ARG4(%esp) # save newSaveArea 8687 movl LOCAL1_OFFSET(%ebp), %edx # %edx<- newFP 8688 movl %edx, offThread_curFrame(%ecx) # glue->self->curFrame<- newFP 8689 movl %ecx, OUT_ARG3(%esp) # save glue->self 8690 movl %ecx, OUT_ARG2(%esp) # push parameter glue->self 8691 GET_GLUE(%ecx) # %ecx<- pMterpGlue 8692 movl OUT_ARG1(%esp), %eax # %eax<- methodToCall 8693 lea offGlue_retval(%ecx), %ecx # %ecx<- &retval 8694 movl %ecx, OUT_ARG0(%esp) # push parameter pMterpGlue 8695 push %edx # push parameter newFP 8696 8697 call *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc 8698 lea 4(%esp), %esp 8699 movl OUT_ARG4(%esp), %ecx # %ecx<- newSaveArea 8700 movl OUT_ARG3(%esp), %eax # %eax<- glue->self 8701 movl offStackSaveArea_localRefCookie(%ecx), %edx # %edx<- old top 8702 cmp $0, offThread_exception(%eax) # check for exception 8703 movl rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP 8704 movl %edx, offThread_jniLocal_topCookie(%eax) # new top <- old top 8705 UNSPILL(rPC) 8706 jne common_exceptionThrown # handle exception 8707 FETCH_INST_WORD(3) 8708 ADVANCE_PC(3) 8709 GOTO_NEXT # jump to next instruction 8710 8711.LstackOverflow: # eax=methodToCall 8712 movl %eax, OUT_ARG1(%esp) # push parameter methodToCall 8713 GET_GLUE(%eax) # %eax<- pMterpGlue 8714 movl offGlue_self(%eax), %eax # %eax<- glue->self 8715 movl %eax, OUT_ARG0(%esp) # push parameter self 8716 call dvmHandleStackOverflow # call: (Thread* self, Method* meth) 8717 UNSPILL(rPC) # return: void 8718 jmp common_exceptionThrown # handle exception 8719 8720 8721/* 8722 * Common invoke code (old-style). 8723 * TUNING: Rewrite along lines of new armv5 code? 8724 * 8725 * On entry: 8726 * eax = Method* methodToCall 8727 * ecx = bool methodCallRange 8728 * rINST trashed, must reload 8729 */ 8730common_invokeOld: 8731 movl %ecx,OUT_ARG1(%esp) # arg1<- methodCallRange 8732 GET_GLUE(%ecx) 8733 movzwl (rPC),rINST_FULL # recover rINST 8734 movl %eax,OUT_ARG2(%esp) # arg2<- method 8735 movzwl 4(rPC),%eax # eax<- GFED or CCCC 8736 SAVE_PC_TO_GLUE(%ecx) 8737 SAVE_FP_TO_GLUE(%ecx) 8738 movzbl rINST_HI,rINST_FULL 8739 movl rINST_FULL,OUT_ARG3(%esp)# arg3<- AA 8740 movl %ecx,OUT_ARG0(%esp) # arg0<- GLUE 8741 movl %eax,OUT_ARG4(%esp) # arg4<- GFED/CCCC 8742 call dvmMterp_invokeMethod 8743 jmp common_resumeAfterGlueCall 8744 8745 8746/* 8747 * Do we need the thread to be suspended or have debugger/profiling activity? 8748 * 8749 * On entry: 8750 * ebx -> PC adjustment in 16-bit words (must be preserved) 8751 * ecx -> GLUE pointer 8752 * 8753 * Note: A call will normally kill %eax, rPC/%edx and %ecx. To 8754 * streamline the normal case, this routine will preserve rPC and 8755 * %ecx in addition to the normal caller save regs. The save/restore 8756 * is a bit ugly, but will happen in the relatively uncommon path. 8757 * TUNING: Might be worthwhile to inline this. 8758 * TODO: Basic-block style Jit will need a hook here as well. Fold it into 8759 * the suspendCount check so we can get both in 1 shot. 8760 * TODO: to match the other intepreters, this should handle suspension 8761 * and then check for debugger/profiling after dvmCheckSuspendPending 8762 * returns. 8763 */ 8764common_periodicChecks: 8765 movl offGlue_pSelfSuspendCount(%ecx),%eax # eax <- &suspendCount 8766 cmpl $0,(%eax) 8767 jne 1f 8768 8769#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 8770#if defined(WITH_DEBUGGER) 8771 movl offGlue_pDebuggerActive(%ecx),%eax # eax <- &DebuggerActive 8772#endif 8773#if defined(WITH_PROFILER) 8774 movl offGlue_pActiveProfilers(%ecx),%ecx # ecx <- &ActiveProfilers 8775#endif 8776#if defined(WITH_DEBUGGER) && defined(WITH_PROFILER) 8777 # TODO: check for NULL before load 8778 movzbl (%eax),%eax # eax <- debuggerActive (boolean) 8779 orl (%ecx),%eax # eax <- debuggerActive || activeProfilers 8780#elif defined(WITH_DEBUGGER) 8781 # TODO: check for NULL before load 8782 movzbl (%eax),%eax # eax <- debuggerActive (boolean) 8783#elif defined(WITH_PROFILER) 8784 movl (%ecx),%eax # eax <= activeProfilers 8785#endif 8786 GET_GLUE(%ecx) # restore rGLUE 8787 testl %eax,%eax 8788 jne 3f # one or both active - switch interp 8789#endif 8790 8791 ret 8792 8793 /* Check for suspend */ 87941: 8795 /* At this point, the return pointer to the caller of 8796 * common_periodicChecks is on the top of stack. We need to preserve 8797 * rPC(edx) and GLUE(ecx). We'll spill rPC, and reload GLUE. 8798 * The outgoing profile is: 8799 * bool dvmCheckSuspendPending(Thread* self) 8800 * Because we reached here via a call, go ahead and build a new frame. 8801 */ 8802 EXPORT_PC() # need for precise GC 8803 movl offGlue_self(%ecx),%eax # eax<- glue->self 8804 SPILL(rPC) # save edx 8805 push %ebp 8806 movl %esp,%ebp 8807 subl $24,%esp 8808 movl %eax,OUT_ARG0(%esp) 8809 call dvmCheckSuspendPending 8810 addl $24,%esp 8811 pop %ebp 8812 UNSPILL(rPC) 8813 GET_GLUE(%ecx) 8814 ret 8815 8816 /* Switch interpreters */ 8817 /* Note: %ebx contains the 16-bit word offset to be applied to rPC to 8818 * "complete" the interpretation of backwards branches. In effect, we 8819 * are completing the interpretation of the branch instruction here, 8820 * and the new interpreter will resume interpretation at the branch 8821 * target. However, a switch request recognized during the handling 8822 * of a return from method instruction results in an immediate abort, 8823 * and the new interpreter will resume by re-interpreting the return 8824 * instruction. 8825 */ 88263: 8827 leal (rPC,%ebx,2),rPC # adjust pc to show target 8828 GET_GLUE(%ecx) # bail expect GLUE already loaded 8829 movl $1,rINST_FULL # set changeInterp to true 8830 jmp common_gotoBail 8831 8832 8833/* 8834 * Common code for handling a return instruction 8835 */ 8836common_returnFromMethod: 8837 GET_GLUE(%ecx) 8838 /* Set entry mode in case we bail */ 8839 movb $kInterpEntryReturn,offGlue_entryPoint(%ecx) 8840 xorl rINST_FULL,rINST_FULL # zero offset in case we switch interps 8841 call common_periodicChecks # Note: expects %ecx to be preserved 8842 8843 SAVEAREA_FROM_FP(%eax,rFP) # eax<- saveArea (old) 8844 movl offStackSaveArea_prevFrame(%eax),rFP # rFP<- prevFrame 8845 movl (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST_FULL 8846 cmpl $0,rINST_FULL # break? 8847 je common_gotoBail # break frame, bail out completely 8848 8849 movl offStackSaveArea_savedPc(%eax),rPC # pc<- saveArea->savedPC 8850 movl offGlue_self(%ecx),%eax # eax<- self 8851 movl rINST_FULL,offGlue_method(%ecx) # glue->method = newSave->meethod 8852 movl rFP,offThread_curFrame(%eax) # self->curFrame = fp 8853 movl offMethod_clazz(rINST_FULL),%eax # eax<- method->clazz 8854 FETCH_INST_WORD(3) 8855 movl offClassObject_pDvmDex(%eax),%eax # eax<- method->clazz->pDvmDex 8856 ADVANCE_PC(3) 8857 movl %eax,offGlue_methodClassDex(%ecx) 8858 /* not bailing - restore entry mode to default */ 8859 movb $kInterpEntryInstr,offGlue_entryPoint(%ecx) 8860 GOTO_NEXT 8861 8862/* 8863 * Prepare to strip the current frame and "longjump" back to caller of 8864 * dvmMterpStdRun. 8865 * 8866 * on entry: 8867 * rINST_FULL holds changeInterp 8868 * ecx holds glue pointer 8869 * 8870 * expected profile: dvmMterpStdBail(MterpGlue *glue, bool changeInterp) 8871 */ 8872common_gotoBail: 8873 SAVE_PC_TO_GLUE(%ecx) # export state to glue 8874 SAVE_FP_TO_GLUE(%ecx) 8875 movl %ecx,OUT_ARG0(%esp) # glue in arg0 8876 movl rINST_FULL,OUT_ARG1(%esp) # changeInterp in arg1 8877 call dvmMterpStdBail # bail out.... 8878 8879 8880/* 8881 * After returning from a "glued" function, pull out the updated values 8882 * and start executing at the next instruction. 8883 */ 8884 common_resumeAfterGlueCall: 8885 GET_GLUE(%ecx) 8886 LOAD_PC_FROM_GLUE(%ecx) 8887 LOAD_FP_FROM_GLUE(%ecx) 8888 FETCH_INST() 8889 GOTO_NEXT 8890 8891/* 8892 * Integer divide or mod by zero 8893 */ 8894common_errDivideByZero: 8895 EXPORT_PC() 8896 movl $.LstrArithmeticException,%eax 8897 movl %eax,OUT_ARG0(%esp) 8898 movl $.LstrDivideByZero,%eax 8899 movl %eax,OUT_ARG1(%esp) 8900 SPILL(rPC) 8901 call dvmThrowException 8902 UNSPILL(rPC) 8903 jmp common_exceptionThrown 8904 8905/* 8906 * Attempt to allocate an array with a negative size. 8907 */ 8908common_errNegativeArraySize: 8909 EXPORT_PC() 8910 movl $.LstrNegativeArraySizeException,%eax 8911 movl %eax,OUT_ARG0(%esp) 8912 xorl %eax,%eax 8913 movl %eax,OUT_ARG1(%esp) 8914 SPILL(rPC) 8915 call dvmThrowException 8916 UNSPILL(rPC) 8917 jmp common_exceptionThrown 8918 8919/* 8920 * Attempt to allocate an array with a negative size. 8921 */ 8922common_errNoSuchMethod: 8923 8924 EXPORT_PC() 8925 movl $.LstrNoSuchMethodError,%eax 8926 movl %eax,OUT_ARG0(%esp) 8927 xorl %eax,%eax 8928 movl %eax,OUT_ARG1(%esp) 8929 SPILL(rPC) 8930 call dvmThrowException 8931 UNSPILL(rPC) 8932 jmp common_exceptionThrown 8933 8934/* 8935 * Hit a null object when we weren't expecting one. Export the PC, throw a 8936 * NullPointerException and goto the exception processing code. 8937 */ 8938common_errNullObject: 8939 EXPORT_PC() 8940 movl $.LstrNullPointerException,%eax 8941 movl %eax,OUT_ARG0(%esp) 8942 xorl %eax,%eax 8943 movl %eax,OUT_ARG1(%esp) 8944 SPILL(rPC) 8945 call dvmThrowException 8946 UNSPILL(rPC) 8947 jmp common_exceptionThrown 8948 8949/* 8950 * Array index exceeds max. 8951 */ 8952common_errArrayIndex: 8953 EXPORT_PC() 8954 movl $.LstrArrayIndexException,%eax 8955 movl %eax,OUT_ARG0(%esp) 8956 xorl %eax,%eax 8957 movl %eax,OUT_ARG1(%esp) 8958 SPILL(rPC) 8959 call dvmThrowException 8960 UNSPILL(rPC) 8961 jmp common_exceptionThrown 8962/* 8963 * Invalid array value. 8964 */ 8965common_errArrayStore: 8966 EXPORT_PC() 8967 movl $.LstrArrayStoreException,%eax 8968 movl %eax,OUT_ARG0(%esp) 8969 xorl %eax,%eax 8970 movl %eax,OUT_ARG1(%esp) 8971 SPILL(rPC) 8972 call dvmThrowException 8973 UNSPILL(rPC) 8974 jmp common_exceptionThrown 8975 8976/* 8977 * Somebody has thrown an exception. Handle it. 8978 * 8979 * If the exception processing code returns to us (instead of falling 8980 * out of the interpreter), continue with whatever the next instruction 8981 * now happens to be. 8982 * 8983 * This does not return. 8984 */ 8985common_exceptionThrown: 8986 GET_GLUE(%ecx) 8987 SAVE_PC_TO_GLUE(%ecx) 8988 SAVE_FP_TO_GLUE(%ecx) 8989 movl %ecx,OUT_ARG0(%esp) 8990 call dvmMterp_exceptionThrown 8991 jmp common_resumeAfterGlueCall 8992 8993common_abort: 8994 movl $0xdeadf00d,%eax 8995 call *%eax 8996 8997 8998/* 8999 * Strings 9000 */ 9001 9002 .section .rodata 9003.LstrNullPointerException: 9004 .asciz "Ljava/lang/NullPointerException;" 9005.LstrArithmeticException: 9006 .asciz "Ljava/lang/ArithmeticException;" 9007.LstrDivideByZero: 9008 .asciz "divide by zero" 9009.LstrArrayIndexException: 9010 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 9011.LstrArrayStoreException: 9012 .asciz "Ljava/lang/ArrayStoreException;" 9013.LstrNegativeArraySizeException: 9014 .asciz "Ljava/lang/NegativeArraySizeException;" 9015.LstrInstantiationError: 9016 .asciz "Ljava/lang/InstantiationError;" 9017.LstrClassCastException: 9018 .asciz "Ljava/lang/ClassCastException;" 9019.LstrNoSuchMethodError: 9020 .asciz "Ljava/lang/NoSuchMethodError;" 9021.LstrInternalError: 9022 .asciz "Ljava/lang/InternalError;" 9023.LstrFilledNewArrayNotImpl: 9024 .asciz "filled-new-array only implemented for 'int'" 9025 9026