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