InterpAsm-armv7-a.S revision d88756df5b4dbc6fd450afd0019a5f64ebe4432d
1/* 2 * This file was generated automatically by gen-mterp.py for 'armv7-a'. 3 * 4 * --> DO NOT EDIT <-- 5 */ 6 7/* File: armv5te/header.S */ 8/* 9 * Copyright (C) 2008 The Android Open Source Project 10 * 11 * Licensed under the Apache License, Version 2.0 (the "License"); 12 * you may not use this file except in compliance with the License. 13 * You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 */ 23 24/* 25 * ARMv5 definitions and declarations. 26 */ 27 28/* 29ARM EABI general notes: 30 31r0-r3 hold first 4 args to a method; they are not preserved across method calls 32r4-r8 are available for general use 33r9 is given special treatment in some situations, but not for us 34r10 (sl) seems to be generally available 35r11 (fp) is used by gcc (unless -fomit-frame-pointer is set) 36r12 (ip) is scratch -- not preserved across method calls 37r13 (sp) should be managed carefully in case a signal arrives 38r14 (lr) must be preserved 39r15 (pc) can be tinkered with directly 40 41r0 holds returns of <= 4 bytes 42r0-r1 hold returns of 8 bytes, low word in r0 43 44Callee must save/restore r4+ (except r12) if it modifies them. If VFP 45is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved, 46s0-s15 (d0-d7, q0-a3) do not need to be. 47 48Stack is "full descending". Only the arguments that don't fit in the first 4 49registers are placed on the stack. "sp" points at the first stacked argument 50(i.e. the 5th arg). 51 52VFP: single-precision results in s0, double-precision results in d0. 53 54In the EABI, "sp" must be 64-bit aligned on entry to a function, and any 5564-bit quantities (long long, double) must be 64-bit aligned. 56*/ 57 58/* 59Mterp and ARM notes: 60 61The following registers have fixed assignments: 62 63 reg nick purpose 64 r4 rPC interpreted program counter, used for fetching instructions 65 r5 rFP interpreted frame pointer, used for accessing locals and args 66 r6 rGLUE MterpGlue pointer 67 r7 rINST first 16-bit code unit of current instruction 68 r8 rIBASE interpreted instruction base pointer, used for computed goto 69 70Macros are provided for common operations. Each macro MUST emit only 71one instruction to make instruction-counting easier. They MUST NOT alter 72unspecified registers or condition codes. 73*/ 74 75/* single-purpose registers, given names for clarity */ 76#define rPC r4 77#define rFP r5 78#define rGLUE r6 79#define rINST r7 80#define rIBASE r8 81 82/* save/restore the PC and/or FP from the glue struct */ 83#define LOAD_PC_FROM_GLUE() ldr rPC, [rGLUE, #offGlue_pc] 84#define SAVE_PC_TO_GLUE() str rPC, [rGLUE, #offGlue_pc] 85#define LOAD_FP_FROM_GLUE() ldr rFP, [rGLUE, #offGlue_fp] 86#define SAVE_FP_TO_GLUE() str rFP, [rGLUE, #offGlue_fp] 87#define LOAD_PC_FP_FROM_GLUE() ldmia rGLUE, {rPC, rFP} 88#define SAVE_PC_FP_TO_GLUE() stmia rGLUE, {rPC, rFP} 89 90/* 91 * "export" the PC to the stack frame, f/b/o future exception objects. Must 92 * be done *before* something calls dvmThrowException. 93 * 94 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e. 95 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc) 96 * 97 * It's okay to do this more than once. 98 */ 99#define EXPORT_PC() \ 100 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)] 101 102/* 103 * Given a frame pointer, find the stack save area. 104 * 105 * In C this is "((StackSaveArea*)(_fp) -1)". 106 */ 107#define SAVEAREA_FROM_FP(_reg, _fpreg) \ 108 sub _reg, _fpreg, #sizeofStackSaveArea 109 110/* 111 * Fetch the next instruction from rPC into rINST. Does not advance rPC. 112 */ 113#define FETCH_INST() ldrh rINST, [rPC] 114 115/* 116 * Fetch the next instruction from the specified offset. Advances rPC 117 * to point to the next instruction. "_count" is in 16-bit code units. 118 * 119 * Because of the limited size of immediate constants on ARM, this is only 120 * suitable for small forward movements (i.e. don't try to implement "goto" 121 * with this). 122 * 123 * This must come AFTER anything that can throw an exception, or the 124 * exception catch may miss. (This also implies that it must come after 125 * EXPORT_PC().) 126 */ 127#define FETCH_ADVANCE_INST(_count) ldrh rINST, [rPC, #(_count*2)]! 128 129/* 130 * The operation performed here is similar to FETCH_ADVANCE_INST, except the 131 * src and dest registers are parameterized (not hard-wired to rPC and rINST). 132 */ 133#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \ 134 ldrh _dreg, [_sreg, #(_count*2)]! 135 136/* 137 * Fetch the next instruction from an offset specified by _reg. Updates 138 * rPC to point to the next instruction. "_reg" must specify the distance 139 * in bytes, *not* 16-bit code units, and may be a signed value. 140 * 141 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the 142 * bits that hold the shift distance are used for the half/byte/sign flags. 143 * In some cases we can pre-double _reg for free, so we require a byte offset 144 * here. 145 */ 146#define FETCH_ADVANCE_INST_RB(_reg) ldrh rINST, [rPC, _reg]! 147 148/* 149 * Fetch a half-word code unit from an offset past the current PC. The 150 * "_count" value is in 16-bit code units. Does not advance rPC. 151 * 152 * The "_S" variant works the same but treats the value as signed. 153 */ 154#define FETCH(_reg, _count) ldrh _reg, [rPC, #(_count*2)] 155#define FETCH_S(_reg, _count) ldrsh _reg, [rPC, #(_count*2)] 156 157/* 158 * Fetch one byte from an offset past the current PC. Pass in the same 159 * "_count" as you would for FETCH, and an additional 0/1 indicating which 160 * byte of the halfword you want (lo/hi). 161 */ 162#define FETCH_B(_reg, _count, _byte) ldrb _reg, [rPC, #(_count*2+_byte)] 163 164/* 165 * Put the instruction's opcode field into the specified register. 166 */ 167#define GET_INST_OPCODE(_reg) and _reg, rINST, #255 168 169/* 170 * Put the prefetched instruction's opcode field into the specified register. 171 */ 172#define GET_PREFETCHED_OPCODE(_oreg, _ireg) and _oreg, _ireg, #255 173 174/* 175 * Begin executing the opcode in _reg. Because this only jumps within the 176 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork. 177 */ 178#define GOTO_OPCODE(_reg) add pc, rIBASE, _reg, lsl #6 179#define GOTO_OPCODE_IFEQ(_reg) addeq pc, rIBASE, _reg, lsl #6 180#define GOTO_OPCODE_IFNE(_reg) addne pc, rIBASE, _reg, lsl #6 181 182/* 183 * Get/set the 32-bit value from a Dalvik register. 184 */ 185#define GET_VREG(_reg, _vreg) ldr _reg, [rFP, _vreg, lsl #2] 186#define SET_VREG(_reg, _vreg) str _reg, [rFP, _vreg, lsl #2] 187 188#if defined(WITH_JIT) 189#define GET_JIT_PROF_TABLE(_reg) ldr _reg,[rGLUE,#offGlue_pJitProfTable] 190#define GET_JIT_THRESHOLD(_reg) ldr _reg,[rGLUE,#offGlue_jitThreshold] 191#endif 192 193/* 194 * Convert a virtual register index into an address. 195 */ 196#define VREG_INDEX_TO_ADDR(_reg, _vreg) \ 197 add _reg, rFP, _vreg, lsl #2 198 199/* 200 * This is a #include, not a %include, because we want the C pre-processor 201 * to expand the macros into assembler assignment statements. 202 */ 203#include "../common/asm-constants.h" 204 205#if defined(WITH_JIT) 206#include "../common/jit-config.h" 207#endif 208 209/* File: armv7-a/platform.S */ 210/* 211 * =========================================================================== 212 * CPU-version-specific defines 213 * =========================================================================== 214 */ 215 216#if !defined(ANDROID_SMP) 217# error "Must define ANDROID_SMP" 218#endif 219 220/* 221 * Macro for data memory barrier. 222 */ 223.macro SMP_DMB 224#if ANDROID_SMP != 0 225 dmb 226#else 227 /* not SMP */ 228#endif 229.endm 230 231/* 232 * Macro for data memory barrier (store/store variant). 233 */ 234.macro SMP_DMB_ST 235#if ANDROID_SMP != 0 236 dmb st 237#else 238 /* not SMP */ 239#endif 240.endm 241 242/* File: armv5te/entry.S */ 243/* 244 * Copyright (C) 2008 The Android Open Source Project 245 * 246 * Licensed under the Apache License, Version 2.0 (the "License"); 247 * you may not use this file except in compliance with the License. 248 * You may obtain a copy of the License at 249 * 250 * http://www.apache.org/licenses/LICENSE-2.0 251 * 252 * Unless required by applicable law or agreed to in writing, software 253 * distributed under the License is distributed on an "AS IS" BASIS, 254 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 255 * See the License for the specific language governing permissions and 256 * limitations under the License. 257 */ 258/* 259 * Interpreter entry point. 260 */ 261 262/* 263 * We don't have formal stack frames, so gdb scans upward in the code 264 * to find the start of the function (a label with the %function type), 265 * and then looks at the next few instructions to figure out what 266 * got pushed onto the stack. From this it figures out how to restore 267 * the registers, including PC, for the previous stack frame. If gdb 268 * sees a non-function label, it stops scanning, so either we need to 269 * have nothing but assembler-local labels between the entry point and 270 * the break, or we need to fake it out. 271 * 272 * When this is defined, we add some stuff to make gdb less confused. 273 */ 274#define ASSIST_DEBUGGER 1 275 276 .text 277 .align 2 278 .global dvmMterpStdRun 279 .type dvmMterpStdRun, %function 280 281/* 282 * On entry: 283 * r0 MterpGlue* glue 284 * 285 * This function returns a boolean "changeInterp" value. The return comes 286 * via a call to dvmMterpStdBail(). 287 */ 288dvmMterpStdRun: 289#define MTERP_ENTRY1 \ 290 .save {r4-r10,fp,lr}; \ 291 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs 292#define MTERP_ENTRY2 \ 293 .pad #4; \ 294 sub sp, sp, #4 @ align 64 295 296 .fnstart 297 MTERP_ENTRY1 298 MTERP_ENTRY2 299 300 /* save stack pointer, add magic word for debuggerd */ 301 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return 302 303 /* set up "named" registers, figure out entry point */ 304 mov rGLUE, r0 @ set rGLUE 305 ldr r1, [r0, #offGlue_entryPoint] @ enum is 4 bytes in aapcs-EABI 306 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue" 307 adr rIBASE, dvmAsmInstructionStart @ set rIBASE 308 cmp r1, #kInterpEntryInstr @ usual case? 309 bne .Lnot_instr @ no, handle it 310 311#if defined(WITH_JIT) 312.LentryInstr: 313 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 314 /* Entry is always a possible trace start */ 315 GET_JIT_PROF_TABLE(r0) 316 FETCH_INST() 317 mov r1, #0 @ prepare the value for the new state 318 str r1, [r10, #offThread_inJitCodeCache] @ back to the interp land 319 cmp r0,#0 @ is profiling disabled? 320#if !defined(WITH_SELF_VERIFICATION) 321 bne common_updateProfile @ profiling is enabled 322#else 323 ldr r2, [r10, #offThread_shadowSpace] @ to find out the jit exit state 324 beq 1f @ profiling is disabled 325 ldr r3, [r2, #offShadowSpace_jitExitState] @ jit exit state 326 cmp r3, #kSVSTraceSelect @ hot trace following? 327 moveq r2,#kJitTSelectRequestHot @ ask for trace selection 328 beq common_selectTrace @ go build the trace 329 cmp r3, #kSVSNoProfile @ don't profile the next instruction? 330 beq 1f @ intrepret the next instruction 331 b common_updateProfile @ collect profiles 332#endif 3331: 334 GET_INST_OPCODE(ip) 335 GOTO_OPCODE(ip) 336#else 337 /* start executing the instruction at rPC */ 338 FETCH_INST() @ load rINST from rPC 339 GET_INST_OPCODE(ip) @ extract opcode from rINST 340 GOTO_OPCODE(ip) @ jump to next instruction 341#endif 342 343.Lnot_instr: 344 cmp r1, #kInterpEntryReturn @ were we returning from a method? 345 beq common_returnFromMethod 346 347.Lnot_return: 348 cmp r1, #kInterpEntryThrow @ were we throwing an exception? 349 beq common_exceptionThrown 350 351#if defined(WITH_JIT) 352.Lnot_throw: 353 ldr r10,[rGLUE, #offGlue_jitResumeNPC] 354 ldr r2,[rGLUE, #offGlue_jitResumeDPC] 355 cmp r1, #kInterpEntryResume @ resuming after Jit single-step? 356 bne .Lbad_arg 357 cmp rPC,r2 358 bne .LentryInstr @ must have branched, don't resume 359#if defined(WITH_SELF_VERIFICATION) 360 @ glue->entryPoint will be set in dvmSelfVerificationSaveState 361 b jitSVShadowRunStart @ re-enter the translation after the 362 @ single-stepped instruction 363 @noreturn 364#endif 365 mov r1, #kInterpEntryInstr 366 str r1, [rGLUE, #offGlue_entryPoint] 367 bx r10 @ re-enter the translation 368#endif 369 370.Lbad_arg: 371 ldr r0, strBadEntryPoint 372 @ r1 holds value of entryPoint 373 bl printf 374 bl dvmAbort 375 .fnend 376 377 378 .global dvmMterpStdBail 379 .type dvmMterpStdBail, %function 380 381/* 382 * Restore the stack pointer and PC from the save point established on entry. 383 * This is essentially the same as a longjmp, but should be cheaper. The 384 * last instruction causes us to return to whoever called dvmMterpStdRun. 385 * 386 * We pushed some registers on the stack in dvmMterpStdRun, then saved 387 * SP and LR. Here we restore SP, restore the registers, and then restore 388 * LR to PC. 389 * 390 * On entry: 391 * r0 MterpGlue* glue 392 * r1 bool changeInterp 393 */ 394dvmMterpStdBail: 395 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 396 mov r0, r1 @ return the changeInterp value 397 add sp, sp, #4 @ un-align 64 398 ldmfd sp!, {r4-r10,fp,pc} @ restore 9 regs and return 399 400 401/* 402 * String references. 403 */ 404strBadEntryPoint: 405 .word .LstrBadEntryPoint 406 407 408 .global dvmAsmInstructionStart 409 .type dvmAsmInstructionStart, %function 410dvmAsmInstructionStart = .L_OP_NOP 411 .text 412 413/* ------------------------------ */ 414 .balign 64 415.L_OP_NOP: /* 0x00 */ 416/* File: armv5te/OP_NOP.S */ 417 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST 418 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 419 GOTO_OPCODE(ip) @ execute it 420 421#ifdef ASSIST_DEBUGGER 422 /* insert fake function header to help gdb find the stack frame */ 423 .type dalvik_inst, %function 424dalvik_inst: 425 .fnstart 426 MTERP_ENTRY1 427 MTERP_ENTRY2 428 .fnend 429#endif 430 431/* ------------------------------ */ 432 .balign 64 433.L_OP_MOVE: /* 0x01 */ 434/* File: armv6t2/OP_MOVE.S */ 435 /* for move, move-object, long-to-int */ 436 /* op vA, vB */ 437 mov r1, rINST, lsr #12 @ r1<- B from 15:12 438 ubfx r0, rINST, #8, #4 @ r0<- A from 11:8 439 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 440 GET_VREG(r2, r1) @ r2<- fp[B] 441 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 442 SET_VREG(r2, r0) @ fp[A]<- r2 443 GOTO_OPCODE(ip) @ execute next instruction 444 445/* ------------------------------ */ 446 .balign 64 447.L_OP_MOVE_FROM16: /* 0x02 */ 448/* File: armv5te/OP_MOVE_FROM16.S */ 449 /* for: move/from16, move-object/from16 */ 450 /* op vAA, vBBBB */ 451 FETCH(r1, 1) @ r1<- BBBB 452 mov r0, rINST, lsr #8 @ r0<- AA 453 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 454 GET_VREG(r2, r1) @ r2<- fp[BBBB] 455 GET_INST_OPCODE(ip) @ extract opcode from rINST 456 SET_VREG(r2, r0) @ fp[AA]<- r2 457 GOTO_OPCODE(ip) @ jump to next instruction 458 459/* ------------------------------ */ 460 .balign 64 461.L_OP_MOVE_16: /* 0x03 */ 462/* File: armv5te/OP_MOVE_16.S */ 463 /* for: move/16, move-object/16 */ 464 /* op vAAAA, vBBBB */ 465 FETCH(r1, 2) @ r1<- BBBB 466 FETCH(r0, 1) @ r0<- AAAA 467 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 468 GET_VREG(r2, r1) @ r2<- fp[BBBB] 469 GET_INST_OPCODE(ip) @ extract opcode from rINST 470 SET_VREG(r2, r0) @ fp[AAAA]<- r2 471 GOTO_OPCODE(ip) @ jump to next instruction 472 473/* ------------------------------ */ 474 .balign 64 475.L_OP_MOVE_WIDE: /* 0x04 */ 476/* File: armv6t2/OP_MOVE_WIDE.S */ 477 /* move-wide vA, vB */ 478 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 479 mov r3, rINST, lsr #12 @ r3<- B 480 ubfx r2, rINST, #8, #4 @ r2<- A 481 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 482 add r2, rFP, r2, lsl #2 @ r2<- &fp[A] 483 ldmia r3, {r0-r1} @ r0/r1<- fp[B] 484 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 485 GET_INST_OPCODE(ip) @ extract opcode from rINST 486 stmia r2, {r0-r1} @ fp[A]<- r0/r1 487 GOTO_OPCODE(ip) @ jump to next instruction 488 489/* ------------------------------ */ 490 .balign 64 491.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 492/* File: armv5te/OP_MOVE_WIDE_FROM16.S */ 493 /* move-wide/from16 vAA, vBBBB */ 494 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 495 FETCH(r3, 1) @ r3<- BBBB 496 mov r2, rINST, lsr #8 @ r2<- AA 497 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 498 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 499 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 500 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 501 GET_INST_OPCODE(ip) @ extract opcode from rINST 502 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 503 GOTO_OPCODE(ip) @ jump to next instruction 504 505/* ------------------------------ */ 506 .balign 64 507.L_OP_MOVE_WIDE_16: /* 0x06 */ 508/* File: armv5te/OP_MOVE_WIDE_16.S */ 509 /* move-wide/16 vAAAA, vBBBB */ 510 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 511 FETCH(r3, 2) @ r3<- BBBB 512 FETCH(r2, 1) @ r2<- AAAA 513 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 514 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA] 515 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 516 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 517 GET_INST_OPCODE(ip) @ extract opcode from rINST 518 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1 519 GOTO_OPCODE(ip) @ jump to next instruction 520 521/* ------------------------------ */ 522 .balign 64 523.L_OP_MOVE_OBJECT: /* 0x07 */ 524/* File: armv5te/OP_MOVE_OBJECT.S */ 525/* File: armv5te/OP_MOVE.S */ 526 /* for move, move-object, long-to-int */ 527 /* op vA, vB */ 528 mov r1, rINST, lsr #12 @ r1<- B from 15:12 529 mov r0, rINST, lsr #8 @ r0<- A from 11:8 530 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 531 GET_VREG(r2, r1) @ r2<- fp[B] 532 and r0, r0, #15 533 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 534 SET_VREG(r2, r0) @ fp[A]<- r2 535 GOTO_OPCODE(ip) @ execute next instruction 536 537 538/* ------------------------------ */ 539 .balign 64 540.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 541/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */ 542/* File: armv5te/OP_MOVE_FROM16.S */ 543 /* for: move/from16, move-object/from16 */ 544 /* op vAA, vBBBB */ 545 FETCH(r1, 1) @ r1<- BBBB 546 mov r0, rINST, lsr #8 @ r0<- AA 547 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 548 GET_VREG(r2, r1) @ r2<- fp[BBBB] 549 GET_INST_OPCODE(ip) @ extract opcode from rINST 550 SET_VREG(r2, r0) @ fp[AA]<- r2 551 GOTO_OPCODE(ip) @ jump to next instruction 552 553 554/* ------------------------------ */ 555 .balign 64 556.L_OP_MOVE_OBJECT_16: /* 0x09 */ 557/* File: armv5te/OP_MOVE_OBJECT_16.S */ 558/* File: armv5te/OP_MOVE_16.S */ 559 /* for: move/16, move-object/16 */ 560 /* op vAAAA, vBBBB */ 561 FETCH(r1, 2) @ r1<- BBBB 562 FETCH(r0, 1) @ r0<- AAAA 563 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 564 GET_VREG(r2, r1) @ r2<- fp[BBBB] 565 GET_INST_OPCODE(ip) @ extract opcode from rINST 566 SET_VREG(r2, r0) @ fp[AAAA]<- r2 567 GOTO_OPCODE(ip) @ jump to next instruction 568 569 570/* ------------------------------ */ 571 .balign 64 572.L_OP_MOVE_RESULT: /* 0x0a */ 573/* File: armv5te/OP_MOVE_RESULT.S */ 574 /* for: move-result, move-result-object */ 575 /* op vAA */ 576 mov r2, rINST, lsr #8 @ r2<- AA 577 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 578 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 579 GET_INST_OPCODE(ip) @ extract opcode from rINST 580 SET_VREG(r0, r2) @ fp[AA]<- r0 581 GOTO_OPCODE(ip) @ jump to next instruction 582 583/* ------------------------------ */ 584 .balign 64 585.L_OP_MOVE_RESULT_WIDE: /* 0x0b */ 586/* File: armv5te/OP_MOVE_RESULT_WIDE.S */ 587 /* move-result-wide vAA */ 588 mov r2, rINST, lsr #8 @ r2<- AA 589 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 590 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 591 ldmia r3, {r0-r1} @ r0/r1<- retval.j 592 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 593 GET_INST_OPCODE(ip) @ extract opcode from rINST 594 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 595 GOTO_OPCODE(ip) @ jump to next instruction 596 597/* ------------------------------ */ 598 .balign 64 599.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 600/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */ 601/* File: armv5te/OP_MOVE_RESULT.S */ 602 /* for: move-result, move-result-object */ 603 /* op vAA */ 604 mov r2, rINST, lsr #8 @ r2<- AA 605 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 606 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 607 GET_INST_OPCODE(ip) @ extract opcode from rINST 608 SET_VREG(r0, r2) @ fp[AA]<- r0 609 GOTO_OPCODE(ip) @ jump to next instruction 610 611 612/* ------------------------------ */ 613 .balign 64 614.L_OP_MOVE_EXCEPTION: /* 0x0d */ 615/* File: armv5te/OP_MOVE_EXCEPTION.S */ 616 /* move-exception vAA */ 617 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 618 mov r2, rINST, lsr #8 @ r2<- AA 619 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass 620 mov r1, #0 @ r1<- 0 621 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 622 SET_VREG(r3, r2) @ fp[AA]<- exception obj 623 GET_INST_OPCODE(ip) @ extract opcode from rINST 624 str r1, [r0, #offThread_exception] @ dvmClearException bypass 625 GOTO_OPCODE(ip) @ jump to next instruction 626 627/* ------------------------------ */ 628 .balign 64 629.L_OP_RETURN_VOID: /* 0x0e */ 630/* File: armv5te/OP_RETURN_VOID.S */ 631 b common_returnFromMethod 632 633/* ------------------------------ */ 634 .balign 64 635.L_OP_RETURN: /* 0x0f */ 636/* File: armv5te/OP_RETURN.S */ 637 /* 638 * Return a 32-bit value. Copies the return value into the "glue" 639 * structure, then jumps to the return handler. 640 * 641 * for: return, return-object 642 */ 643 /* op vAA */ 644 mov r2, rINST, lsr #8 @ r2<- AA 645 GET_VREG(r0, r2) @ r0<- vAA 646 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 647 b common_returnFromMethod 648 649/* ------------------------------ */ 650 .balign 64 651.L_OP_RETURN_WIDE: /* 0x10 */ 652/* File: armv5te/OP_RETURN_WIDE.S */ 653 /* 654 * Return a 64-bit value. Copies the return value into the "glue" 655 * structure, then jumps to the return handler. 656 */ 657 /* return-wide vAA */ 658 mov r2, rINST, lsr #8 @ r2<- AA 659 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 660 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 661 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1 662 stmia r3, {r0-r1} @ retval<- r0/r1 663 b common_returnFromMethod 664 665/* ------------------------------ */ 666 .balign 64 667.L_OP_RETURN_OBJECT: /* 0x11 */ 668/* File: armv5te/OP_RETURN_OBJECT.S */ 669/* File: armv5te/OP_RETURN.S */ 670 /* 671 * Return a 32-bit value. Copies the return value into the "glue" 672 * structure, then jumps to the return handler. 673 * 674 * for: return, return-object 675 */ 676 /* op vAA */ 677 mov r2, rINST, lsr #8 @ r2<- AA 678 GET_VREG(r0, r2) @ r0<- vAA 679 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 680 b common_returnFromMethod 681 682 683/* ------------------------------ */ 684 .balign 64 685.L_OP_CONST_4: /* 0x12 */ 686/* File: armv6t2/OP_CONST_4.S */ 687 /* const/4 vA, #+B */ 688 mov r1, rINST, lsl #16 @ r1<- Bxxx0000 689 ubfx r0, rINST, #8, #4 @ r0<- A 690 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 691 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended) 692 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 693 SET_VREG(r1, r0) @ fp[A]<- r1 694 GOTO_OPCODE(ip) @ execute next instruction 695 696/* ------------------------------ */ 697 .balign 64 698.L_OP_CONST_16: /* 0x13 */ 699/* File: armv5te/OP_CONST_16.S */ 700 /* const/16 vAA, #+BBBB */ 701 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 702 mov r3, rINST, lsr #8 @ r3<- AA 703 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 704 SET_VREG(r0, r3) @ vAA<- r0 705 GET_INST_OPCODE(ip) @ extract opcode from rINST 706 GOTO_OPCODE(ip) @ jump to next instruction 707 708/* ------------------------------ */ 709 .balign 64 710.L_OP_CONST: /* 0x14 */ 711/* File: armv5te/OP_CONST.S */ 712 /* const vAA, #+BBBBbbbb */ 713 mov r3, rINST, lsr #8 @ r3<- AA 714 FETCH(r0, 1) @ r0<- bbbb (low) 715 FETCH(r1, 2) @ r1<- BBBB (high) 716 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 717 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 718 GET_INST_OPCODE(ip) @ extract opcode from rINST 719 SET_VREG(r0, r3) @ vAA<- r0 720 GOTO_OPCODE(ip) @ jump to next instruction 721 722/* ------------------------------ */ 723 .balign 64 724.L_OP_CONST_HIGH16: /* 0x15 */ 725/* File: armv5te/OP_CONST_HIGH16.S */ 726 /* const/high16 vAA, #+BBBB0000 */ 727 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended) 728 mov r3, rINST, lsr #8 @ r3<- AA 729 mov r0, r0, lsl #16 @ r0<- BBBB0000 730 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 731 SET_VREG(r0, r3) @ vAA<- r0 732 GET_INST_OPCODE(ip) @ extract opcode from rINST 733 GOTO_OPCODE(ip) @ jump to next instruction 734 735/* ------------------------------ */ 736 .balign 64 737.L_OP_CONST_WIDE_16: /* 0x16 */ 738/* File: armv5te/OP_CONST_WIDE_16.S */ 739 /* const-wide/16 vAA, #+BBBB */ 740 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 741 mov r3, rINST, lsr #8 @ r3<- AA 742 mov r1, r0, asr #31 @ r1<- ssssssss 743 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 744 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 745 GET_INST_OPCODE(ip) @ extract opcode from rINST 746 stmia r3, {r0-r1} @ vAA<- r0/r1 747 GOTO_OPCODE(ip) @ jump to next instruction 748 749/* ------------------------------ */ 750 .balign 64 751.L_OP_CONST_WIDE_32: /* 0x17 */ 752/* File: armv5te/OP_CONST_WIDE_32.S */ 753 /* const-wide/32 vAA, #+BBBBbbbb */ 754 FETCH(r0, 1) @ r0<- 0000bbbb (low) 755 mov r3, rINST, lsr #8 @ r3<- AA 756 FETCH_S(r2, 2) @ r2<- ssssBBBB (high) 757 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 758 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb 759 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 760 mov r1, r0, asr #31 @ r1<- ssssssss 761 GET_INST_OPCODE(ip) @ extract opcode from rINST 762 stmia r3, {r0-r1} @ vAA<- r0/r1 763 GOTO_OPCODE(ip) @ jump to next instruction 764 765/* ------------------------------ */ 766 .balign 64 767.L_OP_CONST_WIDE: /* 0x18 */ 768/* File: armv5te/OP_CONST_WIDE.S */ 769 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 770 FETCH(r0, 1) @ r0<- bbbb (low) 771 FETCH(r1, 2) @ r1<- BBBB (low middle) 772 FETCH(r2, 3) @ r2<- hhhh (high middle) 773 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word) 774 FETCH(r3, 4) @ r3<- HHHH (high) 775 mov r9, rINST, lsr #8 @ r9<- AA 776 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word) 777 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 778 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 779 GET_INST_OPCODE(ip) @ extract opcode from rINST 780 stmia r9, {r0-r1} @ vAA<- r0/r1 781 GOTO_OPCODE(ip) @ jump to next instruction 782 783/* ------------------------------ */ 784 .balign 64 785.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 786/* File: armv5te/OP_CONST_WIDE_HIGH16.S */ 787 /* const-wide/high16 vAA, #+BBBB000000000000 */ 788 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended) 789 mov r3, rINST, lsr #8 @ r3<- AA 790 mov r0, #0 @ r0<- 00000000 791 mov r1, r1, lsl #16 @ r1<- BBBB0000 792 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 793 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 794 GET_INST_OPCODE(ip) @ extract opcode from rINST 795 stmia r3, {r0-r1} @ vAA<- r0/r1 796 GOTO_OPCODE(ip) @ jump to next instruction 797 798/* ------------------------------ */ 799 .balign 64 800.L_OP_CONST_STRING: /* 0x1a */ 801/* File: armv5te/OP_CONST_STRING.S */ 802 /* const/string vAA, String@BBBB */ 803 FETCH(r1, 1) @ r1<- BBBB 804 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 805 mov r9, rINST, lsr #8 @ r9<- AA 806 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 807 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 808 cmp r0, #0 @ not yet resolved? 809 beq .LOP_CONST_STRING_resolve 810 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 811 GET_INST_OPCODE(ip) @ extract opcode from rINST 812 SET_VREG(r0, r9) @ vAA<- r0 813 GOTO_OPCODE(ip) @ jump to next instruction 814 815/* ------------------------------ */ 816 .balign 64 817.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 818/* File: armv5te/OP_CONST_STRING_JUMBO.S */ 819 /* const/string vAA, String@BBBBBBBB */ 820 FETCH(r0, 1) @ r0<- bbbb (low) 821 FETCH(r1, 2) @ r1<- BBBB (high) 822 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 823 mov r9, rINST, lsr #8 @ r9<- AA 824 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 825 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 826 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 827 cmp r0, #0 828 beq .LOP_CONST_STRING_JUMBO_resolve 829 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 830 GET_INST_OPCODE(ip) @ extract opcode from rINST 831 SET_VREG(r0, r9) @ vAA<- r0 832 GOTO_OPCODE(ip) @ jump to next instruction 833 834/* ------------------------------ */ 835 .balign 64 836.L_OP_CONST_CLASS: /* 0x1c */ 837/* File: armv5te/OP_CONST_CLASS.S */ 838 /* const/class vAA, Class@BBBB */ 839 FETCH(r1, 1) @ r1<- BBBB 840 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 841 mov r9, rINST, lsr #8 @ r9<- AA 842 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 843 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB] 844 cmp r0, #0 @ not yet resolved? 845 beq .LOP_CONST_CLASS_resolve 846 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 847 GET_INST_OPCODE(ip) @ extract opcode from rINST 848 SET_VREG(r0, r9) @ vAA<- r0 849 GOTO_OPCODE(ip) @ jump to next instruction 850 851/* ------------------------------ */ 852 .balign 64 853.L_OP_MONITOR_ENTER: /* 0x1d */ 854/* File: armv5te/OP_MONITOR_ENTER.S */ 855 /* 856 * Synchronize on an object. 857 */ 858 /* monitor-enter vAA */ 859 mov r2, rINST, lsr #8 @ r2<- AA 860 GET_VREG(r1, r2) @ r1<- vAA (object) 861 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 862 cmp r1, #0 @ null object? 863 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING 864 beq common_errNullObject @ null object, throw an exception 865 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 866 bl dvmLockObject @ call(self, obj) 867#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ 868 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 869 ldr r1, [r0, #offThread_exception] @ check for exception 870 cmp r1, #0 871 bne common_exceptionThrown @ exception raised, bail out 872#endif 873 GET_INST_OPCODE(ip) @ extract opcode from rINST 874 GOTO_OPCODE(ip) @ jump to next instruction 875 876/* ------------------------------ */ 877 .balign 64 878.L_OP_MONITOR_EXIT: /* 0x1e */ 879/* File: armv5te/OP_MONITOR_EXIT.S */ 880 /* 881 * Unlock an object. 882 * 883 * Exceptions that occur when unlocking a monitor need to appear as 884 * if they happened at the following instruction. See the Dalvik 885 * instruction spec. 886 */ 887 /* monitor-exit vAA */ 888 mov r2, rINST, lsr #8 @ r2<- AA 889 EXPORT_PC() @ before fetch: export the PC 890 GET_VREG(r1, r2) @ r1<- vAA (object) 891 cmp r1, #0 @ null object? 892 beq 1f @ yes 893 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 894 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 895 cmp r0, #0 @ failed? 896 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 897 beq common_exceptionThrown @ yes, exception is pending 898 GET_INST_OPCODE(ip) @ extract opcode from rINST 899 GOTO_OPCODE(ip) @ jump to next instruction 9001: 901 FETCH_ADVANCE_INST(1) @ advance before throw 902 b common_errNullObject 903 904/* ------------------------------ */ 905 .balign 64 906.L_OP_CHECK_CAST: /* 0x1f */ 907/* File: armv5te/OP_CHECK_CAST.S */ 908 /* 909 * Check to see if a cast from one class to another is allowed. 910 */ 911 /* check-cast vAA, class@BBBB */ 912 mov r3, rINST, lsr #8 @ r3<- AA 913 FETCH(r2, 1) @ r2<- BBBB 914 GET_VREG(r9, r3) @ r9<- object 915 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 916 cmp r9, #0 @ is object null? 917 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 918 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 919 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 920 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 921 cmp r1, #0 @ have we resolved this before? 922 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 923.LOP_CHECK_CAST_resolved: 924 cmp r0, r1 @ same class (trivial success)? 925 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 926.LOP_CHECK_CAST_okay: 927 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 928 GET_INST_OPCODE(ip) @ extract opcode from rINST 929 GOTO_OPCODE(ip) @ jump to next instruction 930 931/* ------------------------------ */ 932 .balign 64 933.L_OP_INSTANCE_OF: /* 0x20 */ 934/* File: armv5te/OP_INSTANCE_OF.S */ 935 /* 936 * Check to see if an object reference is an instance of a class. 937 * 938 * Most common situation is a non-null object, being compared against 939 * an already-resolved class. 940 */ 941 /* instance-of vA, vB, class@CCCC */ 942 mov r3, rINST, lsr #12 @ r3<- B 943 mov r9, rINST, lsr #8 @ r9<- A+ 944 GET_VREG(r0, r3) @ r0<- vB (object) 945 and r9, r9, #15 @ r9<- A 946 cmp r0, #0 @ is object null? 947 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 948 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 949 FETCH(r3, 1) @ r3<- CCCC 950 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 951 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 952 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 953 cmp r1, #0 @ have we resolved this before? 954 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 955.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 956 cmp r0, r1 @ same class (trivial success)? 957 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 958 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 959 960/* ------------------------------ */ 961 .balign 64 962.L_OP_ARRAY_LENGTH: /* 0x21 */ 963/* File: armv6t2/OP_ARRAY_LENGTH.S */ 964 /* 965 * Return the length of an array. 966 */ 967 mov r1, rINST, lsr #12 @ r1<- B 968 ubfx r2, rINST, #8, #4 @ r2<- A 969 GET_VREG(r0, r1) @ r0<- vB (object ref) 970 cmp r0, #0 @ is object null? 971 beq common_errNullObject @ yup, fail 972 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 973 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 974 GET_INST_OPCODE(ip) @ extract opcode from rINST 975 SET_VREG(r3, r2) @ vB<- length 976 GOTO_OPCODE(ip) @ jump to next instruction 977 978/* ------------------------------ */ 979 .balign 64 980.L_OP_NEW_INSTANCE: /* 0x22 */ 981/* File: armv5te/OP_NEW_INSTANCE.S */ 982 /* 983 * Create a new instance of a class. 984 */ 985 /* new-instance vAA, class@BBBB */ 986 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 987 FETCH(r1, 1) @ r1<- BBBB 988 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 989 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 990 EXPORT_PC() @ req'd for init, resolve, alloc 991 cmp r0, #0 @ already resolved? 992 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 993.LOP_NEW_INSTANCE_resolved: @ r0=class 994 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 995 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 996 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 997.LOP_NEW_INSTANCE_initialized: @ r0=class 998 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 999 bl dvmAllocObject @ r0<- new object 1000 b .LOP_NEW_INSTANCE_finish @ continue 1001 1002/* ------------------------------ */ 1003 .balign 64 1004.L_OP_NEW_ARRAY: /* 0x23 */ 1005/* File: armv5te/OP_NEW_ARRAY.S */ 1006 /* 1007 * Allocate an array of objects, specified with the array class 1008 * and a count. 1009 * 1010 * The verifier guarantees that this is an array class, so we don't 1011 * check for it here. 1012 */ 1013 /* new-array vA, vB, class@CCCC */ 1014 mov r0, rINST, lsr #12 @ r0<- B 1015 FETCH(r2, 1) @ r2<- CCCC 1016 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1017 GET_VREG(r1, r0) @ r1<- vB (array length) 1018 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1019 cmp r1, #0 @ check length 1020 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 1021 bmi common_errNegativeArraySize @ negative length, bail 1022 cmp r0, #0 @ already resolved? 1023 EXPORT_PC() @ req'd for resolve, alloc 1024 bne .LOP_NEW_ARRAY_finish @ resolved, continue 1025 b .LOP_NEW_ARRAY_resolve @ do resolve now 1026 1027/* ------------------------------ */ 1028 .balign 64 1029.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1030/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1031 /* 1032 * Create a new array with elements filled from registers. 1033 * 1034 * for: filled-new-array, filled-new-array/range 1035 */ 1036 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1037 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1038 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1039 FETCH(r1, 1) @ r1<- BBBB 1040 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1041 EXPORT_PC() @ need for resolve and alloc 1042 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1043 mov r10, rINST, lsr #8 @ r10<- AA or BA 1044 cmp r0, #0 @ already resolved? 1045 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10468: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1047 mov r2, #0 @ r2<- false 1048 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1049 bl dvmResolveClass @ r0<- call(clazz, ref) 1050 cmp r0, #0 @ got null? 1051 beq common_exceptionThrown @ yes, handle exception 1052 b .LOP_FILLED_NEW_ARRAY_continue 1053 1054/* ------------------------------ */ 1055 .balign 64 1056.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1057/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1058/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1059 /* 1060 * Create a new array with elements filled from registers. 1061 * 1062 * for: filled-new-array, filled-new-array/range 1063 */ 1064 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1065 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1066 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1067 FETCH(r1, 1) @ r1<- BBBB 1068 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1069 EXPORT_PC() @ need for resolve and alloc 1070 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1071 mov r10, rINST, lsr #8 @ r10<- AA or BA 1072 cmp r0, #0 @ already resolved? 1073 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10748: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1075 mov r2, #0 @ r2<- false 1076 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1077 bl dvmResolveClass @ r0<- call(clazz, ref) 1078 cmp r0, #0 @ got null? 1079 beq common_exceptionThrown @ yes, handle exception 1080 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1081 1082 1083/* ------------------------------ */ 1084 .balign 64 1085.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1086/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1087 /* fill-array-data vAA, +BBBBBBBB */ 1088 FETCH(r0, 1) @ r0<- bbbb (lo) 1089 FETCH(r1, 2) @ r1<- BBBB (hi) 1090 mov r3, rINST, lsr #8 @ r3<- AA 1091 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1092 GET_VREG(r0, r3) @ r0<- vAA (array object) 1093 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1094 EXPORT_PC(); 1095 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1096 cmp r0, #0 @ 0 means an exception is thrown 1097 beq common_exceptionThrown @ has exception 1098 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1099 GET_INST_OPCODE(ip) @ extract opcode from rINST 1100 GOTO_OPCODE(ip) @ jump to next instruction 1101 1102/* ------------------------------ */ 1103 .balign 64 1104.L_OP_THROW: /* 0x27 */ 1105/* File: armv5te/OP_THROW.S */ 1106 /* 1107 * Throw an exception object in the current thread. 1108 */ 1109 /* throw vAA */ 1110 mov r2, rINST, lsr #8 @ r2<- AA 1111 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1112 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1113 EXPORT_PC() @ exception handler can throw 1114 cmp r1, #0 @ null object? 1115 beq common_errNullObject @ yes, throw an NPE instead 1116 @ bypass dvmSetException, just store it 1117 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1118 b common_exceptionThrown 1119 1120/* ------------------------------ */ 1121 .balign 64 1122.L_OP_GOTO: /* 0x28 */ 1123/* File: armv5te/OP_GOTO.S */ 1124 /* 1125 * Unconditional branch, 8-bit offset. 1126 * 1127 * The branch distance is a signed code-unit offset, which we need to 1128 * double to get a byte offset. 1129 */ 1130 /* goto +AA */ 1131 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1132 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1133 mov r9, r9, lsl #1 @ r9<- byte offset 1134 bmi common_backwardBranch @ backward branch, do periodic checks 1135#if defined(WITH_JIT) 1136 GET_JIT_PROF_TABLE(r0) 1137 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1138 cmp r0,#0 1139 bne common_updateProfile 1140 GET_INST_OPCODE(ip) @ extract opcode from rINST 1141 GOTO_OPCODE(ip) @ jump to next instruction 1142#else 1143 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1144 GET_INST_OPCODE(ip) @ extract opcode from rINST 1145 GOTO_OPCODE(ip) @ jump to next instruction 1146#endif 1147 1148/* ------------------------------ */ 1149 .balign 64 1150.L_OP_GOTO_16: /* 0x29 */ 1151/* File: armv5te/OP_GOTO_16.S */ 1152 /* 1153 * Unconditional branch, 16-bit offset. 1154 * 1155 * The branch distance is a signed code-unit offset, which we need to 1156 * double to get a byte offset. 1157 */ 1158 /* goto/16 +AAAA */ 1159 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1160 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1161 bmi common_backwardBranch @ backward branch, do periodic checks 1162#if defined(WITH_JIT) 1163 GET_JIT_PROF_TABLE(r0) 1164 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1165 cmp r0,#0 1166 bne common_updateProfile 1167 GET_INST_OPCODE(ip) @ extract opcode from rINST 1168 GOTO_OPCODE(ip) @ jump to next instruction 1169#else 1170 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1171 GET_INST_OPCODE(ip) @ extract opcode from rINST 1172 GOTO_OPCODE(ip) @ jump to next instruction 1173#endif 1174 1175/* ------------------------------ */ 1176 .balign 64 1177.L_OP_GOTO_32: /* 0x2a */ 1178/* File: armv5te/OP_GOTO_32.S */ 1179 /* 1180 * Unconditional branch, 32-bit offset. 1181 * 1182 * The branch distance is a signed code-unit offset, which we need to 1183 * double to get a byte offset. 1184 * 1185 * Unlike most opcodes, this one is allowed to branch to itself, so 1186 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1187 * instruction doesn't affect the V flag, so we need to clear it 1188 * explicitly. 1189 */ 1190 /* goto/32 +AAAAAAAA */ 1191 FETCH(r0, 1) @ r0<- aaaa (lo) 1192 FETCH(r1, 2) @ r1<- AAAA (hi) 1193 cmp ip, ip @ (clear V flag during stall) 1194 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1195 mov r9, r0, asl #1 @ r9<- byte offset 1196 ble common_backwardBranch @ backward branch, do periodic checks 1197#if defined(WITH_JIT) 1198 GET_JIT_PROF_TABLE(r0) 1199 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1200 cmp r0,#0 1201 bne common_updateProfile 1202 GET_INST_OPCODE(ip) @ extract opcode from rINST 1203 GOTO_OPCODE(ip) @ jump to next instruction 1204#else 1205 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1206 GET_INST_OPCODE(ip) @ extract opcode from rINST 1207 GOTO_OPCODE(ip) @ jump to next instruction 1208#endif 1209 1210/* ------------------------------ */ 1211 .balign 64 1212.L_OP_PACKED_SWITCH: /* 0x2b */ 1213/* File: armv5te/OP_PACKED_SWITCH.S */ 1214 /* 1215 * Handle a packed-switch or sparse-switch instruction. In both cases 1216 * we decode it and hand it off to a helper function. 1217 * 1218 * We don't really expect backward branches in a switch statement, but 1219 * they're perfectly legal, so we check for them here. 1220 * 1221 * for: packed-switch, sparse-switch 1222 */ 1223 /* op vAA, +BBBB */ 1224 FETCH(r0, 1) @ r0<- bbbb (lo) 1225 FETCH(r1, 2) @ r1<- BBBB (hi) 1226 mov r3, rINST, lsr #8 @ r3<- AA 1227 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1228 GET_VREG(r1, r3) @ r1<- vAA 1229 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1230 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1231 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1232 bmi common_backwardBranch @ backward branch, do periodic checks 1233 beq common_backwardBranch @ (want to use BLE but V is unknown) 1234#if defined(WITH_JIT) 1235 GET_JIT_PROF_TABLE(r0) 1236 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1237 cmp r0,#0 1238 bne common_updateProfile 1239 GET_INST_OPCODE(ip) @ extract opcode from rINST 1240 GOTO_OPCODE(ip) @ jump to next instruction 1241#else 1242 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1243 GET_INST_OPCODE(ip) @ extract opcode from rINST 1244 GOTO_OPCODE(ip) @ jump to next instruction 1245#endif 1246 1247/* ------------------------------ */ 1248 .balign 64 1249.L_OP_SPARSE_SWITCH: /* 0x2c */ 1250/* File: armv5te/OP_SPARSE_SWITCH.S */ 1251/* File: armv5te/OP_PACKED_SWITCH.S */ 1252 /* 1253 * Handle a packed-switch or sparse-switch instruction. In both cases 1254 * we decode it and hand it off to a helper function. 1255 * 1256 * We don't really expect backward branches in a switch statement, but 1257 * they're perfectly legal, so we check for them here. 1258 * 1259 * for: packed-switch, sparse-switch 1260 */ 1261 /* op vAA, +BBBB */ 1262 FETCH(r0, 1) @ r0<- bbbb (lo) 1263 FETCH(r1, 2) @ r1<- BBBB (hi) 1264 mov r3, rINST, lsr #8 @ r3<- AA 1265 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1266 GET_VREG(r1, r3) @ r1<- vAA 1267 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1268 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1269 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1270 bmi common_backwardBranch @ backward branch, do periodic checks 1271 beq common_backwardBranch @ (want to use BLE but V is unknown) 1272#if defined(WITH_JIT) 1273 GET_JIT_PROF_TABLE(r0) 1274 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1275 cmp r0,#0 1276 bne common_updateProfile 1277 GET_INST_OPCODE(ip) @ extract opcode from rINST 1278 GOTO_OPCODE(ip) @ jump to next instruction 1279#else 1280 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1281 GET_INST_OPCODE(ip) @ extract opcode from rINST 1282 GOTO_OPCODE(ip) @ jump to next instruction 1283#endif 1284 1285 1286/* ------------------------------ */ 1287 .balign 64 1288.L_OP_CMPL_FLOAT: /* 0x2d */ 1289/* File: arm-vfp/OP_CMPL_FLOAT.S */ 1290 /* 1291 * Compare two floating-point values. Puts 0, 1, or -1 into the 1292 * destination register based on the results of the comparison. 1293 * 1294 * int compare(x, y) { 1295 * if (x == y) { 1296 * return 0; 1297 * } else if (x > y) { 1298 * return 1; 1299 * } else if (x < y) { 1300 * return -1; 1301 * } else { 1302 * return -1; 1303 * } 1304 * } 1305 */ 1306 /* op vAA, vBB, vCC */ 1307 FETCH(r0, 1) @ r0<- CCBB 1308 mov r9, rINST, lsr #8 @ r9<- AA 1309 and r2, r0, #255 @ r2<- BB 1310 mov r3, r0, lsr #8 @ r3<- CC 1311 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1312 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1313 flds s0, [r2] @ s0<- vBB 1314 flds s1, [r3] @ s1<- vCC 1315 fcmpes s0, s1 @ compare (vBB, vCC) 1316 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1317 mvn r0, #0 @ r0<- -1 (default) 1318 GET_INST_OPCODE(ip) @ extract opcode from rINST 1319 fmstat @ export status flags 1320 movgt r0, #1 @ (greater than) r1<- 1 1321 moveq r0, #0 @ (equal) r1<- 0 1322 b .LOP_CMPL_FLOAT_finish @ argh 1323 1324 1325/* ------------------------------ */ 1326 .balign 64 1327.L_OP_CMPG_FLOAT: /* 0x2e */ 1328/* File: arm-vfp/OP_CMPG_FLOAT.S */ 1329 /* 1330 * Compare two floating-point values. Puts 0, 1, or -1 into the 1331 * destination register based on the results of the comparison. 1332 * 1333 * int compare(x, y) { 1334 * if (x == y) { 1335 * return 0; 1336 * } else if (x < y) { 1337 * return -1; 1338 * } else if (x > y) { 1339 * return 1; 1340 * } else { 1341 * return 1; 1342 * } 1343 * } 1344 */ 1345 /* op vAA, vBB, vCC */ 1346 FETCH(r0, 1) @ r0<- CCBB 1347 mov r9, rINST, lsr #8 @ r9<- AA 1348 and r2, r0, #255 @ r2<- BB 1349 mov r3, r0, lsr #8 @ r3<- CC 1350 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1351 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1352 flds s0, [r2] @ s0<- vBB 1353 flds s1, [r3] @ s1<- vCC 1354 fcmpes s0, s1 @ compare (vBB, vCC) 1355 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1356 mov r0, #1 @ r0<- 1 (default) 1357 GET_INST_OPCODE(ip) @ extract opcode from rINST 1358 fmstat @ export status flags 1359 mvnmi r0, #0 @ (less than) r1<- -1 1360 moveq r0, #0 @ (equal) r1<- 0 1361 b .LOP_CMPG_FLOAT_finish @ argh 1362 1363 1364/* ------------------------------ */ 1365 .balign 64 1366.L_OP_CMPL_DOUBLE: /* 0x2f */ 1367/* File: arm-vfp/OP_CMPL_DOUBLE.S */ 1368 /* 1369 * Compare two floating-point values. Puts 0, 1, or -1 into the 1370 * destination register based on the results of the comparison. 1371 * 1372 * int compare(x, y) { 1373 * if (x == y) { 1374 * return 0; 1375 * } else if (x > y) { 1376 * return 1; 1377 * } else if (x < y) { 1378 * return -1; 1379 * } else { 1380 * return -1; 1381 * } 1382 * } 1383 */ 1384 /* op vAA, vBB, vCC */ 1385 FETCH(r0, 1) @ r0<- CCBB 1386 mov r9, rINST, lsr #8 @ r9<- AA 1387 and r2, r0, #255 @ r2<- BB 1388 mov r3, r0, lsr #8 @ r3<- CC 1389 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1390 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1391 fldd d0, [r2] @ d0<- vBB 1392 fldd d1, [r3] @ d1<- vCC 1393 fcmped d0, d1 @ compare (vBB, vCC) 1394 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1395 mvn r0, #0 @ r0<- -1 (default) 1396 GET_INST_OPCODE(ip) @ extract opcode from rINST 1397 fmstat @ export status flags 1398 movgt r0, #1 @ (greater than) r1<- 1 1399 moveq r0, #0 @ (equal) r1<- 0 1400 b .LOP_CMPL_DOUBLE_finish @ argh 1401 1402 1403/* ------------------------------ */ 1404 .balign 64 1405.L_OP_CMPG_DOUBLE: /* 0x30 */ 1406/* File: arm-vfp/OP_CMPG_DOUBLE.S */ 1407 /* 1408 * Compare two floating-point values. Puts 0, 1, or -1 into the 1409 * destination register based on the results of the comparison. 1410 * 1411 * int compare(x, y) { 1412 * if (x == y) { 1413 * return 0; 1414 * } else if (x < y) { 1415 * return -1; 1416 * } else if (x > y) { 1417 * return 1; 1418 * } else { 1419 * return 1; 1420 * } 1421 * } 1422 */ 1423 /* op vAA, vBB, vCC */ 1424 FETCH(r0, 1) @ r0<- CCBB 1425 mov r9, rINST, lsr #8 @ r9<- AA 1426 and r2, r0, #255 @ r2<- BB 1427 mov r3, r0, lsr #8 @ r3<- CC 1428 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1429 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1430 fldd d0, [r2] @ d0<- vBB 1431 fldd d1, [r3] @ d1<- vCC 1432 fcmped d0, d1 @ compare (vBB, vCC) 1433 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1434 mov r0, #1 @ r0<- 1 (default) 1435 GET_INST_OPCODE(ip) @ extract opcode from rINST 1436 fmstat @ export status flags 1437 mvnmi r0, #0 @ (less than) r1<- -1 1438 moveq r0, #0 @ (equal) r1<- 0 1439 b .LOP_CMPG_DOUBLE_finish @ argh 1440 1441 1442/* ------------------------------ */ 1443 .balign 64 1444.L_OP_CMP_LONG: /* 0x31 */ 1445/* File: armv5te/OP_CMP_LONG.S */ 1446 /* 1447 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1448 * register based on the results of the comparison. 1449 * 1450 * We load the full values with LDM, but in practice many values could 1451 * be resolved by only looking at the high word. This could be made 1452 * faster or slower by splitting the LDM into a pair of LDRs. 1453 * 1454 * If we just wanted to set condition flags, we could do this: 1455 * subs ip, r0, r2 1456 * sbcs ip, r1, r3 1457 * subeqs ip, r0, r2 1458 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1459 * integer value, which we can do with 2 conditional mov/mvn instructions 1460 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1461 * us a constant 5-cycle path plus a branch at the end to the 1462 * instruction epilogue code. The multi-compare approach below needs 1463 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1464 * in the worst case (the 64-bit values are equal). 1465 */ 1466 /* cmp-long vAA, vBB, vCC */ 1467 FETCH(r0, 1) @ r0<- CCBB 1468 mov r9, rINST, lsr #8 @ r9<- AA 1469 and r2, r0, #255 @ r2<- BB 1470 mov r3, r0, lsr #8 @ r3<- CC 1471 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1472 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1473 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1474 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1475 cmp r1, r3 @ compare (vBB+1, vCC+1) 1476 blt .LOP_CMP_LONG_less @ signed compare on high part 1477 bgt .LOP_CMP_LONG_greater 1478 subs r1, r0, r2 @ r1<- r0 - r2 1479 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1480 bne .LOP_CMP_LONG_less 1481 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1482 1483/* ------------------------------ */ 1484 .balign 64 1485.L_OP_IF_EQ: /* 0x32 */ 1486/* File: armv6t2/OP_IF_EQ.S */ 1487/* File: armv6t2/bincmp.S */ 1488 /* 1489 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1490 * fragment that specifies the *reverse* comparison to perform, e.g. 1491 * for "if-le" you would use "gt". 1492 * 1493 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1494 */ 1495 /* if-cmp vA, vB, +CCCC */ 1496 mov r1, rINST, lsr #12 @ r1<- B 1497 ubfx r0, rINST, #8, #4 @ r0<- A 1498 GET_VREG(r3, r1) @ r3<- vB 1499 GET_VREG(r2, r0) @ r2<- vA 1500 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1501 cmp r2, r3 @ compare (vA, vB) 1502 bne 1f @ branch to 1 if comparison failed 1503 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1504 movs r9, r9, asl #1 @ convert to bytes, check sign 1505 bmi common_backwardBranch @ yes, do periodic checks 15061: 1507#if defined(WITH_JIT) 1508 GET_JIT_PROF_TABLE(r0) 1509 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1510 b common_testUpdateProfile 1511#else 1512 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1513 GET_INST_OPCODE(ip) @ extract opcode from rINST 1514 GOTO_OPCODE(ip) @ jump to next instruction 1515#endif 1516 1517 1518/* ------------------------------ */ 1519 .balign 64 1520.L_OP_IF_NE: /* 0x33 */ 1521/* File: armv6t2/OP_IF_NE.S */ 1522/* File: armv6t2/bincmp.S */ 1523 /* 1524 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1525 * fragment that specifies the *reverse* comparison to perform, e.g. 1526 * for "if-le" you would use "gt". 1527 * 1528 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1529 */ 1530 /* if-cmp vA, vB, +CCCC */ 1531 mov r1, rINST, lsr #12 @ r1<- B 1532 ubfx r0, rINST, #8, #4 @ r0<- A 1533 GET_VREG(r3, r1) @ r3<- vB 1534 GET_VREG(r2, r0) @ r2<- vA 1535 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1536 cmp r2, r3 @ compare (vA, vB) 1537 beq 1f @ branch to 1 if comparison failed 1538 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1539 movs r9, r9, asl #1 @ convert to bytes, check sign 1540 bmi common_backwardBranch @ yes, do periodic checks 15411: 1542#if defined(WITH_JIT) 1543 GET_JIT_PROF_TABLE(r0) 1544 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1545 b common_testUpdateProfile 1546#else 1547 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1548 GET_INST_OPCODE(ip) @ extract opcode from rINST 1549 GOTO_OPCODE(ip) @ jump to next instruction 1550#endif 1551 1552 1553/* ------------------------------ */ 1554 .balign 64 1555.L_OP_IF_LT: /* 0x34 */ 1556/* File: armv6t2/OP_IF_LT.S */ 1557/* File: armv6t2/bincmp.S */ 1558 /* 1559 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1560 * fragment that specifies the *reverse* comparison to perform, e.g. 1561 * for "if-le" you would use "gt". 1562 * 1563 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1564 */ 1565 /* if-cmp vA, vB, +CCCC */ 1566 mov r1, rINST, lsr #12 @ r1<- B 1567 ubfx r0, rINST, #8, #4 @ r0<- A 1568 GET_VREG(r3, r1) @ r3<- vB 1569 GET_VREG(r2, r0) @ r2<- vA 1570 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1571 cmp r2, r3 @ compare (vA, vB) 1572 bge 1f @ branch to 1 if comparison failed 1573 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1574 movs r9, r9, asl #1 @ convert to bytes, check sign 1575 bmi common_backwardBranch @ yes, do periodic checks 15761: 1577#if defined(WITH_JIT) 1578 GET_JIT_PROF_TABLE(r0) 1579 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1580 b common_testUpdateProfile 1581#else 1582 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1583 GET_INST_OPCODE(ip) @ extract opcode from rINST 1584 GOTO_OPCODE(ip) @ jump to next instruction 1585#endif 1586 1587 1588/* ------------------------------ */ 1589 .balign 64 1590.L_OP_IF_GE: /* 0x35 */ 1591/* File: armv6t2/OP_IF_GE.S */ 1592/* File: armv6t2/bincmp.S */ 1593 /* 1594 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1595 * fragment that specifies the *reverse* comparison to perform, e.g. 1596 * for "if-le" you would use "gt". 1597 * 1598 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1599 */ 1600 /* if-cmp vA, vB, +CCCC */ 1601 mov r1, rINST, lsr #12 @ r1<- B 1602 ubfx r0, rINST, #8, #4 @ r0<- A 1603 GET_VREG(r3, r1) @ r3<- vB 1604 GET_VREG(r2, r0) @ r2<- vA 1605 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1606 cmp r2, r3 @ compare (vA, vB) 1607 blt 1f @ branch to 1 if comparison failed 1608 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1609 movs r9, r9, asl #1 @ convert to bytes, check sign 1610 bmi common_backwardBranch @ yes, do periodic checks 16111: 1612#if defined(WITH_JIT) 1613 GET_JIT_PROF_TABLE(r0) 1614 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1615 b common_testUpdateProfile 1616#else 1617 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1618 GET_INST_OPCODE(ip) @ extract opcode from rINST 1619 GOTO_OPCODE(ip) @ jump to next instruction 1620#endif 1621 1622 1623/* ------------------------------ */ 1624 .balign 64 1625.L_OP_IF_GT: /* 0x36 */ 1626/* File: armv6t2/OP_IF_GT.S */ 1627/* File: armv6t2/bincmp.S */ 1628 /* 1629 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1630 * fragment that specifies the *reverse* comparison to perform, e.g. 1631 * for "if-le" you would use "gt". 1632 * 1633 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1634 */ 1635 /* if-cmp vA, vB, +CCCC */ 1636 mov r1, rINST, lsr #12 @ r1<- B 1637 ubfx r0, rINST, #8, #4 @ r0<- A 1638 GET_VREG(r3, r1) @ r3<- vB 1639 GET_VREG(r2, r0) @ r2<- vA 1640 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1641 cmp r2, r3 @ compare (vA, vB) 1642 ble 1f @ branch to 1 if comparison failed 1643 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1644 movs r9, r9, asl #1 @ convert to bytes, check sign 1645 bmi common_backwardBranch @ yes, do periodic checks 16461: 1647#if defined(WITH_JIT) 1648 GET_JIT_PROF_TABLE(r0) 1649 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1650 b common_testUpdateProfile 1651#else 1652 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1653 GET_INST_OPCODE(ip) @ extract opcode from rINST 1654 GOTO_OPCODE(ip) @ jump to next instruction 1655#endif 1656 1657 1658/* ------------------------------ */ 1659 .balign 64 1660.L_OP_IF_LE: /* 0x37 */ 1661/* File: armv6t2/OP_IF_LE.S */ 1662/* File: armv6t2/bincmp.S */ 1663 /* 1664 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1665 * fragment that specifies the *reverse* comparison to perform, e.g. 1666 * for "if-le" you would use "gt". 1667 * 1668 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1669 */ 1670 /* if-cmp vA, vB, +CCCC */ 1671 mov r1, rINST, lsr #12 @ r1<- B 1672 ubfx r0, rINST, #8, #4 @ r0<- A 1673 GET_VREG(r3, r1) @ r3<- vB 1674 GET_VREG(r2, r0) @ r2<- vA 1675 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1676 cmp r2, r3 @ compare (vA, vB) 1677 bgt 1f @ branch to 1 if comparison failed 1678 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1679 movs r9, r9, asl #1 @ convert to bytes, check sign 1680 bmi common_backwardBranch @ yes, do periodic checks 16811: 1682#if defined(WITH_JIT) 1683 GET_JIT_PROF_TABLE(r0) 1684 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1685 b common_testUpdateProfile 1686#else 1687 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1688 GET_INST_OPCODE(ip) @ extract opcode from rINST 1689 GOTO_OPCODE(ip) @ jump to next instruction 1690#endif 1691 1692 1693/* ------------------------------ */ 1694 .balign 64 1695.L_OP_IF_EQZ: /* 0x38 */ 1696/* File: armv5te/OP_IF_EQZ.S */ 1697/* File: armv5te/zcmp.S */ 1698 /* 1699 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1700 * fragment that specifies the *reverse* comparison to perform, e.g. 1701 * for "if-le" you would use "gt". 1702 * 1703 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1704 */ 1705 /* if-cmp vAA, +BBBB */ 1706 mov r0, rINST, lsr #8 @ r0<- AA 1707 GET_VREG(r2, r0) @ r2<- vAA 1708 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1709 cmp r2, #0 @ compare (vA, 0) 1710 bne 1f @ branch to 1 if comparison failed 1711 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1712 movs r9, r9, asl #1 @ convert to bytes, check sign 1713 bmi common_backwardBranch @ backward branch, do periodic checks 17141: 1715#if defined(WITH_JIT) 1716 GET_JIT_PROF_TABLE(r0) 1717 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1718 cmp r0,#0 1719 bne common_updateProfile 1720 GET_INST_OPCODE(ip) @ extract opcode from rINST 1721 GOTO_OPCODE(ip) @ jump to next instruction 1722#else 1723 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1724 GET_INST_OPCODE(ip) @ extract opcode from rINST 1725 GOTO_OPCODE(ip) @ jump to next instruction 1726#endif 1727 1728 1729/* ------------------------------ */ 1730 .balign 64 1731.L_OP_IF_NEZ: /* 0x39 */ 1732/* File: armv5te/OP_IF_NEZ.S */ 1733/* File: armv5te/zcmp.S */ 1734 /* 1735 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1736 * fragment that specifies the *reverse* comparison to perform, e.g. 1737 * for "if-le" you would use "gt". 1738 * 1739 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1740 */ 1741 /* if-cmp vAA, +BBBB */ 1742 mov r0, rINST, lsr #8 @ r0<- AA 1743 GET_VREG(r2, r0) @ r2<- vAA 1744 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1745 cmp r2, #0 @ compare (vA, 0) 1746 beq 1f @ branch to 1 if comparison failed 1747 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1748 movs r9, r9, asl #1 @ convert to bytes, check sign 1749 bmi common_backwardBranch @ backward branch, do periodic checks 17501: 1751#if defined(WITH_JIT) 1752 GET_JIT_PROF_TABLE(r0) 1753 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1754 cmp r0,#0 1755 bne common_updateProfile 1756 GET_INST_OPCODE(ip) @ extract opcode from rINST 1757 GOTO_OPCODE(ip) @ jump to next instruction 1758#else 1759 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1760 GET_INST_OPCODE(ip) @ extract opcode from rINST 1761 GOTO_OPCODE(ip) @ jump to next instruction 1762#endif 1763 1764 1765/* ------------------------------ */ 1766 .balign 64 1767.L_OP_IF_LTZ: /* 0x3a */ 1768/* File: armv5te/OP_IF_LTZ.S */ 1769/* File: armv5te/zcmp.S */ 1770 /* 1771 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1772 * fragment that specifies the *reverse* comparison to perform, e.g. 1773 * for "if-le" you would use "gt". 1774 * 1775 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1776 */ 1777 /* if-cmp vAA, +BBBB */ 1778 mov r0, rINST, lsr #8 @ r0<- AA 1779 GET_VREG(r2, r0) @ r2<- vAA 1780 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1781 cmp r2, #0 @ compare (vA, 0) 1782 bge 1f @ branch to 1 if comparison failed 1783 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1784 movs r9, r9, asl #1 @ convert to bytes, check sign 1785 bmi common_backwardBranch @ backward branch, do periodic checks 17861: 1787#if defined(WITH_JIT) 1788 GET_JIT_PROF_TABLE(r0) 1789 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1790 cmp r0,#0 1791 bne common_updateProfile 1792 GET_INST_OPCODE(ip) @ extract opcode from rINST 1793 GOTO_OPCODE(ip) @ jump to next instruction 1794#else 1795 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1796 GET_INST_OPCODE(ip) @ extract opcode from rINST 1797 GOTO_OPCODE(ip) @ jump to next instruction 1798#endif 1799 1800 1801/* ------------------------------ */ 1802 .balign 64 1803.L_OP_IF_GEZ: /* 0x3b */ 1804/* File: armv5te/OP_IF_GEZ.S */ 1805/* File: armv5te/zcmp.S */ 1806 /* 1807 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1808 * fragment that specifies the *reverse* comparison to perform, e.g. 1809 * for "if-le" you would use "gt". 1810 * 1811 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1812 */ 1813 /* if-cmp vAA, +BBBB */ 1814 mov r0, rINST, lsr #8 @ r0<- AA 1815 GET_VREG(r2, r0) @ r2<- vAA 1816 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1817 cmp r2, #0 @ compare (vA, 0) 1818 blt 1f @ branch to 1 if comparison failed 1819 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1820 movs r9, r9, asl #1 @ convert to bytes, check sign 1821 bmi common_backwardBranch @ backward branch, do periodic checks 18221: 1823#if defined(WITH_JIT) 1824 GET_JIT_PROF_TABLE(r0) 1825 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1826 cmp r0,#0 1827 bne common_updateProfile 1828 GET_INST_OPCODE(ip) @ extract opcode from rINST 1829 GOTO_OPCODE(ip) @ jump to next instruction 1830#else 1831 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1832 GET_INST_OPCODE(ip) @ extract opcode from rINST 1833 GOTO_OPCODE(ip) @ jump to next instruction 1834#endif 1835 1836 1837/* ------------------------------ */ 1838 .balign 64 1839.L_OP_IF_GTZ: /* 0x3c */ 1840/* File: armv5te/OP_IF_GTZ.S */ 1841/* File: armv5te/zcmp.S */ 1842 /* 1843 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1844 * fragment that specifies the *reverse* comparison to perform, e.g. 1845 * for "if-le" you would use "gt". 1846 * 1847 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1848 */ 1849 /* if-cmp vAA, +BBBB */ 1850 mov r0, rINST, lsr #8 @ r0<- AA 1851 GET_VREG(r2, r0) @ r2<- vAA 1852 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1853 cmp r2, #0 @ compare (vA, 0) 1854 ble 1f @ branch to 1 if comparison failed 1855 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1856 movs r9, r9, asl #1 @ convert to bytes, check sign 1857 bmi common_backwardBranch @ backward branch, do periodic checks 18581: 1859#if defined(WITH_JIT) 1860 GET_JIT_PROF_TABLE(r0) 1861 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1862 cmp r0,#0 1863 bne common_updateProfile 1864 GET_INST_OPCODE(ip) @ extract opcode from rINST 1865 GOTO_OPCODE(ip) @ jump to next instruction 1866#else 1867 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1868 GET_INST_OPCODE(ip) @ extract opcode from rINST 1869 GOTO_OPCODE(ip) @ jump to next instruction 1870#endif 1871 1872 1873/* ------------------------------ */ 1874 .balign 64 1875.L_OP_IF_LEZ: /* 0x3d */ 1876/* File: armv5te/OP_IF_LEZ.S */ 1877/* File: armv5te/zcmp.S */ 1878 /* 1879 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1880 * fragment that specifies the *reverse* comparison to perform, e.g. 1881 * for "if-le" you would use "gt". 1882 * 1883 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1884 */ 1885 /* if-cmp vAA, +BBBB */ 1886 mov r0, rINST, lsr #8 @ r0<- AA 1887 GET_VREG(r2, r0) @ r2<- vAA 1888 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1889 cmp r2, #0 @ compare (vA, 0) 1890 bgt 1f @ branch to 1 if comparison failed 1891 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1892 movs r9, r9, asl #1 @ convert to bytes, check sign 1893 bmi common_backwardBranch @ backward branch, do periodic checks 18941: 1895#if defined(WITH_JIT) 1896 GET_JIT_PROF_TABLE(r0) 1897 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1898 cmp r0,#0 1899 bne common_updateProfile 1900 GET_INST_OPCODE(ip) @ extract opcode from rINST 1901 GOTO_OPCODE(ip) @ jump to next instruction 1902#else 1903 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1904 GET_INST_OPCODE(ip) @ extract opcode from rINST 1905 GOTO_OPCODE(ip) @ jump to next instruction 1906#endif 1907 1908 1909/* ------------------------------ */ 1910 .balign 64 1911.L_OP_UNUSED_3E: /* 0x3e */ 1912/* File: armv5te/OP_UNUSED_3E.S */ 1913/* File: armv5te/unused.S */ 1914 bl common_abort 1915 1916 1917/* ------------------------------ */ 1918 .balign 64 1919.L_OP_UNUSED_3F: /* 0x3f */ 1920/* File: armv5te/OP_UNUSED_3F.S */ 1921/* File: armv5te/unused.S */ 1922 bl common_abort 1923 1924 1925/* ------------------------------ */ 1926 .balign 64 1927.L_OP_UNUSED_40: /* 0x40 */ 1928/* File: armv5te/OP_UNUSED_40.S */ 1929/* File: armv5te/unused.S */ 1930 bl common_abort 1931 1932 1933/* ------------------------------ */ 1934 .balign 64 1935.L_OP_UNUSED_41: /* 0x41 */ 1936/* File: armv5te/OP_UNUSED_41.S */ 1937/* File: armv5te/unused.S */ 1938 bl common_abort 1939 1940 1941/* ------------------------------ */ 1942 .balign 64 1943.L_OP_UNUSED_42: /* 0x42 */ 1944/* File: armv5te/OP_UNUSED_42.S */ 1945/* File: armv5te/unused.S */ 1946 bl common_abort 1947 1948 1949/* ------------------------------ */ 1950 .balign 64 1951.L_OP_UNUSED_43: /* 0x43 */ 1952/* File: armv5te/OP_UNUSED_43.S */ 1953/* File: armv5te/unused.S */ 1954 bl common_abort 1955 1956 1957/* ------------------------------ */ 1958 .balign 64 1959.L_OP_AGET: /* 0x44 */ 1960/* File: armv5te/OP_AGET.S */ 1961 /* 1962 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1963 * 1964 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1965 * instructions. We use a pair of FETCH_Bs instead. 1966 * 1967 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1968 */ 1969 /* op vAA, vBB, vCC */ 1970 FETCH_B(r2, 1, 0) @ r2<- BB 1971 mov r9, rINST, lsr #8 @ r9<- AA 1972 FETCH_B(r3, 1, 1) @ r3<- CC 1973 GET_VREG(r0, r2) @ r0<- vBB (array object) 1974 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1975 cmp r0, #0 @ null array object? 1976 beq common_errNullObject @ yes, bail 1977 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1978 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 1979 cmp r1, r3 @ compare unsigned index, length 1980 bcs common_errArrayIndex @ index >= length, bail 1981 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1982 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 1983 GET_INST_OPCODE(ip) @ extract opcode from rINST 1984 SET_VREG(r2, r9) @ vAA<- r2 1985 GOTO_OPCODE(ip) @ jump to next instruction 1986 1987/* ------------------------------ */ 1988 .balign 64 1989.L_OP_AGET_WIDE: /* 0x45 */ 1990/* File: armv5te/OP_AGET_WIDE.S */ 1991 /* 1992 * Array get, 64 bits. vAA <- vBB[vCC]. 1993 * 1994 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 1995 */ 1996 /* aget-wide vAA, vBB, vCC */ 1997 FETCH(r0, 1) @ r0<- CCBB 1998 mov r9, rINST, lsr #8 @ r9<- AA 1999 and r2, r0, #255 @ r2<- BB 2000 mov r3, r0, lsr #8 @ r3<- CC 2001 GET_VREG(r0, r2) @ r0<- vBB (array object) 2002 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2003 cmp r0, #0 @ null array object? 2004 beq common_errNullObject @ yes, bail 2005 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2006 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2007 cmp r1, r3 @ compare unsigned index, length 2008 bcc .LOP_AGET_WIDE_finish @ okay, continue below 2009 b common_errArrayIndex @ index >= length, bail 2010 @ May want to swap the order of these two branches depending on how the 2011 @ branch prediction (if any) handles conditional forward branches vs. 2012 @ unconditional forward branches. 2013 2014/* ------------------------------ */ 2015 .balign 64 2016.L_OP_AGET_OBJECT: /* 0x46 */ 2017/* File: armv5te/OP_AGET_OBJECT.S */ 2018/* File: armv5te/OP_AGET.S */ 2019 /* 2020 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2021 * 2022 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2023 * instructions. We use a pair of FETCH_Bs instead. 2024 * 2025 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2026 */ 2027 /* op vAA, vBB, vCC */ 2028 FETCH_B(r2, 1, 0) @ r2<- BB 2029 mov r9, rINST, lsr #8 @ r9<- AA 2030 FETCH_B(r3, 1, 1) @ r3<- CC 2031 GET_VREG(r0, r2) @ r0<- vBB (array object) 2032 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2033 cmp r0, #0 @ null array object? 2034 beq common_errNullObject @ yes, bail 2035 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2036 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2037 cmp r1, r3 @ compare unsigned index, length 2038 bcs common_errArrayIndex @ index >= length, bail 2039 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2040 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2041 GET_INST_OPCODE(ip) @ extract opcode from rINST 2042 SET_VREG(r2, r9) @ vAA<- r2 2043 GOTO_OPCODE(ip) @ jump to next instruction 2044 2045 2046/* ------------------------------ */ 2047 .balign 64 2048.L_OP_AGET_BOOLEAN: /* 0x47 */ 2049/* File: armv5te/OP_AGET_BOOLEAN.S */ 2050/* File: armv5te/OP_AGET.S */ 2051 /* 2052 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2053 * 2054 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2055 * instructions. We use a pair of FETCH_Bs instead. 2056 * 2057 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2058 */ 2059 /* op vAA, vBB, vCC */ 2060 FETCH_B(r2, 1, 0) @ r2<- BB 2061 mov r9, rINST, lsr #8 @ r9<- AA 2062 FETCH_B(r3, 1, 1) @ r3<- CC 2063 GET_VREG(r0, r2) @ r0<- vBB (array object) 2064 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2065 cmp r0, #0 @ null array object? 2066 beq common_errNullObject @ yes, bail 2067 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2068 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2069 cmp r1, r3 @ compare unsigned index, length 2070 bcs common_errArrayIndex @ index >= length, bail 2071 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2072 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2073 GET_INST_OPCODE(ip) @ extract opcode from rINST 2074 SET_VREG(r2, r9) @ vAA<- r2 2075 GOTO_OPCODE(ip) @ jump to next instruction 2076 2077 2078/* ------------------------------ */ 2079 .balign 64 2080.L_OP_AGET_BYTE: /* 0x48 */ 2081/* File: armv5te/OP_AGET_BYTE.S */ 2082/* File: armv5te/OP_AGET.S */ 2083 /* 2084 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2085 * 2086 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2087 * instructions. We use a pair of FETCH_Bs instead. 2088 * 2089 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2090 */ 2091 /* op vAA, vBB, vCC */ 2092 FETCH_B(r2, 1, 0) @ r2<- BB 2093 mov r9, rINST, lsr #8 @ r9<- AA 2094 FETCH_B(r3, 1, 1) @ r3<- CC 2095 GET_VREG(r0, r2) @ r0<- vBB (array object) 2096 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2097 cmp r0, #0 @ null array object? 2098 beq common_errNullObject @ yes, bail 2099 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2100 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2101 cmp r1, r3 @ compare unsigned index, length 2102 bcs common_errArrayIndex @ index >= length, bail 2103 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2104 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2105 GET_INST_OPCODE(ip) @ extract opcode from rINST 2106 SET_VREG(r2, r9) @ vAA<- r2 2107 GOTO_OPCODE(ip) @ jump to next instruction 2108 2109 2110/* ------------------------------ */ 2111 .balign 64 2112.L_OP_AGET_CHAR: /* 0x49 */ 2113/* File: armv5te/OP_AGET_CHAR.S */ 2114/* File: armv5te/OP_AGET.S */ 2115 /* 2116 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2117 * 2118 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2119 * instructions. We use a pair of FETCH_Bs instead. 2120 * 2121 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2122 */ 2123 /* op vAA, vBB, vCC */ 2124 FETCH_B(r2, 1, 0) @ r2<- BB 2125 mov r9, rINST, lsr #8 @ r9<- AA 2126 FETCH_B(r3, 1, 1) @ r3<- CC 2127 GET_VREG(r0, r2) @ r0<- vBB (array object) 2128 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2129 cmp r0, #0 @ null array object? 2130 beq common_errNullObject @ yes, bail 2131 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2132 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2133 cmp r1, r3 @ compare unsigned index, length 2134 bcs common_errArrayIndex @ index >= length, bail 2135 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2136 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2137 GET_INST_OPCODE(ip) @ extract opcode from rINST 2138 SET_VREG(r2, r9) @ vAA<- r2 2139 GOTO_OPCODE(ip) @ jump to next instruction 2140 2141 2142/* ------------------------------ */ 2143 .balign 64 2144.L_OP_AGET_SHORT: /* 0x4a */ 2145/* File: armv5te/OP_AGET_SHORT.S */ 2146/* File: armv5te/OP_AGET.S */ 2147 /* 2148 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2149 * 2150 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2151 * instructions. We use a pair of FETCH_Bs instead. 2152 * 2153 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2154 */ 2155 /* op vAA, vBB, vCC */ 2156 FETCH_B(r2, 1, 0) @ r2<- BB 2157 mov r9, rINST, lsr #8 @ r9<- AA 2158 FETCH_B(r3, 1, 1) @ r3<- CC 2159 GET_VREG(r0, r2) @ r0<- vBB (array object) 2160 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2161 cmp r0, #0 @ null array object? 2162 beq common_errNullObject @ yes, bail 2163 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2164 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2165 cmp r1, r3 @ compare unsigned index, length 2166 bcs common_errArrayIndex @ index >= length, bail 2167 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2168 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2169 GET_INST_OPCODE(ip) @ extract opcode from rINST 2170 SET_VREG(r2, r9) @ vAA<- r2 2171 GOTO_OPCODE(ip) @ jump to next instruction 2172 2173 2174/* ------------------------------ */ 2175 .balign 64 2176.L_OP_APUT: /* 0x4b */ 2177/* File: armv5te/OP_APUT.S */ 2178 /* 2179 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2180 * 2181 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2182 * instructions. We use a pair of FETCH_Bs instead. 2183 * 2184 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2185 */ 2186 /* op vAA, vBB, vCC */ 2187 FETCH_B(r2, 1, 0) @ r2<- BB 2188 mov r9, rINST, lsr #8 @ r9<- AA 2189 FETCH_B(r3, 1, 1) @ r3<- CC 2190 GET_VREG(r0, r2) @ r0<- vBB (array object) 2191 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2192 cmp r0, #0 @ null array object? 2193 beq common_errNullObject @ yes, bail 2194 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2195 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2196 cmp r1, r3 @ compare unsigned index, length 2197 bcs common_errArrayIndex @ index >= length, bail 2198 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2199 GET_VREG(r2, r9) @ r2<- vAA 2200 GET_INST_OPCODE(ip) @ extract opcode from rINST 2201 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2202 GOTO_OPCODE(ip) @ jump to next instruction 2203 2204/* ------------------------------ */ 2205 .balign 64 2206.L_OP_APUT_WIDE: /* 0x4c */ 2207/* File: armv5te/OP_APUT_WIDE.S */ 2208 /* 2209 * Array put, 64 bits. vBB[vCC] <- vAA. 2210 * 2211 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 2212 */ 2213 /* aput-wide vAA, vBB, vCC */ 2214 FETCH(r0, 1) @ r0<- CCBB 2215 mov r9, rINST, lsr #8 @ r9<- AA 2216 and r2, r0, #255 @ r2<- BB 2217 mov r3, r0, lsr #8 @ r3<- CC 2218 GET_VREG(r0, r2) @ r0<- vBB (array object) 2219 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2220 cmp r0, #0 @ null array object? 2221 beq common_errNullObject @ yes, bail 2222 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2223 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2224 cmp r1, r3 @ compare unsigned index, length 2225 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2226 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2227 b common_errArrayIndex @ index >= length, bail 2228 @ May want to swap the order of these two branches depending on how the 2229 @ branch prediction (if any) handles conditional forward branches vs. 2230 @ unconditional forward branches. 2231 2232/* ------------------------------ */ 2233 .balign 64 2234.L_OP_APUT_OBJECT: /* 0x4d */ 2235/* File: armv5te/OP_APUT_OBJECT.S */ 2236 /* 2237 * Store an object into an array. vBB[vCC] <- vAA. 2238 */ 2239 /* op vAA, vBB, vCC */ 2240 FETCH(r0, 1) @ r0<- CCBB 2241 mov r9, rINST, lsr #8 @ r9<- AA 2242 and r2, r0, #255 @ r2<- BB 2243 mov r3, r0, lsr #8 @ r3<- CC 2244 GET_VREG(rINST, r2) @ rINST<- vBB (array object) 2245 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2246 cmp rINST, #0 @ null array object? 2247 GET_VREG(r9, r9) @ r9<- vAA 2248 beq common_errNullObject @ yes, bail 2249 ldr r3, [rINST, #offArrayObject_length] @ r3<- arrayObj->length 2250 add r10, rINST, r1, lsl #2 @ r10<- arrayObj + index*width 2251 cmp r1, r3 @ compare unsigned index, length 2252 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2253 b common_errArrayIndex @ index >= length, bail 2254 2255 2256/* ------------------------------ */ 2257 .balign 64 2258.L_OP_APUT_BOOLEAN: /* 0x4e */ 2259/* File: armv5te/OP_APUT_BOOLEAN.S */ 2260/* File: armv5te/OP_APUT.S */ 2261 /* 2262 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2263 * 2264 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2265 * instructions. We use a pair of FETCH_Bs instead. 2266 * 2267 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2268 */ 2269 /* op vAA, vBB, vCC */ 2270 FETCH_B(r2, 1, 0) @ r2<- BB 2271 mov r9, rINST, lsr #8 @ r9<- AA 2272 FETCH_B(r3, 1, 1) @ r3<- CC 2273 GET_VREG(r0, r2) @ r0<- vBB (array object) 2274 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2275 cmp r0, #0 @ null array object? 2276 beq common_errNullObject @ yes, bail 2277 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2278 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2279 cmp r1, r3 @ compare unsigned index, length 2280 bcs common_errArrayIndex @ index >= length, bail 2281 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2282 GET_VREG(r2, r9) @ r2<- vAA 2283 GET_INST_OPCODE(ip) @ extract opcode from rINST 2284 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2285 GOTO_OPCODE(ip) @ jump to next instruction 2286 2287 2288/* ------------------------------ */ 2289 .balign 64 2290.L_OP_APUT_BYTE: /* 0x4f */ 2291/* File: armv5te/OP_APUT_BYTE.S */ 2292/* File: armv5te/OP_APUT.S */ 2293 /* 2294 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2295 * 2296 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2297 * instructions. We use a pair of FETCH_Bs instead. 2298 * 2299 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2300 */ 2301 /* op vAA, vBB, vCC */ 2302 FETCH_B(r2, 1, 0) @ r2<- BB 2303 mov r9, rINST, lsr #8 @ r9<- AA 2304 FETCH_B(r3, 1, 1) @ r3<- CC 2305 GET_VREG(r0, r2) @ r0<- vBB (array object) 2306 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2307 cmp r0, #0 @ null array object? 2308 beq common_errNullObject @ yes, bail 2309 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2310 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2311 cmp r1, r3 @ compare unsigned index, length 2312 bcs common_errArrayIndex @ index >= length, bail 2313 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2314 GET_VREG(r2, r9) @ r2<- vAA 2315 GET_INST_OPCODE(ip) @ extract opcode from rINST 2316 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2317 GOTO_OPCODE(ip) @ jump to next instruction 2318 2319 2320/* ------------------------------ */ 2321 .balign 64 2322.L_OP_APUT_CHAR: /* 0x50 */ 2323/* File: armv5te/OP_APUT_CHAR.S */ 2324/* File: armv5te/OP_APUT.S */ 2325 /* 2326 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2327 * 2328 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2329 * instructions. We use a pair of FETCH_Bs instead. 2330 * 2331 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2332 */ 2333 /* op vAA, vBB, vCC */ 2334 FETCH_B(r2, 1, 0) @ r2<- BB 2335 mov r9, rINST, lsr #8 @ r9<- AA 2336 FETCH_B(r3, 1, 1) @ r3<- CC 2337 GET_VREG(r0, r2) @ r0<- vBB (array object) 2338 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2339 cmp r0, #0 @ null array object? 2340 beq common_errNullObject @ yes, bail 2341 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2342 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2343 cmp r1, r3 @ compare unsigned index, length 2344 bcs common_errArrayIndex @ index >= length, bail 2345 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2346 GET_VREG(r2, r9) @ r2<- vAA 2347 GET_INST_OPCODE(ip) @ extract opcode from rINST 2348 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2349 GOTO_OPCODE(ip) @ jump to next instruction 2350 2351 2352/* ------------------------------ */ 2353 .balign 64 2354.L_OP_APUT_SHORT: /* 0x51 */ 2355/* File: armv5te/OP_APUT_SHORT.S */ 2356/* File: armv5te/OP_APUT.S */ 2357 /* 2358 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2359 * 2360 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2361 * instructions. We use a pair of FETCH_Bs instead. 2362 * 2363 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2364 */ 2365 /* op vAA, vBB, vCC */ 2366 FETCH_B(r2, 1, 0) @ r2<- BB 2367 mov r9, rINST, lsr #8 @ r9<- AA 2368 FETCH_B(r3, 1, 1) @ r3<- CC 2369 GET_VREG(r0, r2) @ r0<- vBB (array object) 2370 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2371 cmp r0, #0 @ null array object? 2372 beq common_errNullObject @ yes, bail 2373 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2374 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2375 cmp r1, r3 @ compare unsigned index, length 2376 bcs common_errArrayIndex @ index >= length, bail 2377 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2378 GET_VREG(r2, r9) @ r2<- vAA 2379 GET_INST_OPCODE(ip) @ extract opcode from rINST 2380 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2381 GOTO_OPCODE(ip) @ jump to next instruction 2382 2383 2384/* ------------------------------ */ 2385 .balign 64 2386.L_OP_IGET: /* 0x52 */ 2387/* File: armv6t2/OP_IGET.S */ 2388 /* 2389 * General 32-bit instance field get. 2390 * 2391 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2392 */ 2393 /* op vA, vB, field@CCCC */ 2394 mov r0, rINST, lsr #12 @ r0<- B 2395 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2396 FETCH(r1, 1) @ r1<- field ref CCCC 2397 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2398 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2399 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2400 cmp r0, #0 @ is resolved entry null? 2401 bne .LOP_IGET_finish @ no, already resolved 24028: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2403 EXPORT_PC() @ resolve() could throw 2404 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2405 bl dvmResolveInstField @ r0<- resolved InstField ptr 2406 cmp r0, #0 2407 bne .LOP_IGET_finish 2408 b common_exceptionThrown 2409 2410/* ------------------------------ */ 2411 .balign 64 2412.L_OP_IGET_WIDE: /* 0x53 */ 2413/* File: armv6t2/OP_IGET_WIDE.S */ 2414 /* 2415 * Wide 32-bit instance field get. 2416 */ 2417 /* iget-wide vA, vB, field@CCCC */ 2418 mov r0, rINST, lsr #12 @ r0<- B 2419 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2420 FETCH(r1, 1) @ r1<- field ref CCCC 2421 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2422 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2423 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2424 cmp r0, #0 @ is resolved entry null? 2425 bne .LOP_IGET_WIDE_finish @ no, already resolved 24268: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2427 EXPORT_PC() @ resolve() could throw 2428 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2429 bl dvmResolveInstField @ r0<- resolved InstField ptr 2430 cmp r0, #0 2431 bne .LOP_IGET_WIDE_finish 2432 b common_exceptionThrown 2433 2434/* ------------------------------ */ 2435 .balign 64 2436.L_OP_IGET_OBJECT: /* 0x54 */ 2437/* File: armv5te/OP_IGET_OBJECT.S */ 2438/* File: armv5te/OP_IGET.S */ 2439 /* 2440 * General 32-bit instance field get. 2441 * 2442 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2443 */ 2444 /* op vA, vB, field@CCCC */ 2445 mov r0, rINST, lsr #12 @ r0<- B 2446 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2447 FETCH(r1, 1) @ r1<- field ref CCCC 2448 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2449 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2450 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2451 cmp r0, #0 @ is resolved entry null? 2452 bne .LOP_IGET_OBJECT_finish @ no, already resolved 24538: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2454 EXPORT_PC() @ resolve() could throw 2455 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2456 bl dvmResolveInstField @ r0<- resolved InstField ptr 2457 cmp r0, #0 2458 bne .LOP_IGET_OBJECT_finish 2459 b common_exceptionThrown 2460 2461 2462/* ------------------------------ */ 2463 .balign 64 2464.L_OP_IGET_BOOLEAN: /* 0x55 */ 2465/* File: armv5te/OP_IGET_BOOLEAN.S */ 2466@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2467/* File: armv5te/OP_IGET.S */ 2468 /* 2469 * General 32-bit instance field get. 2470 * 2471 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2472 */ 2473 /* op vA, vB, field@CCCC */ 2474 mov r0, rINST, lsr #12 @ r0<- B 2475 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2476 FETCH(r1, 1) @ r1<- field ref CCCC 2477 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2478 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2479 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2480 cmp r0, #0 @ is resolved entry null? 2481 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 24828: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2483 EXPORT_PC() @ resolve() could throw 2484 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2485 bl dvmResolveInstField @ r0<- resolved InstField ptr 2486 cmp r0, #0 2487 bne .LOP_IGET_BOOLEAN_finish 2488 b common_exceptionThrown 2489 2490 2491/* ------------------------------ */ 2492 .balign 64 2493.L_OP_IGET_BYTE: /* 0x56 */ 2494/* File: armv5te/OP_IGET_BYTE.S */ 2495@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2496/* File: armv5te/OP_IGET.S */ 2497 /* 2498 * General 32-bit instance field get. 2499 * 2500 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2501 */ 2502 /* op vA, vB, field@CCCC */ 2503 mov r0, rINST, lsr #12 @ r0<- B 2504 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2505 FETCH(r1, 1) @ r1<- field ref CCCC 2506 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2507 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2508 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2509 cmp r0, #0 @ is resolved entry null? 2510 bne .LOP_IGET_BYTE_finish @ no, already resolved 25118: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2512 EXPORT_PC() @ resolve() could throw 2513 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2514 bl dvmResolveInstField @ r0<- resolved InstField ptr 2515 cmp r0, #0 2516 bne .LOP_IGET_BYTE_finish 2517 b common_exceptionThrown 2518 2519 2520/* ------------------------------ */ 2521 .balign 64 2522.L_OP_IGET_CHAR: /* 0x57 */ 2523/* File: armv5te/OP_IGET_CHAR.S */ 2524@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2525/* File: armv5te/OP_IGET.S */ 2526 /* 2527 * General 32-bit instance field get. 2528 * 2529 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2530 */ 2531 /* op vA, vB, field@CCCC */ 2532 mov r0, rINST, lsr #12 @ r0<- B 2533 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2534 FETCH(r1, 1) @ r1<- field ref CCCC 2535 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2536 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2537 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2538 cmp r0, #0 @ is resolved entry null? 2539 bne .LOP_IGET_CHAR_finish @ no, already resolved 25408: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2541 EXPORT_PC() @ resolve() could throw 2542 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2543 bl dvmResolveInstField @ r0<- resolved InstField ptr 2544 cmp r0, #0 2545 bne .LOP_IGET_CHAR_finish 2546 b common_exceptionThrown 2547 2548 2549/* ------------------------------ */ 2550 .balign 64 2551.L_OP_IGET_SHORT: /* 0x58 */ 2552/* File: armv5te/OP_IGET_SHORT.S */ 2553@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2554/* File: armv5te/OP_IGET.S */ 2555 /* 2556 * General 32-bit instance field get. 2557 * 2558 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2559 */ 2560 /* op vA, vB, field@CCCC */ 2561 mov r0, rINST, lsr #12 @ r0<- B 2562 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2563 FETCH(r1, 1) @ r1<- field ref CCCC 2564 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2565 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2566 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2567 cmp r0, #0 @ is resolved entry null? 2568 bne .LOP_IGET_SHORT_finish @ no, already resolved 25698: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2570 EXPORT_PC() @ resolve() could throw 2571 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2572 bl dvmResolveInstField @ r0<- resolved InstField ptr 2573 cmp r0, #0 2574 bne .LOP_IGET_SHORT_finish 2575 b common_exceptionThrown 2576 2577 2578/* ------------------------------ */ 2579 .balign 64 2580.L_OP_IPUT: /* 0x59 */ 2581/* File: armv6t2/OP_IPUT.S */ 2582 /* 2583 * General 32-bit instance field put. 2584 * 2585 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2586 */ 2587 /* op vA, vB, field@CCCC */ 2588 mov r0, rINST, lsr #12 @ r0<- B 2589 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2590 FETCH(r1, 1) @ r1<- field ref CCCC 2591 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2592 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2593 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2594 cmp r0, #0 @ is resolved entry null? 2595 bne .LOP_IPUT_finish @ no, already resolved 25968: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2597 EXPORT_PC() @ resolve() could throw 2598 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2599 bl dvmResolveInstField @ r0<- resolved InstField ptr 2600 cmp r0, #0 @ success? 2601 bne .LOP_IPUT_finish @ yes, finish up 2602 b common_exceptionThrown 2603 2604/* ------------------------------ */ 2605 .balign 64 2606.L_OP_IPUT_WIDE: /* 0x5a */ 2607/* File: armv6t2/OP_IPUT_WIDE.S */ 2608 /* iput-wide vA, vB, field@CCCC */ 2609 mov r0, rINST, lsr #12 @ r0<- B 2610 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2611 FETCH(r1, 1) @ r1<- field ref CCCC 2612 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2613 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2614 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2615 cmp r0, #0 @ is resolved entry null? 2616 bne .LOP_IPUT_WIDE_finish @ no, already resolved 26178: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2618 EXPORT_PC() @ resolve() could throw 2619 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2620 bl dvmResolveInstField @ r0<- resolved InstField ptr 2621 cmp r0, #0 @ success? 2622 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2623 b common_exceptionThrown 2624 2625/* ------------------------------ */ 2626 .balign 64 2627.L_OP_IPUT_OBJECT: /* 0x5b */ 2628/* File: armv5te/OP_IPUT_OBJECT.S */ 2629 /* 2630 * 32-bit instance field put. 2631 * 2632 * for: iput-object, iput-object-volatile 2633 */ 2634 /* op vA, vB, field@CCCC */ 2635 mov r0, rINST, lsr #12 @ r0<- B 2636 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2637 FETCH(r1, 1) @ r1<- field ref CCCC 2638 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2639 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2640 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2641 cmp r0, #0 @ is resolved entry null? 2642 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 26438: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2644 EXPORT_PC() @ resolve() could throw 2645 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2646 bl dvmResolveInstField @ r0<- resolved InstField ptr 2647 cmp r0, #0 @ success? 2648 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2649 b common_exceptionThrown 2650 2651/* ------------------------------ */ 2652 .balign 64 2653.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2654/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2655@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2656/* File: armv5te/OP_IPUT.S */ 2657 /* 2658 * General 32-bit instance field put. 2659 * 2660 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2661 */ 2662 /* op vA, vB, field@CCCC */ 2663 mov r0, rINST, lsr #12 @ r0<- B 2664 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2665 FETCH(r1, 1) @ r1<- field ref CCCC 2666 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2667 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2668 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2669 cmp r0, #0 @ is resolved entry null? 2670 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 26718: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2672 EXPORT_PC() @ resolve() could throw 2673 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2674 bl dvmResolveInstField @ r0<- resolved InstField ptr 2675 cmp r0, #0 @ success? 2676 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2677 b common_exceptionThrown 2678 2679 2680/* ------------------------------ */ 2681 .balign 64 2682.L_OP_IPUT_BYTE: /* 0x5d */ 2683/* File: armv5te/OP_IPUT_BYTE.S */ 2684@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2685/* File: armv5te/OP_IPUT.S */ 2686 /* 2687 * General 32-bit instance field put. 2688 * 2689 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2690 */ 2691 /* op vA, vB, field@CCCC */ 2692 mov r0, rINST, lsr #12 @ r0<- B 2693 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2694 FETCH(r1, 1) @ r1<- field ref CCCC 2695 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2696 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2697 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2698 cmp r0, #0 @ is resolved entry null? 2699 bne .LOP_IPUT_BYTE_finish @ no, already resolved 27008: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2701 EXPORT_PC() @ resolve() could throw 2702 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2703 bl dvmResolveInstField @ r0<- resolved InstField ptr 2704 cmp r0, #0 @ success? 2705 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2706 b common_exceptionThrown 2707 2708 2709/* ------------------------------ */ 2710 .balign 64 2711.L_OP_IPUT_CHAR: /* 0x5e */ 2712/* File: armv5te/OP_IPUT_CHAR.S */ 2713@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2714/* File: armv5te/OP_IPUT.S */ 2715 /* 2716 * General 32-bit instance field put. 2717 * 2718 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2719 */ 2720 /* op vA, vB, field@CCCC */ 2721 mov r0, rINST, lsr #12 @ r0<- B 2722 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2723 FETCH(r1, 1) @ r1<- field ref CCCC 2724 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2725 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2726 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2727 cmp r0, #0 @ is resolved entry null? 2728 bne .LOP_IPUT_CHAR_finish @ no, already resolved 27298: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2730 EXPORT_PC() @ resolve() could throw 2731 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2732 bl dvmResolveInstField @ r0<- resolved InstField ptr 2733 cmp r0, #0 @ success? 2734 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2735 b common_exceptionThrown 2736 2737 2738/* ------------------------------ */ 2739 .balign 64 2740.L_OP_IPUT_SHORT: /* 0x5f */ 2741/* File: armv5te/OP_IPUT_SHORT.S */ 2742@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2743/* File: armv5te/OP_IPUT.S */ 2744 /* 2745 * General 32-bit instance field put. 2746 * 2747 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2748 */ 2749 /* op vA, vB, field@CCCC */ 2750 mov r0, rINST, lsr #12 @ r0<- B 2751 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2752 FETCH(r1, 1) @ r1<- field ref CCCC 2753 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2754 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2755 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2756 cmp r0, #0 @ is resolved entry null? 2757 bne .LOP_IPUT_SHORT_finish @ no, already resolved 27588: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2759 EXPORT_PC() @ resolve() could throw 2760 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2761 bl dvmResolveInstField @ r0<- resolved InstField ptr 2762 cmp r0, #0 @ success? 2763 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2764 b common_exceptionThrown 2765 2766 2767/* ------------------------------ */ 2768 .balign 64 2769.L_OP_SGET: /* 0x60 */ 2770/* File: armv5te/OP_SGET.S */ 2771 /* 2772 * General 32-bit SGET handler. 2773 * 2774 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2775 */ 2776 /* op vAA, field@BBBB */ 2777 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2778 FETCH(r1, 1) @ r1<- field ref BBBB 2779 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2780 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2781 cmp r0, #0 @ is resolved entry null? 2782 beq .LOP_SGET_resolve @ yes, do resolve 2783.LOP_SGET_finish: @ field ptr in r0 2784 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2785 @ no-op @ acquiring load 2786 mov r2, rINST, lsr #8 @ r2<- AA 2787 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2788 SET_VREG(r1, r2) @ fp[AA]<- r1 2789 GET_INST_OPCODE(ip) @ extract opcode from rINST 2790 GOTO_OPCODE(ip) @ jump to next instruction 2791 2792/* ------------------------------ */ 2793 .balign 64 2794.L_OP_SGET_WIDE: /* 0x61 */ 2795/* File: armv5te/OP_SGET_WIDE.S */ 2796 /* 2797 * 64-bit SGET handler. 2798 */ 2799 /* sget-wide vAA, field@BBBB */ 2800 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2801 FETCH(r1, 1) @ r1<- field ref BBBB 2802 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2803 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2804 cmp r0, #0 @ is resolved entry null? 2805 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2806.LOP_SGET_WIDE_finish: 2807 mov r9, rINST, lsr #8 @ r9<- AA 2808 .if 0 2809 add r0, r0, #offStaticField_value @ r0<- pointer to data 2810 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 2811 .else 2812 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 2813 .endif 2814 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2815 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2816 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 2817 GET_INST_OPCODE(ip) @ extract opcode from rINST 2818 GOTO_OPCODE(ip) @ jump to next instruction 2819 2820/* ------------------------------ */ 2821 .balign 64 2822.L_OP_SGET_OBJECT: /* 0x62 */ 2823/* File: armv5te/OP_SGET_OBJECT.S */ 2824/* File: armv5te/OP_SGET.S */ 2825 /* 2826 * General 32-bit SGET handler. 2827 * 2828 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2829 */ 2830 /* op vAA, field@BBBB */ 2831 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2832 FETCH(r1, 1) @ r1<- field ref BBBB 2833 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2834 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2835 cmp r0, #0 @ is resolved entry null? 2836 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2837.LOP_SGET_OBJECT_finish: @ field ptr in r0 2838 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2839 @ no-op @ acquiring load 2840 mov r2, rINST, lsr #8 @ r2<- AA 2841 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2842 SET_VREG(r1, r2) @ fp[AA]<- r1 2843 GET_INST_OPCODE(ip) @ extract opcode from rINST 2844 GOTO_OPCODE(ip) @ jump to next instruction 2845 2846 2847/* ------------------------------ */ 2848 .balign 64 2849.L_OP_SGET_BOOLEAN: /* 0x63 */ 2850/* File: armv5te/OP_SGET_BOOLEAN.S */ 2851/* File: armv5te/OP_SGET.S */ 2852 /* 2853 * General 32-bit SGET handler. 2854 * 2855 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2856 */ 2857 /* op vAA, field@BBBB */ 2858 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2859 FETCH(r1, 1) @ r1<- field ref BBBB 2860 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2861 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2862 cmp r0, #0 @ is resolved entry null? 2863 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2864.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2865 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2866 @ no-op @ acquiring load 2867 mov r2, rINST, lsr #8 @ r2<- AA 2868 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2869 SET_VREG(r1, r2) @ fp[AA]<- r1 2870 GET_INST_OPCODE(ip) @ extract opcode from rINST 2871 GOTO_OPCODE(ip) @ jump to next instruction 2872 2873 2874/* ------------------------------ */ 2875 .balign 64 2876.L_OP_SGET_BYTE: /* 0x64 */ 2877/* File: armv5te/OP_SGET_BYTE.S */ 2878/* File: armv5te/OP_SGET.S */ 2879 /* 2880 * General 32-bit SGET handler. 2881 * 2882 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2883 */ 2884 /* op vAA, field@BBBB */ 2885 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2886 FETCH(r1, 1) @ r1<- field ref BBBB 2887 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2888 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2889 cmp r0, #0 @ is resolved entry null? 2890 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2891.LOP_SGET_BYTE_finish: @ field ptr in r0 2892 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2893 @ no-op @ acquiring load 2894 mov r2, rINST, lsr #8 @ r2<- AA 2895 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2896 SET_VREG(r1, r2) @ fp[AA]<- r1 2897 GET_INST_OPCODE(ip) @ extract opcode from rINST 2898 GOTO_OPCODE(ip) @ jump to next instruction 2899 2900 2901/* ------------------------------ */ 2902 .balign 64 2903.L_OP_SGET_CHAR: /* 0x65 */ 2904/* File: armv5te/OP_SGET_CHAR.S */ 2905/* File: armv5te/OP_SGET.S */ 2906 /* 2907 * General 32-bit SGET handler. 2908 * 2909 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2910 */ 2911 /* op vAA, field@BBBB */ 2912 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2913 FETCH(r1, 1) @ r1<- field ref BBBB 2914 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2915 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2916 cmp r0, #0 @ is resolved entry null? 2917 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2918.LOP_SGET_CHAR_finish: @ field ptr in r0 2919 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2920 @ no-op @ acquiring load 2921 mov r2, rINST, lsr #8 @ r2<- AA 2922 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2923 SET_VREG(r1, r2) @ fp[AA]<- r1 2924 GET_INST_OPCODE(ip) @ extract opcode from rINST 2925 GOTO_OPCODE(ip) @ jump to next instruction 2926 2927 2928/* ------------------------------ */ 2929 .balign 64 2930.L_OP_SGET_SHORT: /* 0x66 */ 2931/* File: armv5te/OP_SGET_SHORT.S */ 2932/* File: armv5te/OP_SGET.S */ 2933 /* 2934 * General 32-bit SGET handler. 2935 * 2936 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2937 */ 2938 /* op vAA, field@BBBB */ 2939 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2940 FETCH(r1, 1) @ r1<- field ref BBBB 2941 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2942 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2943 cmp r0, #0 @ is resolved entry null? 2944 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 2945.LOP_SGET_SHORT_finish: @ field ptr in r0 2946 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2947 @ no-op @ acquiring load 2948 mov r2, rINST, lsr #8 @ r2<- AA 2949 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2950 SET_VREG(r1, r2) @ fp[AA]<- r1 2951 GET_INST_OPCODE(ip) @ extract opcode from rINST 2952 GOTO_OPCODE(ip) @ jump to next instruction 2953 2954 2955/* ------------------------------ */ 2956 .balign 64 2957.L_OP_SPUT: /* 0x67 */ 2958/* File: armv5te/OP_SPUT.S */ 2959 /* 2960 * General 32-bit SPUT handler. 2961 * 2962 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 2963 */ 2964 /* op vAA, field@BBBB */ 2965 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2966 FETCH(r1, 1) @ r1<- field ref BBBB 2967 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2968 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2969 cmp r0, #0 @ is resolved entry null? 2970 beq .LOP_SPUT_resolve @ yes, do resolve 2971.LOP_SPUT_finish: @ field ptr in r0 2972 mov r2, rINST, lsr #8 @ r2<- AA 2973 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2974 GET_VREG(r1, r2) @ r1<- fp[AA] 2975 GET_INST_OPCODE(ip) @ extract opcode from rINST 2976 @ no-op @ releasing store 2977 str r1, [r0, #offStaticField_value] @ field<- vAA 2978 GOTO_OPCODE(ip) @ jump to next instruction 2979 2980/* ------------------------------ */ 2981 .balign 64 2982.L_OP_SPUT_WIDE: /* 0x68 */ 2983/* File: armv5te/OP_SPUT_WIDE.S */ 2984 /* 2985 * 64-bit SPUT handler. 2986 */ 2987 /* sput-wide vAA, field@BBBB */ 2988 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 2989 FETCH(r1, 1) @ r1<- field ref BBBB 2990 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 2991 mov r9, rINST, lsr #8 @ r9<- AA 2992 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 2993 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2994 cmp r2, #0 @ is resolved entry null? 2995 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 2996.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9 2997 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2998 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 2999 GET_INST_OPCODE(r10) @ extract opcode from rINST 3000 .if 0 3001 add r2, r2, #offStaticField_value @ r2<- pointer to data 3002 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 3003 .else 3004 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 3005 .endif 3006 GOTO_OPCODE(r10) @ jump to next instruction 3007 3008/* ------------------------------ */ 3009 .balign 64 3010.L_OP_SPUT_OBJECT: /* 0x69 */ 3011/* File: armv5te/OP_SPUT_OBJECT.S */ 3012 /* 3013 * 32-bit SPUT handler for objects 3014 * 3015 * for: sput-object, sput-object-volatile 3016 */ 3017 /* op vAA, field@BBBB */ 3018 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3019 FETCH(r1, 1) @ r1<- field ref BBBB 3020 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3021 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3022 cmp r0, #0 @ is resolved entry null? 3023 bne .LOP_SPUT_OBJECT_finish @ no, continue 3024 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3025 EXPORT_PC() @ resolve() could throw, so export now 3026 ldr r0, [r9, #offMethod_clazz] @ r0<- method->clazz 3027 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 3028 cmp r0, #0 @ success? 3029 bne .LOP_SPUT_OBJECT_finish @ yes, finish 3030 b common_exceptionThrown @ no, handle exception 3031 3032 3033/* ------------------------------ */ 3034 .balign 64 3035.L_OP_SPUT_BOOLEAN: /* 0x6a */ 3036/* File: armv5te/OP_SPUT_BOOLEAN.S */ 3037/* File: armv5te/OP_SPUT.S */ 3038 /* 3039 * General 32-bit SPUT handler. 3040 * 3041 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3042 */ 3043 /* op vAA, field@BBBB */ 3044 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3045 FETCH(r1, 1) @ r1<- field ref BBBB 3046 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3047 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3048 cmp r0, #0 @ is resolved entry null? 3049 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 3050.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 3051 mov r2, rINST, lsr #8 @ r2<- AA 3052 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3053 GET_VREG(r1, r2) @ r1<- fp[AA] 3054 GET_INST_OPCODE(ip) @ extract opcode from rINST 3055 @ no-op @ releasing store 3056 str r1, [r0, #offStaticField_value] @ field<- vAA 3057 GOTO_OPCODE(ip) @ jump to next instruction 3058 3059 3060/* ------------------------------ */ 3061 .balign 64 3062.L_OP_SPUT_BYTE: /* 0x6b */ 3063/* File: armv5te/OP_SPUT_BYTE.S */ 3064/* File: armv5te/OP_SPUT.S */ 3065 /* 3066 * General 32-bit SPUT handler. 3067 * 3068 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3069 */ 3070 /* op vAA, field@BBBB */ 3071 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3072 FETCH(r1, 1) @ r1<- field ref BBBB 3073 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3074 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3075 cmp r0, #0 @ is resolved entry null? 3076 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 3077.LOP_SPUT_BYTE_finish: @ field ptr in r0 3078 mov r2, rINST, lsr #8 @ r2<- AA 3079 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3080 GET_VREG(r1, r2) @ r1<- fp[AA] 3081 GET_INST_OPCODE(ip) @ extract opcode from rINST 3082 @ no-op @ releasing store 3083 str r1, [r0, #offStaticField_value] @ field<- vAA 3084 GOTO_OPCODE(ip) @ jump to next instruction 3085 3086 3087/* ------------------------------ */ 3088 .balign 64 3089.L_OP_SPUT_CHAR: /* 0x6c */ 3090/* File: armv5te/OP_SPUT_CHAR.S */ 3091/* File: armv5te/OP_SPUT.S */ 3092 /* 3093 * General 32-bit SPUT handler. 3094 * 3095 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3096 */ 3097 /* op vAA, field@BBBB */ 3098 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3099 FETCH(r1, 1) @ r1<- field ref BBBB 3100 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3101 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3102 cmp r0, #0 @ is resolved entry null? 3103 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 3104.LOP_SPUT_CHAR_finish: @ field ptr in r0 3105 mov r2, rINST, lsr #8 @ r2<- AA 3106 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3107 GET_VREG(r1, r2) @ r1<- fp[AA] 3108 GET_INST_OPCODE(ip) @ extract opcode from rINST 3109 @ no-op @ releasing store 3110 str r1, [r0, #offStaticField_value] @ field<- vAA 3111 GOTO_OPCODE(ip) @ jump to next instruction 3112 3113 3114/* ------------------------------ */ 3115 .balign 64 3116.L_OP_SPUT_SHORT: /* 0x6d */ 3117/* File: armv5te/OP_SPUT_SHORT.S */ 3118/* File: armv5te/OP_SPUT.S */ 3119 /* 3120 * General 32-bit SPUT handler. 3121 * 3122 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3123 */ 3124 /* op vAA, field@BBBB */ 3125 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3126 FETCH(r1, 1) @ r1<- field ref BBBB 3127 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3128 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3129 cmp r0, #0 @ is resolved entry null? 3130 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 3131.LOP_SPUT_SHORT_finish: @ field ptr in r0 3132 mov r2, rINST, lsr #8 @ r2<- AA 3133 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3134 GET_VREG(r1, r2) @ r1<- fp[AA] 3135 GET_INST_OPCODE(ip) @ extract opcode from rINST 3136 @ no-op @ releasing store 3137 str r1, [r0, #offStaticField_value] @ field<- vAA 3138 GOTO_OPCODE(ip) @ jump to next instruction 3139 3140 3141/* ------------------------------ */ 3142 .balign 64 3143.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3144/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3145 /* 3146 * Handle a virtual method call. 3147 * 3148 * for: invoke-virtual, invoke-virtual/range 3149 */ 3150 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3151 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3152 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3153 FETCH(r1, 1) @ r1<- BBBB 3154 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3155 FETCH(r10, 2) @ r10<- GFED or CCCC 3156 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3157 .if (!0) 3158 and r10, r10, #15 @ r10<- D (or stays CCCC) 3159 .endif 3160 cmp r0, #0 @ already resolved? 3161 EXPORT_PC() @ must export for invoke 3162 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3163 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3164 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3165 mov r2, #METHOD_VIRTUAL @ resolver method type 3166 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3167 cmp r0, #0 @ got null? 3168 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3169 b common_exceptionThrown @ yes, handle exception 3170 3171/* ------------------------------ */ 3172 .balign 64 3173.L_OP_INVOKE_SUPER: /* 0x6f */ 3174/* File: armv5te/OP_INVOKE_SUPER.S */ 3175 /* 3176 * Handle a "super" method call. 3177 * 3178 * for: invoke-super, invoke-super/range 3179 */ 3180 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3181 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3182 FETCH(r10, 2) @ r10<- GFED or CCCC 3183 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3184 .if (!0) 3185 and r10, r10, #15 @ r10<- D (or stays CCCC) 3186 .endif 3187 FETCH(r1, 1) @ r1<- BBBB 3188 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3189 GET_VREG(r2, r10) @ r2<- "this" ptr 3190 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3191 cmp r2, #0 @ null "this"? 3192 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3193 beq common_errNullObject @ null "this", throw exception 3194 cmp r0, #0 @ already resolved? 3195 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3196 EXPORT_PC() @ must export for invoke 3197 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3198 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3199 3200/* ------------------------------ */ 3201 .balign 64 3202.L_OP_INVOKE_DIRECT: /* 0x70 */ 3203/* File: armv5te/OP_INVOKE_DIRECT.S */ 3204 /* 3205 * Handle a direct method call. 3206 * 3207 * (We could defer the "is 'this' pointer null" test to the common 3208 * method invocation code, and use a flag to indicate that static 3209 * calls don't count. If we do this as part of copying the arguments 3210 * out we could avoiding loading the first arg twice.) 3211 * 3212 * for: invoke-direct, invoke-direct/range 3213 */ 3214 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3215 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3216 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3217 FETCH(r1, 1) @ r1<- BBBB 3218 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3219 FETCH(r10, 2) @ r10<- GFED or CCCC 3220 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3221 .if (!0) 3222 and r10, r10, #15 @ r10<- D (or stays CCCC) 3223 .endif 3224 cmp r0, #0 @ already resolved? 3225 EXPORT_PC() @ must export for invoke 3226 GET_VREG(r2, r10) @ r2<- "this" ptr 3227 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3228.LOP_INVOKE_DIRECT_finish: 3229 cmp r2, #0 @ null "this" ref? 3230 bne common_invokeMethodNoRange @ no, continue on 3231 b common_errNullObject @ yes, throw exception 3232 3233/* ------------------------------ */ 3234 .balign 64 3235.L_OP_INVOKE_STATIC: /* 0x71 */ 3236/* File: armv5te/OP_INVOKE_STATIC.S */ 3237 /* 3238 * Handle a static method call. 3239 * 3240 * for: invoke-static, invoke-static/range 3241 */ 3242 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3243 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3244 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3245 FETCH(r1, 1) @ r1<- BBBB 3246 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3247 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3248 cmp r0, #0 @ already resolved? 3249 EXPORT_PC() @ must export for invoke 3250 bne common_invokeMethodNoRange @ yes, continue on 32510: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3252 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3253 mov r2, #METHOD_STATIC @ resolver method type 3254 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3255 cmp r0, #0 @ got null? 3256 bne common_invokeMethodNoRange @ no, continue 3257 b common_exceptionThrown @ yes, handle exception 3258 3259/* ------------------------------ */ 3260 .balign 64 3261.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3262/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3263 /* 3264 * Handle an interface method call. 3265 * 3266 * for: invoke-interface, invoke-interface/range 3267 */ 3268 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3269 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3270 FETCH(r2, 2) @ r2<- FEDC or CCCC 3271 FETCH(r1, 1) @ r1<- BBBB 3272 .if (!0) 3273 and r2, r2, #15 @ r2<- C (or stays CCCC) 3274 .endif 3275 EXPORT_PC() @ must export for invoke 3276 GET_VREG(r0, r2) @ r0<- first arg ("this") 3277 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3278 cmp r0, #0 @ null obj? 3279 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3280 beq common_errNullObject @ yes, fail 3281 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3282 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3283 cmp r0, #0 @ failed? 3284 beq common_exceptionThrown @ yes, handle exception 3285 b common_invokeMethodNoRange @ jump to common handler 3286 3287/* ------------------------------ */ 3288 .balign 64 3289.L_OP_UNUSED_73: /* 0x73 */ 3290/* File: armv5te/OP_UNUSED_73.S */ 3291/* File: armv5te/unused.S */ 3292 bl common_abort 3293 3294 3295/* ------------------------------ */ 3296 .balign 64 3297.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3298/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3299/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3300 /* 3301 * Handle a virtual method call. 3302 * 3303 * for: invoke-virtual, invoke-virtual/range 3304 */ 3305 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3306 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3307 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3308 FETCH(r1, 1) @ r1<- BBBB 3309 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3310 FETCH(r10, 2) @ r10<- GFED or CCCC 3311 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3312 .if (!1) 3313 and r10, r10, #15 @ r10<- D (or stays CCCC) 3314 .endif 3315 cmp r0, #0 @ already resolved? 3316 EXPORT_PC() @ must export for invoke 3317 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3318 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3319 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3320 mov r2, #METHOD_VIRTUAL @ resolver method type 3321 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3322 cmp r0, #0 @ got null? 3323 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3324 b common_exceptionThrown @ yes, handle exception 3325 3326 3327/* ------------------------------ */ 3328 .balign 64 3329.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3330/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3331/* File: armv5te/OP_INVOKE_SUPER.S */ 3332 /* 3333 * Handle a "super" method call. 3334 * 3335 * for: invoke-super, invoke-super/range 3336 */ 3337 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3338 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3339 FETCH(r10, 2) @ r10<- GFED or CCCC 3340 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3341 .if (!1) 3342 and r10, r10, #15 @ r10<- D (or stays CCCC) 3343 .endif 3344 FETCH(r1, 1) @ r1<- BBBB 3345 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3346 GET_VREG(r2, r10) @ r2<- "this" ptr 3347 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3348 cmp r2, #0 @ null "this"? 3349 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3350 beq common_errNullObject @ null "this", throw exception 3351 cmp r0, #0 @ already resolved? 3352 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3353 EXPORT_PC() @ must export for invoke 3354 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3355 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3356 3357 3358/* ------------------------------ */ 3359 .balign 64 3360.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3361/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3362/* File: armv5te/OP_INVOKE_DIRECT.S */ 3363 /* 3364 * Handle a direct method call. 3365 * 3366 * (We could defer the "is 'this' pointer null" test to the common 3367 * method invocation code, and use a flag to indicate that static 3368 * calls don't count. If we do this as part of copying the arguments 3369 * out we could avoiding loading the first arg twice.) 3370 * 3371 * for: invoke-direct, invoke-direct/range 3372 */ 3373 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3374 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3375 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3376 FETCH(r1, 1) @ r1<- BBBB 3377 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3378 FETCH(r10, 2) @ r10<- GFED or CCCC 3379 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3380 .if (!1) 3381 and r10, r10, #15 @ r10<- D (or stays CCCC) 3382 .endif 3383 cmp r0, #0 @ already resolved? 3384 EXPORT_PC() @ must export for invoke 3385 GET_VREG(r2, r10) @ r2<- "this" ptr 3386 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3387.LOP_INVOKE_DIRECT_RANGE_finish: 3388 cmp r2, #0 @ null "this" ref? 3389 bne common_invokeMethodRange @ no, continue on 3390 b common_errNullObject @ yes, throw exception 3391 3392 3393/* ------------------------------ */ 3394 .balign 64 3395.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3396/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3397/* File: armv5te/OP_INVOKE_STATIC.S */ 3398 /* 3399 * Handle a static method call. 3400 * 3401 * for: invoke-static, invoke-static/range 3402 */ 3403 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3404 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3405 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3406 FETCH(r1, 1) @ r1<- BBBB 3407 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3408 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3409 cmp r0, #0 @ already resolved? 3410 EXPORT_PC() @ must export for invoke 3411 bne common_invokeMethodRange @ yes, continue on 34120: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3413 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3414 mov r2, #METHOD_STATIC @ resolver method type 3415 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3416 cmp r0, #0 @ got null? 3417 bne common_invokeMethodRange @ no, continue 3418 b common_exceptionThrown @ yes, handle exception 3419 3420 3421/* ------------------------------ */ 3422 .balign 64 3423.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3424/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3425/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3426 /* 3427 * Handle an interface method call. 3428 * 3429 * for: invoke-interface, invoke-interface/range 3430 */ 3431 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3432 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3433 FETCH(r2, 2) @ r2<- FEDC or CCCC 3434 FETCH(r1, 1) @ r1<- BBBB 3435 .if (!1) 3436 and r2, r2, #15 @ r2<- C (or stays CCCC) 3437 .endif 3438 EXPORT_PC() @ must export for invoke 3439 GET_VREG(r0, r2) @ r0<- first arg ("this") 3440 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3441 cmp r0, #0 @ null obj? 3442 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3443 beq common_errNullObject @ yes, fail 3444 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3445 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3446 cmp r0, #0 @ failed? 3447 beq common_exceptionThrown @ yes, handle exception 3448 b common_invokeMethodRange @ jump to common handler 3449 3450 3451/* ------------------------------ */ 3452 .balign 64 3453.L_OP_UNUSED_79: /* 0x79 */ 3454/* File: armv5te/OP_UNUSED_79.S */ 3455/* File: armv5te/unused.S */ 3456 bl common_abort 3457 3458 3459/* ------------------------------ */ 3460 .balign 64 3461.L_OP_UNUSED_7A: /* 0x7a */ 3462/* File: armv5te/OP_UNUSED_7A.S */ 3463/* File: armv5te/unused.S */ 3464 bl common_abort 3465 3466 3467/* ------------------------------ */ 3468 .balign 64 3469.L_OP_NEG_INT: /* 0x7b */ 3470/* File: armv6t2/OP_NEG_INT.S */ 3471/* File: armv6t2/unop.S */ 3472 /* 3473 * Generic 32-bit unary operation. Provide an "instr" line that 3474 * specifies an instruction that performs "result = op r0". 3475 * This could be an ARM instruction or a function call. 3476 * 3477 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3478 * int-to-byte, int-to-char, int-to-short 3479 */ 3480 /* unop vA, vB */ 3481 mov r3, rINST, lsr #12 @ r3<- B 3482 ubfx r9, rINST, #8, #4 @ r9<- A 3483 GET_VREG(r0, r3) @ r0<- vB 3484 @ optional op; may set condition codes 3485 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3486 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3487 GET_INST_OPCODE(ip) @ extract opcode from rINST 3488 SET_VREG(r0, r9) @ vAA<- r0 3489 GOTO_OPCODE(ip) @ jump to next instruction 3490 /* 8-9 instructions */ 3491 3492 3493/* ------------------------------ */ 3494 .balign 64 3495.L_OP_NOT_INT: /* 0x7c */ 3496/* File: armv6t2/OP_NOT_INT.S */ 3497/* File: armv6t2/unop.S */ 3498 /* 3499 * Generic 32-bit unary operation. Provide an "instr" line that 3500 * specifies an instruction that performs "result = op r0". 3501 * This could be an ARM instruction or a function call. 3502 * 3503 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3504 * int-to-byte, int-to-char, int-to-short 3505 */ 3506 /* unop vA, vB */ 3507 mov r3, rINST, lsr #12 @ r3<- B 3508 ubfx r9, rINST, #8, #4 @ r9<- A 3509 GET_VREG(r0, r3) @ r0<- vB 3510 @ optional op; may set condition codes 3511 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3512 mvn r0, r0 @ r0<- op, r0-r3 changed 3513 GET_INST_OPCODE(ip) @ extract opcode from rINST 3514 SET_VREG(r0, r9) @ vAA<- r0 3515 GOTO_OPCODE(ip) @ jump to next instruction 3516 /* 8-9 instructions */ 3517 3518 3519/* ------------------------------ */ 3520 .balign 64 3521.L_OP_NEG_LONG: /* 0x7d */ 3522/* File: armv6t2/OP_NEG_LONG.S */ 3523/* File: armv6t2/unopWide.S */ 3524 /* 3525 * Generic 64-bit unary operation. Provide an "instr" line that 3526 * specifies an instruction that performs "result = op r0/r1". 3527 * This could be an ARM instruction or a function call. 3528 * 3529 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3530 */ 3531 /* unop vA, vB */ 3532 mov r3, rINST, lsr #12 @ r3<- B 3533 ubfx r9, rINST, #8, #4 @ r9<- A 3534 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3535 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3536 ldmia r3, {r0-r1} @ r0/r1<- vAA 3537 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3538 rsbs r0, r0, #0 @ optional op; may set condition codes 3539 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3540 GET_INST_OPCODE(ip) @ extract opcode from rINST 3541 stmia r9, {r0-r1} @ vAA<- r0/r1 3542 GOTO_OPCODE(ip) @ jump to next instruction 3543 /* 10-11 instructions */ 3544 3545 3546/* ------------------------------ */ 3547 .balign 64 3548.L_OP_NOT_LONG: /* 0x7e */ 3549/* File: armv6t2/OP_NOT_LONG.S */ 3550/* File: armv6t2/unopWide.S */ 3551 /* 3552 * Generic 64-bit unary operation. Provide an "instr" line that 3553 * specifies an instruction that performs "result = op r0/r1". 3554 * This could be an ARM instruction or a function call. 3555 * 3556 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3557 */ 3558 /* unop vA, vB */ 3559 mov r3, rINST, lsr #12 @ r3<- B 3560 ubfx r9, rINST, #8, #4 @ r9<- A 3561 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3562 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3563 ldmia r3, {r0-r1} @ r0/r1<- vAA 3564 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3565 mvn r0, r0 @ optional op; may set condition codes 3566 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3567 GET_INST_OPCODE(ip) @ extract opcode from rINST 3568 stmia r9, {r0-r1} @ vAA<- r0/r1 3569 GOTO_OPCODE(ip) @ jump to next instruction 3570 /* 10-11 instructions */ 3571 3572 3573/* ------------------------------ */ 3574 .balign 64 3575.L_OP_NEG_FLOAT: /* 0x7f */ 3576/* File: armv6t2/OP_NEG_FLOAT.S */ 3577/* File: armv6t2/unop.S */ 3578 /* 3579 * Generic 32-bit unary operation. Provide an "instr" line that 3580 * specifies an instruction that performs "result = op r0". 3581 * This could be an ARM instruction or a function call. 3582 * 3583 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3584 * int-to-byte, int-to-char, int-to-short 3585 */ 3586 /* unop vA, vB */ 3587 mov r3, rINST, lsr #12 @ r3<- B 3588 ubfx r9, rINST, #8, #4 @ r9<- A 3589 GET_VREG(r0, r3) @ r0<- vB 3590 @ optional op; may set condition codes 3591 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3592 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3593 GET_INST_OPCODE(ip) @ extract opcode from rINST 3594 SET_VREG(r0, r9) @ vAA<- r0 3595 GOTO_OPCODE(ip) @ jump to next instruction 3596 /* 8-9 instructions */ 3597 3598 3599/* ------------------------------ */ 3600 .balign 64 3601.L_OP_NEG_DOUBLE: /* 0x80 */ 3602/* File: armv6t2/OP_NEG_DOUBLE.S */ 3603/* File: armv6t2/unopWide.S */ 3604 /* 3605 * Generic 64-bit unary operation. Provide an "instr" line that 3606 * specifies an instruction that performs "result = op r0/r1". 3607 * This could be an ARM instruction or a function call. 3608 * 3609 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3610 */ 3611 /* unop vA, vB */ 3612 mov r3, rINST, lsr #12 @ r3<- B 3613 ubfx r9, rINST, #8, #4 @ r9<- A 3614 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3615 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3616 ldmia r3, {r0-r1} @ r0/r1<- vAA 3617 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3618 @ optional op; may set condition codes 3619 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3620 GET_INST_OPCODE(ip) @ extract opcode from rINST 3621 stmia r9, {r0-r1} @ vAA<- r0/r1 3622 GOTO_OPCODE(ip) @ jump to next instruction 3623 /* 10-11 instructions */ 3624 3625 3626/* ------------------------------ */ 3627 .balign 64 3628.L_OP_INT_TO_LONG: /* 0x81 */ 3629/* File: armv6t2/OP_INT_TO_LONG.S */ 3630/* File: armv6t2/unopWider.S */ 3631 /* 3632 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3633 * that specifies an instruction that performs "result = op r0", where 3634 * "result" is a 64-bit quantity in r0/r1. 3635 * 3636 * For: int-to-long, int-to-double, float-to-long, float-to-double 3637 */ 3638 /* unop vA, vB */ 3639 mov r3, rINST, lsr #12 @ r3<- B 3640 ubfx r9, rINST, #8, #4 @ r9<- A 3641 GET_VREG(r0, r3) @ r0<- vB 3642 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3643 @ optional op; may set condition codes 3644 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3645 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3646 GET_INST_OPCODE(ip) @ extract opcode from rINST 3647 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3648 GOTO_OPCODE(ip) @ jump to next instruction 3649 /* 9-10 instructions */ 3650 3651 3652/* ------------------------------ */ 3653 .balign 64 3654.L_OP_INT_TO_FLOAT: /* 0x82 */ 3655/* File: arm-vfp/OP_INT_TO_FLOAT.S */ 3656/* File: arm-vfp/funop.S */ 3657 /* 3658 * Generic 32-bit unary floating-point operation. Provide an "instr" 3659 * line that specifies an instruction that performs "s1 = op s0". 3660 * 3661 * for: int-to-float, float-to-int 3662 */ 3663 /* unop vA, vB */ 3664 mov r3, rINST, lsr #12 @ r3<- B 3665 mov r9, rINST, lsr #8 @ r9<- A+ 3666 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3667 flds s0, [r3] @ s0<- vB 3668 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3669 and r9, r9, #15 @ r9<- A 3670 fsitos s1, s0 @ s1<- op 3671 GET_INST_OPCODE(ip) @ extract opcode from rINST 3672 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3673 fsts s1, [r9] @ vA<- s1 3674 GOTO_OPCODE(ip) @ jump to next instruction 3675 3676 3677/* ------------------------------ */ 3678 .balign 64 3679.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3680/* File: arm-vfp/OP_INT_TO_DOUBLE.S */ 3681/* File: arm-vfp/funopWider.S */ 3682 /* 3683 * Generic 32bit-to-64bit floating point unary operation. Provide an 3684 * "instr" line that specifies an instruction that performs "d0 = op s0". 3685 * 3686 * For: int-to-double, float-to-double 3687 */ 3688 /* unop vA, vB */ 3689 mov r3, rINST, lsr #12 @ r3<- B 3690 mov r9, rINST, lsr #8 @ r9<- A+ 3691 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3692 flds s0, [r3] @ s0<- vB 3693 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3694 and r9, r9, #15 @ r9<- A 3695 fsitod d0, s0 @ d0<- op 3696 GET_INST_OPCODE(ip) @ extract opcode from rINST 3697 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3698 fstd d0, [r9] @ vA<- d0 3699 GOTO_OPCODE(ip) @ jump to next instruction 3700 3701 3702/* ------------------------------ */ 3703 .balign 64 3704.L_OP_LONG_TO_INT: /* 0x84 */ 3705/* File: armv5te/OP_LONG_TO_INT.S */ 3706/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3707/* File: armv5te/OP_MOVE.S */ 3708 /* for move, move-object, long-to-int */ 3709 /* op vA, vB */ 3710 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3711 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3712 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3713 GET_VREG(r2, r1) @ r2<- fp[B] 3714 and r0, r0, #15 3715 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3716 SET_VREG(r2, r0) @ fp[A]<- r2 3717 GOTO_OPCODE(ip) @ execute next instruction 3718 3719 3720/* ------------------------------ */ 3721 .balign 64 3722.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3723/* File: armv6t2/OP_LONG_TO_FLOAT.S */ 3724/* File: armv6t2/unopNarrower.S */ 3725 /* 3726 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3727 * that specifies an instruction that performs "result = op r0/r1", where 3728 * "result" is a 32-bit quantity in r0. 3729 * 3730 * For: long-to-float, double-to-int, double-to-float 3731 * 3732 * (This would work for long-to-int, but that instruction is actually 3733 * an exact match for OP_MOVE.) 3734 */ 3735 /* unop vA, vB */ 3736 mov r3, rINST, lsr #12 @ r3<- B 3737 ubfx r9, rINST, #8, #4 @ r9<- A 3738 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3739 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3740 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3741 @ optional op; may set condition codes 3742 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3743 GET_INST_OPCODE(ip) @ extract opcode from rINST 3744 SET_VREG(r0, r9) @ vA<- r0 3745 GOTO_OPCODE(ip) @ jump to next instruction 3746 /* 9-10 instructions */ 3747 3748 3749/* ------------------------------ */ 3750 .balign 64 3751.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3752/* File: armv6t2/OP_LONG_TO_DOUBLE.S */ 3753/* File: armv6t2/unopWide.S */ 3754 /* 3755 * Generic 64-bit unary operation. Provide an "instr" line that 3756 * specifies an instruction that performs "result = op r0/r1". 3757 * This could be an ARM instruction or a function call. 3758 * 3759 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3760 */ 3761 /* unop vA, vB */ 3762 mov r3, rINST, lsr #12 @ r3<- B 3763 ubfx r9, rINST, #8, #4 @ r9<- A 3764 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3765 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3766 ldmia r3, {r0-r1} @ r0/r1<- vAA 3767 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3768 @ optional op; may set condition codes 3769 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3770 GET_INST_OPCODE(ip) @ extract opcode from rINST 3771 stmia r9, {r0-r1} @ vAA<- r0/r1 3772 GOTO_OPCODE(ip) @ jump to next instruction 3773 /* 10-11 instructions */ 3774 3775 3776/* ------------------------------ */ 3777 .balign 64 3778.L_OP_FLOAT_TO_INT: /* 0x87 */ 3779/* File: arm-vfp/OP_FLOAT_TO_INT.S */ 3780/* File: arm-vfp/funop.S */ 3781 /* 3782 * Generic 32-bit unary floating-point operation. Provide an "instr" 3783 * line that specifies an instruction that performs "s1 = op s0". 3784 * 3785 * for: int-to-float, float-to-int 3786 */ 3787 /* unop vA, vB */ 3788 mov r3, rINST, lsr #12 @ r3<- B 3789 mov r9, rINST, lsr #8 @ r9<- A+ 3790 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3791 flds s0, [r3] @ s0<- vB 3792 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3793 and r9, r9, #15 @ r9<- A 3794 ftosizs s1, s0 @ s1<- op 3795 GET_INST_OPCODE(ip) @ extract opcode from rINST 3796 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3797 fsts s1, [r9] @ vA<- s1 3798 GOTO_OPCODE(ip) @ jump to next instruction 3799 3800 3801/* ------------------------------ */ 3802 .balign 64 3803.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3804/* File: armv6t2/OP_FLOAT_TO_LONG.S */ 3805@include "armv6t2/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3806/* File: armv6t2/unopWider.S */ 3807 /* 3808 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3809 * that specifies an instruction that performs "result = op r0", where 3810 * "result" is a 64-bit quantity in r0/r1. 3811 * 3812 * For: int-to-long, int-to-double, float-to-long, float-to-double 3813 */ 3814 /* unop vA, vB */ 3815 mov r3, rINST, lsr #12 @ r3<- B 3816 ubfx r9, rINST, #8, #4 @ r9<- A 3817 GET_VREG(r0, r3) @ r0<- vB 3818 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3819 @ optional op; may set condition codes 3820 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3821 bl f2l_doconv @ r0<- op, r0-r3 changed 3822 GET_INST_OPCODE(ip) @ extract opcode from rINST 3823 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3824 GOTO_OPCODE(ip) @ jump to next instruction 3825 /* 9-10 instructions */ 3826 3827 3828 3829/* ------------------------------ */ 3830 .balign 64 3831.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3832/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */ 3833/* File: arm-vfp/funopWider.S */ 3834 /* 3835 * Generic 32bit-to-64bit floating point unary operation. Provide an 3836 * "instr" line that specifies an instruction that performs "d0 = op s0". 3837 * 3838 * For: int-to-double, float-to-double 3839 */ 3840 /* unop vA, vB */ 3841 mov r3, rINST, lsr #12 @ r3<- B 3842 mov r9, rINST, lsr #8 @ r9<- A+ 3843 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3844 flds s0, [r3] @ s0<- vB 3845 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3846 and r9, r9, #15 @ r9<- A 3847 fcvtds d0, s0 @ d0<- op 3848 GET_INST_OPCODE(ip) @ extract opcode from rINST 3849 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3850 fstd d0, [r9] @ vA<- d0 3851 GOTO_OPCODE(ip) @ jump to next instruction 3852 3853 3854/* ------------------------------ */ 3855 .balign 64 3856.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3857/* File: arm-vfp/OP_DOUBLE_TO_INT.S */ 3858/* File: arm-vfp/funopNarrower.S */ 3859 /* 3860 * Generic 64bit-to-32bit unary floating point operation. Provide an 3861 * "instr" line that specifies an instruction that performs "s0 = op d0". 3862 * 3863 * For: double-to-int, double-to-float 3864 */ 3865 /* unop vA, vB */ 3866 mov r3, rINST, lsr #12 @ r3<- B 3867 mov r9, rINST, lsr #8 @ r9<- A+ 3868 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3869 fldd d0, [r3] @ d0<- vB 3870 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3871 and r9, r9, #15 @ r9<- A 3872 ftosizd s0, d0 @ s0<- op 3873 GET_INST_OPCODE(ip) @ extract opcode from rINST 3874 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3875 fsts s0, [r9] @ vA<- s0 3876 GOTO_OPCODE(ip) @ jump to next instruction 3877 3878 3879/* ------------------------------ */ 3880 .balign 64 3881.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3882/* File: armv6t2/OP_DOUBLE_TO_LONG.S */ 3883@include "armv6t2/unopWide.S" {"instr":"bl __aeabi_d2lz"} 3884/* File: armv6t2/unopWide.S */ 3885 /* 3886 * Generic 64-bit unary operation. Provide an "instr" line that 3887 * specifies an instruction that performs "result = op r0/r1". 3888 * This could be an ARM instruction or a function call. 3889 * 3890 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3891 */ 3892 /* unop vA, vB */ 3893 mov r3, rINST, lsr #12 @ r3<- B 3894 ubfx r9, rINST, #8, #4 @ r9<- A 3895 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3896 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3897 ldmia r3, {r0-r1} @ r0/r1<- vAA 3898 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3899 @ optional op; may set condition codes 3900 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 3901 GET_INST_OPCODE(ip) @ extract opcode from rINST 3902 stmia r9, {r0-r1} @ vAA<- r0/r1 3903 GOTO_OPCODE(ip) @ jump to next instruction 3904 /* 10-11 instructions */ 3905 3906 3907 3908/* ------------------------------ */ 3909 .balign 64 3910.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3911/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */ 3912/* File: arm-vfp/funopNarrower.S */ 3913 /* 3914 * Generic 64bit-to-32bit unary floating point operation. Provide an 3915 * "instr" line that specifies an instruction that performs "s0 = op d0". 3916 * 3917 * For: double-to-int, double-to-float 3918 */ 3919 /* unop vA, vB */ 3920 mov r3, rINST, lsr #12 @ r3<- B 3921 mov r9, rINST, lsr #8 @ r9<- A+ 3922 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3923 fldd d0, [r3] @ d0<- vB 3924 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3925 and r9, r9, #15 @ r9<- A 3926 fcvtsd s0, d0 @ s0<- op 3927 GET_INST_OPCODE(ip) @ extract opcode from rINST 3928 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3929 fsts s0, [r9] @ vA<- s0 3930 GOTO_OPCODE(ip) @ jump to next instruction 3931 3932 3933/* ------------------------------ */ 3934 .balign 64 3935.L_OP_INT_TO_BYTE: /* 0x8d */ 3936/* File: armv6t2/OP_INT_TO_BYTE.S */ 3937/* File: armv6t2/unop.S */ 3938 /* 3939 * Generic 32-bit unary operation. Provide an "instr" line that 3940 * specifies an instruction that performs "result = op r0". 3941 * This could be an ARM instruction or a function call. 3942 * 3943 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3944 * int-to-byte, int-to-char, int-to-short 3945 */ 3946 /* unop vA, vB */ 3947 mov r3, rINST, lsr #12 @ r3<- B 3948 ubfx r9, rINST, #8, #4 @ r9<- A 3949 GET_VREG(r0, r3) @ r0<- vB 3950 @ optional op; may set condition codes 3951 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3952 sxtb r0, r0 @ r0<- op, r0-r3 changed 3953 GET_INST_OPCODE(ip) @ extract opcode from rINST 3954 SET_VREG(r0, r9) @ vAA<- r0 3955 GOTO_OPCODE(ip) @ jump to next instruction 3956 /* 8-9 instructions */ 3957 3958 3959/* ------------------------------ */ 3960 .balign 64 3961.L_OP_INT_TO_CHAR: /* 0x8e */ 3962/* File: armv6t2/OP_INT_TO_CHAR.S */ 3963/* File: armv6t2/unop.S */ 3964 /* 3965 * Generic 32-bit unary operation. Provide an "instr" line that 3966 * specifies an instruction that performs "result = op r0". 3967 * This could be an ARM instruction or a function call. 3968 * 3969 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3970 * int-to-byte, int-to-char, int-to-short 3971 */ 3972 /* unop vA, vB */ 3973 mov r3, rINST, lsr #12 @ r3<- B 3974 ubfx r9, rINST, #8, #4 @ r9<- A 3975 GET_VREG(r0, r3) @ r0<- vB 3976 @ optional op; may set condition codes 3977 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3978 uxth r0, r0 @ r0<- op, r0-r3 changed 3979 GET_INST_OPCODE(ip) @ extract opcode from rINST 3980 SET_VREG(r0, r9) @ vAA<- r0 3981 GOTO_OPCODE(ip) @ jump to next instruction 3982 /* 8-9 instructions */ 3983 3984 3985/* ------------------------------ */ 3986 .balign 64 3987.L_OP_INT_TO_SHORT: /* 0x8f */ 3988/* File: armv6t2/OP_INT_TO_SHORT.S */ 3989/* File: armv6t2/unop.S */ 3990 /* 3991 * Generic 32-bit unary operation. Provide an "instr" line that 3992 * specifies an instruction that performs "result = op r0". 3993 * This could be an ARM instruction or a function call. 3994 * 3995 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3996 * int-to-byte, int-to-char, int-to-short 3997 */ 3998 /* unop vA, vB */ 3999 mov r3, rINST, lsr #12 @ r3<- B 4000 ubfx r9, rINST, #8, #4 @ r9<- A 4001 GET_VREG(r0, r3) @ r0<- vB 4002 @ optional op; may set condition codes 4003 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4004 sxth r0, r0 @ r0<- op, r0-r3 changed 4005 GET_INST_OPCODE(ip) @ extract opcode from rINST 4006 SET_VREG(r0, r9) @ vAA<- r0 4007 GOTO_OPCODE(ip) @ jump to next instruction 4008 /* 8-9 instructions */ 4009 4010 4011/* ------------------------------ */ 4012 .balign 64 4013.L_OP_ADD_INT: /* 0x90 */ 4014/* File: armv5te/OP_ADD_INT.S */ 4015/* File: armv5te/binop.S */ 4016 /* 4017 * Generic 32-bit binary operation. Provide an "instr" line that 4018 * specifies an instruction that performs "result = r0 op r1". 4019 * This could be an ARM instruction or a function call. (If the result 4020 * comes back in a register other than r0, you can override "result".) 4021 * 4022 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4023 * vCC (r1). Useful for integer division and modulus. Note that we 4024 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4025 * handles it correctly. 4026 * 4027 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4028 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4029 * mul-float, div-float, rem-float 4030 */ 4031 /* binop vAA, vBB, vCC */ 4032 FETCH(r0, 1) @ r0<- CCBB 4033 mov r9, rINST, lsr #8 @ r9<- AA 4034 mov r3, r0, lsr #8 @ r3<- CC 4035 and r2, r0, #255 @ r2<- BB 4036 GET_VREG(r1, r3) @ r1<- vCC 4037 GET_VREG(r0, r2) @ r0<- vBB 4038 .if 0 4039 cmp r1, #0 @ is second operand zero? 4040 beq common_errDivideByZero 4041 .endif 4042 4043 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4044 @ optional op; may set condition codes 4045 add r0, r0, r1 @ r0<- op, r0-r3 changed 4046 GET_INST_OPCODE(ip) @ extract opcode from rINST 4047 SET_VREG(r0, r9) @ vAA<- r0 4048 GOTO_OPCODE(ip) @ jump to next instruction 4049 /* 11-14 instructions */ 4050 4051 4052/* ------------------------------ */ 4053 .balign 64 4054.L_OP_SUB_INT: /* 0x91 */ 4055/* File: armv5te/OP_SUB_INT.S */ 4056/* File: armv5te/binop.S */ 4057 /* 4058 * Generic 32-bit binary operation. Provide an "instr" line that 4059 * specifies an instruction that performs "result = r0 op r1". 4060 * This could be an ARM instruction or a function call. (If the result 4061 * comes back in a register other than r0, you can override "result".) 4062 * 4063 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4064 * vCC (r1). Useful for integer division and modulus. Note that we 4065 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4066 * handles it correctly. 4067 * 4068 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4069 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4070 * mul-float, div-float, rem-float 4071 */ 4072 /* binop vAA, vBB, vCC */ 4073 FETCH(r0, 1) @ r0<- CCBB 4074 mov r9, rINST, lsr #8 @ r9<- AA 4075 mov r3, r0, lsr #8 @ r3<- CC 4076 and r2, r0, #255 @ r2<- BB 4077 GET_VREG(r1, r3) @ r1<- vCC 4078 GET_VREG(r0, r2) @ r0<- vBB 4079 .if 0 4080 cmp r1, #0 @ is second operand zero? 4081 beq common_errDivideByZero 4082 .endif 4083 4084 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4085 @ optional op; may set condition codes 4086 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4087 GET_INST_OPCODE(ip) @ extract opcode from rINST 4088 SET_VREG(r0, r9) @ vAA<- r0 4089 GOTO_OPCODE(ip) @ jump to next instruction 4090 /* 11-14 instructions */ 4091 4092 4093/* ------------------------------ */ 4094 .balign 64 4095.L_OP_MUL_INT: /* 0x92 */ 4096/* File: armv5te/OP_MUL_INT.S */ 4097/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4098/* File: armv5te/binop.S */ 4099 /* 4100 * Generic 32-bit binary operation. Provide an "instr" line that 4101 * specifies an instruction that performs "result = r0 op r1". 4102 * This could be an ARM instruction or a function call. (If the result 4103 * comes back in a register other than r0, you can override "result".) 4104 * 4105 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4106 * vCC (r1). Useful for integer division and modulus. Note that we 4107 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4108 * handles it correctly. 4109 * 4110 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4111 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4112 * mul-float, div-float, rem-float 4113 */ 4114 /* binop vAA, vBB, vCC */ 4115 FETCH(r0, 1) @ r0<- CCBB 4116 mov r9, rINST, lsr #8 @ r9<- AA 4117 mov r3, r0, lsr #8 @ r3<- CC 4118 and r2, r0, #255 @ r2<- BB 4119 GET_VREG(r1, r3) @ r1<- vCC 4120 GET_VREG(r0, r2) @ r0<- vBB 4121 .if 0 4122 cmp r1, #0 @ is second operand zero? 4123 beq common_errDivideByZero 4124 .endif 4125 4126 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4127 @ optional op; may set condition codes 4128 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4129 GET_INST_OPCODE(ip) @ extract opcode from rINST 4130 SET_VREG(r0, r9) @ vAA<- r0 4131 GOTO_OPCODE(ip) @ jump to next instruction 4132 /* 11-14 instructions */ 4133 4134 4135/* ------------------------------ */ 4136 .balign 64 4137.L_OP_DIV_INT: /* 0x93 */ 4138/* File: armv5te/OP_DIV_INT.S */ 4139/* File: armv5te/binop.S */ 4140 /* 4141 * Generic 32-bit binary operation. Provide an "instr" line that 4142 * specifies an instruction that performs "result = r0 op r1". 4143 * This could be an ARM instruction or a function call. (If the result 4144 * comes back in a register other than r0, you can override "result".) 4145 * 4146 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4147 * vCC (r1). Useful for integer division and modulus. Note that we 4148 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4149 * handles it correctly. 4150 * 4151 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4152 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4153 * mul-float, div-float, rem-float 4154 */ 4155 /* binop vAA, vBB, vCC */ 4156 FETCH(r0, 1) @ r0<- CCBB 4157 mov r9, rINST, lsr #8 @ r9<- AA 4158 mov r3, r0, lsr #8 @ r3<- CC 4159 and r2, r0, #255 @ r2<- BB 4160 GET_VREG(r1, r3) @ r1<- vCC 4161 GET_VREG(r0, r2) @ r0<- vBB 4162 .if 1 4163 cmp r1, #0 @ is second operand zero? 4164 beq common_errDivideByZero 4165 .endif 4166 4167 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4168 @ optional op; may set condition codes 4169 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4170 GET_INST_OPCODE(ip) @ extract opcode from rINST 4171 SET_VREG(r0, r9) @ vAA<- r0 4172 GOTO_OPCODE(ip) @ jump to next instruction 4173 /* 11-14 instructions */ 4174 4175 4176/* ------------------------------ */ 4177 .balign 64 4178.L_OP_REM_INT: /* 0x94 */ 4179/* File: armv5te/OP_REM_INT.S */ 4180/* idivmod returns quotient in r0 and remainder in r1 */ 4181/* File: armv5te/binop.S */ 4182 /* 4183 * Generic 32-bit binary operation. Provide an "instr" line that 4184 * specifies an instruction that performs "result = r0 op r1". 4185 * This could be an ARM instruction or a function call. (If the result 4186 * comes back in a register other than r0, you can override "result".) 4187 * 4188 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4189 * vCC (r1). Useful for integer division and modulus. Note that we 4190 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4191 * handles it correctly. 4192 * 4193 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4194 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4195 * mul-float, div-float, rem-float 4196 */ 4197 /* binop vAA, vBB, vCC */ 4198 FETCH(r0, 1) @ r0<- CCBB 4199 mov r9, rINST, lsr #8 @ r9<- AA 4200 mov r3, r0, lsr #8 @ r3<- CC 4201 and r2, r0, #255 @ r2<- BB 4202 GET_VREG(r1, r3) @ r1<- vCC 4203 GET_VREG(r0, r2) @ r0<- vBB 4204 .if 1 4205 cmp r1, #0 @ is second operand zero? 4206 beq common_errDivideByZero 4207 .endif 4208 4209 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4210 @ optional op; may set condition codes 4211 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4212 GET_INST_OPCODE(ip) @ extract opcode from rINST 4213 SET_VREG(r1, r9) @ vAA<- r1 4214 GOTO_OPCODE(ip) @ jump to next instruction 4215 /* 11-14 instructions */ 4216 4217 4218/* ------------------------------ */ 4219 .balign 64 4220.L_OP_AND_INT: /* 0x95 */ 4221/* File: armv5te/OP_AND_INT.S */ 4222/* File: armv5te/binop.S */ 4223 /* 4224 * Generic 32-bit binary operation. Provide an "instr" line that 4225 * specifies an instruction that performs "result = r0 op r1". 4226 * This could be an ARM instruction or a function call. (If the result 4227 * comes back in a register other than r0, you can override "result".) 4228 * 4229 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4230 * vCC (r1). Useful for integer division and modulus. Note that we 4231 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4232 * handles it correctly. 4233 * 4234 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4235 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4236 * mul-float, div-float, rem-float 4237 */ 4238 /* binop vAA, vBB, vCC */ 4239 FETCH(r0, 1) @ r0<- CCBB 4240 mov r9, rINST, lsr #8 @ r9<- AA 4241 mov r3, r0, lsr #8 @ r3<- CC 4242 and r2, r0, #255 @ r2<- BB 4243 GET_VREG(r1, r3) @ r1<- vCC 4244 GET_VREG(r0, r2) @ r0<- vBB 4245 .if 0 4246 cmp r1, #0 @ is second operand zero? 4247 beq common_errDivideByZero 4248 .endif 4249 4250 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4251 @ optional op; may set condition codes 4252 and r0, r0, r1 @ r0<- op, r0-r3 changed 4253 GET_INST_OPCODE(ip) @ extract opcode from rINST 4254 SET_VREG(r0, r9) @ vAA<- r0 4255 GOTO_OPCODE(ip) @ jump to next instruction 4256 /* 11-14 instructions */ 4257 4258 4259/* ------------------------------ */ 4260 .balign 64 4261.L_OP_OR_INT: /* 0x96 */ 4262/* File: armv5te/OP_OR_INT.S */ 4263/* File: armv5te/binop.S */ 4264 /* 4265 * Generic 32-bit binary operation. Provide an "instr" line that 4266 * specifies an instruction that performs "result = r0 op r1". 4267 * This could be an ARM instruction or a function call. (If the result 4268 * comes back in a register other than r0, you can override "result".) 4269 * 4270 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4271 * vCC (r1). Useful for integer division and modulus. Note that we 4272 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4273 * handles it correctly. 4274 * 4275 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4276 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4277 * mul-float, div-float, rem-float 4278 */ 4279 /* binop vAA, vBB, vCC */ 4280 FETCH(r0, 1) @ r0<- CCBB 4281 mov r9, rINST, lsr #8 @ r9<- AA 4282 mov r3, r0, lsr #8 @ r3<- CC 4283 and r2, r0, #255 @ r2<- BB 4284 GET_VREG(r1, r3) @ r1<- vCC 4285 GET_VREG(r0, r2) @ r0<- vBB 4286 .if 0 4287 cmp r1, #0 @ is second operand zero? 4288 beq common_errDivideByZero 4289 .endif 4290 4291 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4292 @ optional op; may set condition codes 4293 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4294 GET_INST_OPCODE(ip) @ extract opcode from rINST 4295 SET_VREG(r0, r9) @ vAA<- r0 4296 GOTO_OPCODE(ip) @ jump to next instruction 4297 /* 11-14 instructions */ 4298 4299 4300/* ------------------------------ */ 4301 .balign 64 4302.L_OP_XOR_INT: /* 0x97 */ 4303/* File: armv5te/OP_XOR_INT.S */ 4304/* File: armv5te/binop.S */ 4305 /* 4306 * Generic 32-bit binary operation. Provide an "instr" line that 4307 * specifies an instruction that performs "result = r0 op r1". 4308 * This could be an ARM instruction or a function call. (If the result 4309 * comes back in a register other than r0, you can override "result".) 4310 * 4311 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4312 * vCC (r1). Useful for integer division and modulus. Note that we 4313 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4314 * handles it correctly. 4315 * 4316 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4317 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4318 * mul-float, div-float, rem-float 4319 */ 4320 /* binop vAA, vBB, vCC */ 4321 FETCH(r0, 1) @ r0<- CCBB 4322 mov r9, rINST, lsr #8 @ r9<- AA 4323 mov r3, r0, lsr #8 @ r3<- CC 4324 and r2, r0, #255 @ r2<- BB 4325 GET_VREG(r1, r3) @ r1<- vCC 4326 GET_VREG(r0, r2) @ r0<- vBB 4327 .if 0 4328 cmp r1, #0 @ is second operand zero? 4329 beq common_errDivideByZero 4330 .endif 4331 4332 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4333 @ optional op; may set condition codes 4334 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4335 GET_INST_OPCODE(ip) @ extract opcode from rINST 4336 SET_VREG(r0, r9) @ vAA<- r0 4337 GOTO_OPCODE(ip) @ jump to next instruction 4338 /* 11-14 instructions */ 4339 4340 4341/* ------------------------------ */ 4342 .balign 64 4343.L_OP_SHL_INT: /* 0x98 */ 4344/* File: armv5te/OP_SHL_INT.S */ 4345/* File: armv5te/binop.S */ 4346 /* 4347 * Generic 32-bit binary operation. Provide an "instr" line that 4348 * specifies an instruction that performs "result = r0 op r1". 4349 * This could be an ARM instruction or a function call. (If the result 4350 * comes back in a register other than r0, you can override "result".) 4351 * 4352 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4353 * vCC (r1). Useful for integer division and modulus. Note that we 4354 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4355 * handles it correctly. 4356 * 4357 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4358 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4359 * mul-float, div-float, rem-float 4360 */ 4361 /* binop vAA, vBB, vCC */ 4362 FETCH(r0, 1) @ r0<- CCBB 4363 mov r9, rINST, lsr #8 @ r9<- AA 4364 mov r3, r0, lsr #8 @ r3<- CC 4365 and r2, r0, #255 @ r2<- BB 4366 GET_VREG(r1, r3) @ r1<- vCC 4367 GET_VREG(r0, r2) @ r0<- vBB 4368 .if 0 4369 cmp r1, #0 @ is second operand zero? 4370 beq common_errDivideByZero 4371 .endif 4372 4373 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4374 and r1, r1, #31 @ optional op; may set condition codes 4375 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4376 GET_INST_OPCODE(ip) @ extract opcode from rINST 4377 SET_VREG(r0, r9) @ vAA<- r0 4378 GOTO_OPCODE(ip) @ jump to next instruction 4379 /* 11-14 instructions */ 4380 4381 4382/* ------------------------------ */ 4383 .balign 64 4384.L_OP_SHR_INT: /* 0x99 */ 4385/* File: armv5te/OP_SHR_INT.S */ 4386/* File: armv5te/binop.S */ 4387 /* 4388 * Generic 32-bit binary operation. Provide an "instr" line that 4389 * specifies an instruction that performs "result = r0 op r1". 4390 * This could be an ARM instruction or a function call. (If the result 4391 * comes back in a register other than r0, you can override "result".) 4392 * 4393 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4394 * vCC (r1). Useful for integer division and modulus. Note that we 4395 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4396 * handles it correctly. 4397 * 4398 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4399 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4400 * mul-float, div-float, rem-float 4401 */ 4402 /* binop vAA, vBB, vCC */ 4403 FETCH(r0, 1) @ r0<- CCBB 4404 mov r9, rINST, lsr #8 @ r9<- AA 4405 mov r3, r0, lsr #8 @ r3<- CC 4406 and r2, r0, #255 @ r2<- BB 4407 GET_VREG(r1, r3) @ r1<- vCC 4408 GET_VREG(r0, r2) @ r0<- vBB 4409 .if 0 4410 cmp r1, #0 @ is second operand zero? 4411 beq common_errDivideByZero 4412 .endif 4413 4414 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4415 and r1, r1, #31 @ optional op; may set condition codes 4416 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4417 GET_INST_OPCODE(ip) @ extract opcode from rINST 4418 SET_VREG(r0, r9) @ vAA<- r0 4419 GOTO_OPCODE(ip) @ jump to next instruction 4420 /* 11-14 instructions */ 4421 4422 4423/* ------------------------------ */ 4424 .balign 64 4425.L_OP_USHR_INT: /* 0x9a */ 4426/* File: armv5te/OP_USHR_INT.S */ 4427/* File: armv5te/binop.S */ 4428 /* 4429 * Generic 32-bit binary operation. Provide an "instr" line that 4430 * specifies an instruction that performs "result = r0 op r1". 4431 * This could be an ARM instruction or a function call. (If the result 4432 * comes back in a register other than r0, you can override "result".) 4433 * 4434 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4435 * vCC (r1). Useful for integer division and modulus. Note that we 4436 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4437 * handles it correctly. 4438 * 4439 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4440 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4441 * mul-float, div-float, rem-float 4442 */ 4443 /* binop vAA, vBB, vCC */ 4444 FETCH(r0, 1) @ r0<- CCBB 4445 mov r9, rINST, lsr #8 @ r9<- AA 4446 mov r3, r0, lsr #8 @ r3<- CC 4447 and r2, r0, #255 @ r2<- BB 4448 GET_VREG(r1, r3) @ r1<- vCC 4449 GET_VREG(r0, r2) @ r0<- vBB 4450 .if 0 4451 cmp r1, #0 @ is second operand zero? 4452 beq common_errDivideByZero 4453 .endif 4454 4455 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4456 and r1, r1, #31 @ optional op; may set condition codes 4457 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4458 GET_INST_OPCODE(ip) @ extract opcode from rINST 4459 SET_VREG(r0, r9) @ vAA<- r0 4460 GOTO_OPCODE(ip) @ jump to next instruction 4461 /* 11-14 instructions */ 4462 4463 4464/* ------------------------------ */ 4465 .balign 64 4466.L_OP_ADD_LONG: /* 0x9b */ 4467/* File: armv5te/OP_ADD_LONG.S */ 4468/* File: armv5te/binopWide.S */ 4469 /* 4470 * Generic 64-bit binary operation. Provide an "instr" line that 4471 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4472 * This could be an ARM instruction or a function call. (If the result 4473 * comes back in a register other than r0, you can override "result".) 4474 * 4475 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4476 * vCC (r1). Useful for integer division and modulus. 4477 * 4478 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4479 * xor-long, add-double, sub-double, mul-double, div-double, 4480 * rem-double 4481 * 4482 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4483 */ 4484 /* binop vAA, vBB, vCC */ 4485 FETCH(r0, 1) @ r0<- CCBB 4486 mov r9, rINST, lsr #8 @ r9<- AA 4487 and r2, r0, #255 @ r2<- BB 4488 mov r3, r0, lsr #8 @ r3<- CC 4489 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4490 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4491 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4492 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4493 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4494 .if 0 4495 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4496 beq common_errDivideByZero 4497 .endif 4498 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4499 4500 adds r0, r0, r2 @ optional op; may set condition codes 4501 adc r1, r1, r3 @ result<- op, r0-r3 changed 4502 GET_INST_OPCODE(ip) @ extract opcode from rINST 4503 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4504 GOTO_OPCODE(ip) @ jump to next instruction 4505 /* 14-17 instructions */ 4506 4507 4508/* ------------------------------ */ 4509 .balign 64 4510.L_OP_SUB_LONG: /* 0x9c */ 4511/* File: armv5te/OP_SUB_LONG.S */ 4512/* File: armv5te/binopWide.S */ 4513 /* 4514 * Generic 64-bit binary operation. Provide an "instr" line that 4515 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4516 * This could be an ARM instruction or a function call. (If the result 4517 * comes back in a register other than r0, you can override "result".) 4518 * 4519 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4520 * vCC (r1). Useful for integer division and modulus. 4521 * 4522 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4523 * xor-long, add-double, sub-double, mul-double, div-double, 4524 * rem-double 4525 * 4526 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4527 */ 4528 /* binop vAA, vBB, vCC */ 4529 FETCH(r0, 1) @ r0<- CCBB 4530 mov r9, rINST, lsr #8 @ r9<- AA 4531 and r2, r0, #255 @ r2<- BB 4532 mov r3, r0, lsr #8 @ r3<- CC 4533 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4534 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4535 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4536 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4537 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4538 .if 0 4539 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4540 beq common_errDivideByZero 4541 .endif 4542 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4543 4544 subs r0, r0, r2 @ optional op; may set condition codes 4545 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4546 GET_INST_OPCODE(ip) @ extract opcode from rINST 4547 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4548 GOTO_OPCODE(ip) @ jump to next instruction 4549 /* 14-17 instructions */ 4550 4551 4552/* ------------------------------ */ 4553 .balign 64 4554.L_OP_MUL_LONG: /* 0x9d */ 4555/* File: armv5te/OP_MUL_LONG.S */ 4556 /* 4557 * Signed 64-bit integer multiply. 4558 * 4559 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4560 * WX 4561 * x YZ 4562 * -------- 4563 * ZW ZX 4564 * YW YX 4565 * 4566 * The low word of the result holds ZX, the high word holds 4567 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4568 * it doesn't fit in the low 64 bits. 4569 * 4570 * Unlike most ARM math operations, multiply instructions have 4571 * restrictions on using the same register more than once (Rd and Rm 4572 * cannot be the same). 4573 */ 4574 /* mul-long vAA, vBB, vCC */ 4575 FETCH(r0, 1) @ r0<- CCBB 4576 and r2, r0, #255 @ r2<- BB 4577 mov r3, r0, lsr #8 @ r3<- CC 4578 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4579 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4580 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4581 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4582 mul ip, r2, r1 @ ip<- ZxW 4583 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4584 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4585 mov r0, rINST, lsr #8 @ r0<- AA 4586 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4587 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4588 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4589 b .LOP_MUL_LONG_finish 4590 4591/* ------------------------------ */ 4592 .balign 64 4593.L_OP_DIV_LONG: /* 0x9e */ 4594/* File: armv5te/OP_DIV_LONG.S */ 4595/* File: armv5te/binopWide.S */ 4596 /* 4597 * Generic 64-bit binary operation. Provide an "instr" line that 4598 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4599 * This could be an ARM instruction or a function call. (If the result 4600 * comes back in a register other than r0, you can override "result".) 4601 * 4602 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4603 * vCC (r1). Useful for integer division and modulus. 4604 * 4605 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4606 * xor-long, add-double, sub-double, mul-double, div-double, 4607 * rem-double 4608 * 4609 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4610 */ 4611 /* binop vAA, vBB, vCC */ 4612 FETCH(r0, 1) @ r0<- CCBB 4613 mov r9, rINST, lsr #8 @ r9<- AA 4614 and r2, r0, #255 @ r2<- BB 4615 mov r3, r0, lsr #8 @ r3<- CC 4616 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4617 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4618 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4619 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4620 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4621 .if 1 4622 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4623 beq common_errDivideByZero 4624 .endif 4625 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4626 4627 @ optional op; may set condition codes 4628 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4629 GET_INST_OPCODE(ip) @ extract opcode from rINST 4630 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4631 GOTO_OPCODE(ip) @ jump to next instruction 4632 /* 14-17 instructions */ 4633 4634 4635/* ------------------------------ */ 4636 .balign 64 4637.L_OP_REM_LONG: /* 0x9f */ 4638/* File: armv5te/OP_REM_LONG.S */ 4639/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4640/* File: armv5te/binopWide.S */ 4641 /* 4642 * Generic 64-bit binary operation. Provide an "instr" line that 4643 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4644 * This could be an ARM instruction or a function call. (If the result 4645 * comes back in a register other than r0, you can override "result".) 4646 * 4647 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4648 * vCC (r1). Useful for integer division and modulus. 4649 * 4650 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4651 * xor-long, add-double, sub-double, mul-double, div-double, 4652 * rem-double 4653 * 4654 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4655 */ 4656 /* binop vAA, vBB, vCC */ 4657 FETCH(r0, 1) @ r0<- CCBB 4658 mov r9, rINST, lsr #8 @ r9<- AA 4659 and r2, r0, #255 @ r2<- BB 4660 mov r3, r0, lsr #8 @ r3<- CC 4661 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4662 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4663 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4664 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4665 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4666 .if 1 4667 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4668 beq common_errDivideByZero 4669 .endif 4670 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4671 4672 @ optional op; may set condition codes 4673 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4674 GET_INST_OPCODE(ip) @ extract opcode from rINST 4675 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4676 GOTO_OPCODE(ip) @ jump to next instruction 4677 /* 14-17 instructions */ 4678 4679 4680/* ------------------------------ */ 4681 .balign 64 4682.L_OP_AND_LONG: /* 0xa0 */ 4683/* File: armv5te/OP_AND_LONG.S */ 4684/* File: armv5te/binopWide.S */ 4685 /* 4686 * Generic 64-bit binary operation. Provide an "instr" line that 4687 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4688 * This could be an ARM instruction or a function call. (If the result 4689 * comes back in a register other than r0, you can override "result".) 4690 * 4691 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4692 * vCC (r1). Useful for integer division and modulus. 4693 * 4694 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4695 * xor-long, add-double, sub-double, mul-double, div-double, 4696 * rem-double 4697 * 4698 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4699 */ 4700 /* binop vAA, vBB, vCC */ 4701 FETCH(r0, 1) @ r0<- CCBB 4702 mov r9, rINST, lsr #8 @ r9<- AA 4703 and r2, r0, #255 @ r2<- BB 4704 mov r3, r0, lsr #8 @ r3<- CC 4705 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4706 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4707 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4708 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4709 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4710 .if 0 4711 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4712 beq common_errDivideByZero 4713 .endif 4714 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4715 4716 and r0, r0, r2 @ optional op; may set condition codes 4717 and r1, r1, r3 @ result<- op, r0-r3 changed 4718 GET_INST_OPCODE(ip) @ extract opcode from rINST 4719 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4720 GOTO_OPCODE(ip) @ jump to next instruction 4721 /* 14-17 instructions */ 4722 4723 4724/* ------------------------------ */ 4725 .balign 64 4726.L_OP_OR_LONG: /* 0xa1 */ 4727/* File: armv5te/OP_OR_LONG.S */ 4728/* File: armv5te/binopWide.S */ 4729 /* 4730 * Generic 64-bit binary operation. Provide an "instr" line that 4731 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4732 * This could be an ARM instruction or a function call. (If the result 4733 * comes back in a register other than r0, you can override "result".) 4734 * 4735 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4736 * vCC (r1). Useful for integer division and modulus. 4737 * 4738 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4739 * xor-long, add-double, sub-double, mul-double, div-double, 4740 * rem-double 4741 * 4742 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4743 */ 4744 /* binop vAA, vBB, vCC */ 4745 FETCH(r0, 1) @ r0<- CCBB 4746 mov r9, rINST, lsr #8 @ r9<- AA 4747 and r2, r0, #255 @ r2<- BB 4748 mov r3, r0, lsr #8 @ r3<- CC 4749 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4750 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4751 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4752 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4753 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4754 .if 0 4755 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4756 beq common_errDivideByZero 4757 .endif 4758 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4759 4760 orr r0, r0, r2 @ optional op; may set condition codes 4761 orr r1, r1, r3 @ result<- op, r0-r3 changed 4762 GET_INST_OPCODE(ip) @ extract opcode from rINST 4763 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4764 GOTO_OPCODE(ip) @ jump to next instruction 4765 /* 14-17 instructions */ 4766 4767 4768/* ------------------------------ */ 4769 .balign 64 4770.L_OP_XOR_LONG: /* 0xa2 */ 4771/* File: armv5te/OP_XOR_LONG.S */ 4772/* File: armv5te/binopWide.S */ 4773 /* 4774 * Generic 64-bit binary operation. Provide an "instr" line that 4775 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4776 * This could be an ARM instruction or a function call. (If the result 4777 * comes back in a register other than r0, you can override "result".) 4778 * 4779 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4780 * vCC (r1). Useful for integer division and modulus. 4781 * 4782 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4783 * xor-long, add-double, sub-double, mul-double, div-double, 4784 * rem-double 4785 * 4786 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4787 */ 4788 /* binop vAA, vBB, vCC */ 4789 FETCH(r0, 1) @ r0<- CCBB 4790 mov r9, rINST, lsr #8 @ r9<- AA 4791 and r2, r0, #255 @ r2<- BB 4792 mov r3, r0, lsr #8 @ r3<- CC 4793 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4794 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4795 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4796 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4797 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4798 .if 0 4799 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4800 beq common_errDivideByZero 4801 .endif 4802 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4803 4804 eor r0, r0, r2 @ optional op; may set condition codes 4805 eor r1, r1, r3 @ result<- op, r0-r3 changed 4806 GET_INST_OPCODE(ip) @ extract opcode from rINST 4807 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4808 GOTO_OPCODE(ip) @ jump to next instruction 4809 /* 14-17 instructions */ 4810 4811 4812/* ------------------------------ */ 4813 .balign 64 4814.L_OP_SHL_LONG: /* 0xa3 */ 4815/* File: armv5te/OP_SHL_LONG.S */ 4816 /* 4817 * Long integer shift. This is different from the generic 32/64-bit 4818 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4819 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4820 * 6 bits of the shift distance. 4821 */ 4822 /* shl-long vAA, vBB, vCC */ 4823 FETCH(r0, 1) @ r0<- CCBB 4824 mov r9, rINST, lsr #8 @ r9<- AA 4825 and r3, r0, #255 @ r3<- BB 4826 mov r0, r0, lsr #8 @ r0<- CC 4827 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4828 GET_VREG(r2, r0) @ r2<- vCC 4829 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4830 and r2, r2, #63 @ r2<- r2 & 0x3f 4831 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4832 4833 mov r1, r1, asl r2 @ r1<- r1 << r2 4834 rsb r3, r2, #32 @ r3<- 32 - r2 4835 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 4836 subs ip, r2, #32 @ ip<- r2 - 32 4837 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 4838 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4839 b .LOP_SHL_LONG_finish 4840 4841/* ------------------------------ */ 4842 .balign 64 4843.L_OP_SHR_LONG: /* 0xa4 */ 4844/* File: armv5te/OP_SHR_LONG.S */ 4845 /* 4846 * Long integer shift. This is different from the generic 32/64-bit 4847 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4848 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4849 * 6 bits of the shift distance. 4850 */ 4851 /* shr-long vAA, vBB, vCC */ 4852 FETCH(r0, 1) @ r0<- CCBB 4853 mov r9, rINST, lsr #8 @ r9<- AA 4854 and r3, r0, #255 @ r3<- BB 4855 mov r0, r0, lsr #8 @ r0<- CC 4856 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4857 GET_VREG(r2, r0) @ r2<- vCC 4858 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4859 and r2, r2, #63 @ r0<- r0 & 0x3f 4860 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4861 4862 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4863 rsb r3, r2, #32 @ r3<- 32 - r2 4864 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4865 subs ip, r2, #32 @ ip<- r2 - 32 4866 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 4867 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4868 b .LOP_SHR_LONG_finish 4869 4870/* ------------------------------ */ 4871 .balign 64 4872.L_OP_USHR_LONG: /* 0xa5 */ 4873/* File: armv5te/OP_USHR_LONG.S */ 4874 /* 4875 * Long integer shift. This is different from the generic 32/64-bit 4876 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4877 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4878 * 6 bits of the shift distance. 4879 */ 4880 /* ushr-long vAA, vBB, vCC */ 4881 FETCH(r0, 1) @ r0<- CCBB 4882 mov r9, rINST, lsr #8 @ r9<- AA 4883 and r3, r0, #255 @ r3<- BB 4884 mov r0, r0, lsr #8 @ r0<- CC 4885 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4886 GET_VREG(r2, r0) @ r2<- vCC 4887 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4888 and r2, r2, #63 @ r0<- r0 & 0x3f 4889 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4890 4891 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4892 rsb r3, r2, #32 @ r3<- 32 - r2 4893 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4894 subs ip, r2, #32 @ ip<- r2 - 32 4895 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 4896 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4897 b .LOP_USHR_LONG_finish 4898 4899/* ------------------------------ */ 4900 .balign 64 4901.L_OP_ADD_FLOAT: /* 0xa6 */ 4902/* File: arm-vfp/OP_ADD_FLOAT.S */ 4903/* File: arm-vfp/fbinop.S */ 4904 /* 4905 * Generic 32-bit floating-point operation. Provide an "instr" line that 4906 * specifies an instruction that performs "s2 = s0 op s1". Because we 4907 * use the "softfp" ABI, this must be an instruction, not a function call. 4908 * 4909 * For: add-float, sub-float, mul-float, div-float 4910 */ 4911 /* floatop vAA, vBB, vCC */ 4912 FETCH(r0, 1) @ r0<- CCBB 4913 mov r9, rINST, lsr #8 @ r9<- AA 4914 mov r3, r0, lsr #8 @ r3<- CC 4915 and r2, r0, #255 @ r2<- BB 4916 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4917 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4918 flds s1, [r3] @ s1<- vCC 4919 flds s0, [r2] @ s0<- vBB 4920 4921 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4922 fadds s2, s0, s1 @ s2<- op 4923 GET_INST_OPCODE(ip) @ extract opcode from rINST 4924 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4925 fsts s2, [r9] @ vAA<- s2 4926 GOTO_OPCODE(ip) @ jump to next instruction 4927 4928 4929/* ------------------------------ */ 4930 .balign 64 4931.L_OP_SUB_FLOAT: /* 0xa7 */ 4932/* File: arm-vfp/OP_SUB_FLOAT.S */ 4933/* File: arm-vfp/fbinop.S */ 4934 /* 4935 * Generic 32-bit floating-point operation. Provide an "instr" line that 4936 * specifies an instruction that performs "s2 = s0 op s1". Because we 4937 * use the "softfp" ABI, this must be an instruction, not a function call. 4938 * 4939 * For: add-float, sub-float, mul-float, div-float 4940 */ 4941 /* floatop vAA, vBB, vCC */ 4942 FETCH(r0, 1) @ r0<- CCBB 4943 mov r9, rINST, lsr #8 @ r9<- AA 4944 mov r3, r0, lsr #8 @ r3<- CC 4945 and r2, r0, #255 @ r2<- BB 4946 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4947 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4948 flds s1, [r3] @ s1<- vCC 4949 flds s0, [r2] @ s0<- vBB 4950 4951 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4952 fsubs s2, s0, s1 @ s2<- op 4953 GET_INST_OPCODE(ip) @ extract opcode from rINST 4954 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4955 fsts s2, [r9] @ vAA<- s2 4956 GOTO_OPCODE(ip) @ jump to next instruction 4957 4958 4959/* ------------------------------ */ 4960 .balign 64 4961.L_OP_MUL_FLOAT: /* 0xa8 */ 4962/* File: arm-vfp/OP_MUL_FLOAT.S */ 4963/* File: arm-vfp/fbinop.S */ 4964 /* 4965 * Generic 32-bit floating-point operation. Provide an "instr" line that 4966 * specifies an instruction that performs "s2 = s0 op s1". Because we 4967 * use the "softfp" ABI, this must be an instruction, not a function call. 4968 * 4969 * For: add-float, sub-float, mul-float, div-float 4970 */ 4971 /* floatop vAA, vBB, vCC */ 4972 FETCH(r0, 1) @ r0<- CCBB 4973 mov r9, rINST, lsr #8 @ r9<- AA 4974 mov r3, r0, lsr #8 @ r3<- CC 4975 and r2, r0, #255 @ r2<- BB 4976 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4977 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4978 flds s1, [r3] @ s1<- vCC 4979 flds s0, [r2] @ s0<- vBB 4980 4981 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4982 fmuls s2, s0, s1 @ s2<- op 4983 GET_INST_OPCODE(ip) @ extract opcode from rINST 4984 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4985 fsts s2, [r9] @ vAA<- s2 4986 GOTO_OPCODE(ip) @ jump to next instruction 4987 4988 4989/* ------------------------------ */ 4990 .balign 64 4991.L_OP_DIV_FLOAT: /* 0xa9 */ 4992/* File: arm-vfp/OP_DIV_FLOAT.S */ 4993/* File: arm-vfp/fbinop.S */ 4994 /* 4995 * Generic 32-bit floating-point operation. Provide an "instr" line that 4996 * specifies an instruction that performs "s2 = s0 op s1". Because we 4997 * use the "softfp" ABI, this must be an instruction, not a function call. 4998 * 4999 * For: add-float, sub-float, mul-float, div-float 5000 */ 5001 /* floatop vAA, vBB, vCC */ 5002 FETCH(r0, 1) @ r0<- CCBB 5003 mov r9, rINST, lsr #8 @ r9<- AA 5004 mov r3, r0, lsr #8 @ r3<- CC 5005 and r2, r0, #255 @ r2<- BB 5006 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5007 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5008 flds s1, [r3] @ s1<- vCC 5009 flds s0, [r2] @ s0<- vBB 5010 5011 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5012 fdivs s2, s0, s1 @ s2<- op 5013 GET_INST_OPCODE(ip) @ extract opcode from rINST 5014 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5015 fsts s2, [r9] @ vAA<- s2 5016 GOTO_OPCODE(ip) @ jump to next instruction 5017 5018 5019/* ------------------------------ */ 5020 .balign 64 5021.L_OP_REM_FLOAT: /* 0xaa */ 5022/* File: armv5te/OP_REM_FLOAT.S */ 5023/* EABI doesn't define a float remainder function, but libm does */ 5024/* File: armv5te/binop.S */ 5025 /* 5026 * Generic 32-bit binary operation. Provide an "instr" line that 5027 * specifies an instruction that performs "result = r0 op r1". 5028 * This could be an ARM instruction or a function call. (If the result 5029 * comes back in a register other than r0, you can override "result".) 5030 * 5031 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5032 * vCC (r1). Useful for integer division and modulus. Note that we 5033 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5034 * handles it correctly. 5035 * 5036 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5037 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5038 * mul-float, div-float, rem-float 5039 */ 5040 /* binop vAA, vBB, vCC */ 5041 FETCH(r0, 1) @ r0<- CCBB 5042 mov r9, rINST, lsr #8 @ r9<- AA 5043 mov r3, r0, lsr #8 @ r3<- CC 5044 and r2, r0, #255 @ r2<- BB 5045 GET_VREG(r1, r3) @ r1<- vCC 5046 GET_VREG(r0, r2) @ r0<- vBB 5047 .if 0 5048 cmp r1, #0 @ is second operand zero? 5049 beq common_errDivideByZero 5050 .endif 5051 5052 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5053 @ optional op; may set condition codes 5054 bl fmodf @ r0<- op, r0-r3 changed 5055 GET_INST_OPCODE(ip) @ extract opcode from rINST 5056 SET_VREG(r0, r9) @ vAA<- r0 5057 GOTO_OPCODE(ip) @ jump to next instruction 5058 /* 11-14 instructions */ 5059 5060 5061/* ------------------------------ */ 5062 .balign 64 5063.L_OP_ADD_DOUBLE: /* 0xab */ 5064/* File: arm-vfp/OP_ADD_DOUBLE.S */ 5065/* File: arm-vfp/fbinopWide.S */ 5066 /* 5067 * Generic 64-bit double-precision floating point binary operation. 5068 * Provide an "instr" line that specifies an instruction that performs 5069 * "d2 = d0 op d1". 5070 * 5071 * for: add-double, sub-double, mul-double, div-double 5072 */ 5073 /* doubleop vAA, vBB, vCC */ 5074 FETCH(r0, 1) @ r0<- CCBB 5075 mov r9, rINST, lsr #8 @ r9<- AA 5076 mov r3, r0, lsr #8 @ r3<- CC 5077 and r2, r0, #255 @ r2<- BB 5078 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5079 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5080 fldd d1, [r3] @ d1<- vCC 5081 fldd d0, [r2] @ d0<- vBB 5082 5083 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5084 faddd d2, d0, d1 @ s2<- op 5085 GET_INST_OPCODE(ip) @ extract opcode from rINST 5086 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5087 fstd d2, [r9] @ vAA<- d2 5088 GOTO_OPCODE(ip) @ jump to next instruction 5089 5090 5091/* ------------------------------ */ 5092 .balign 64 5093.L_OP_SUB_DOUBLE: /* 0xac */ 5094/* File: arm-vfp/OP_SUB_DOUBLE.S */ 5095/* File: arm-vfp/fbinopWide.S */ 5096 /* 5097 * Generic 64-bit double-precision floating point binary operation. 5098 * Provide an "instr" line that specifies an instruction that performs 5099 * "d2 = d0 op d1". 5100 * 5101 * for: add-double, sub-double, mul-double, div-double 5102 */ 5103 /* doubleop vAA, vBB, vCC */ 5104 FETCH(r0, 1) @ r0<- CCBB 5105 mov r9, rINST, lsr #8 @ r9<- AA 5106 mov r3, r0, lsr #8 @ r3<- CC 5107 and r2, r0, #255 @ r2<- BB 5108 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5109 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5110 fldd d1, [r3] @ d1<- vCC 5111 fldd d0, [r2] @ d0<- vBB 5112 5113 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5114 fsubd d2, d0, d1 @ s2<- op 5115 GET_INST_OPCODE(ip) @ extract opcode from rINST 5116 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5117 fstd d2, [r9] @ vAA<- d2 5118 GOTO_OPCODE(ip) @ jump to next instruction 5119 5120 5121/* ------------------------------ */ 5122 .balign 64 5123.L_OP_MUL_DOUBLE: /* 0xad */ 5124/* File: arm-vfp/OP_MUL_DOUBLE.S */ 5125/* File: arm-vfp/fbinopWide.S */ 5126 /* 5127 * Generic 64-bit double-precision floating point binary operation. 5128 * Provide an "instr" line that specifies an instruction that performs 5129 * "d2 = d0 op d1". 5130 * 5131 * for: add-double, sub-double, mul-double, div-double 5132 */ 5133 /* doubleop vAA, vBB, vCC */ 5134 FETCH(r0, 1) @ r0<- CCBB 5135 mov r9, rINST, lsr #8 @ r9<- AA 5136 mov r3, r0, lsr #8 @ r3<- CC 5137 and r2, r0, #255 @ r2<- BB 5138 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5139 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5140 fldd d1, [r3] @ d1<- vCC 5141 fldd d0, [r2] @ d0<- vBB 5142 5143 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5144 fmuld d2, d0, d1 @ s2<- op 5145 GET_INST_OPCODE(ip) @ extract opcode from rINST 5146 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5147 fstd d2, [r9] @ vAA<- d2 5148 GOTO_OPCODE(ip) @ jump to next instruction 5149 5150 5151/* ------------------------------ */ 5152 .balign 64 5153.L_OP_DIV_DOUBLE: /* 0xae */ 5154/* File: arm-vfp/OP_DIV_DOUBLE.S */ 5155/* File: arm-vfp/fbinopWide.S */ 5156 /* 5157 * Generic 64-bit double-precision floating point binary operation. 5158 * Provide an "instr" line that specifies an instruction that performs 5159 * "d2 = d0 op d1". 5160 * 5161 * for: add-double, sub-double, mul-double, div-double 5162 */ 5163 /* doubleop vAA, vBB, vCC */ 5164 FETCH(r0, 1) @ r0<- CCBB 5165 mov r9, rINST, lsr #8 @ r9<- AA 5166 mov r3, r0, lsr #8 @ r3<- CC 5167 and r2, r0, #255 @ r2<- BB 5168 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5169 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5170 fldd d1, [r3] @ d1<- vCC 5171 fldd d0, [r2] @ d0<- vBB 5172 5173 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5174 fdivd d2, d0, d1 @ s2<- op 5175 GET_INST_OPCODE(ip) @ extract opcode from rINST 5176 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5177 fstd d2, [r9] @ vAA<- d2 5178 GOTO_OPCODE(ip) @ jump to next instruction 5179 5180 5181/* ------------------------------ */ 5182 .balign 64 5183.L_OP_REM_DOUBLE: /* 0xaf */ 5184/* File: armv5te/OP_REM_DOUBLE.S */ 5185/* EABI doesn't define a double remainder function, but libm does */ 5186/* File: armv5te/binopWide.S */ 5187 /* 5188 * Generic 64-bit binary operation. Provide an "instr" line that 5189 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5190 * This could be an ARM instruction or a function call. (If the result 5191 * comes back in a register other than r0, you can override "result".) 5192 * 5193 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5194 * vCC (r1). Useful for integer division and modulus. 5195 * 5196 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5197 * xor-long, add-double, sub-double, mul-double, div-double, 5198 * rem-double 5199 * 5200 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5201 */ 5202 /* binop vAA, vBB, vCC */ 5203 FETCH(r0, 1) @ r0<- CCBB 5204 mov r9, rINST, lsr #8 @ r9<- AA 5205 and r2, r0, #255 @ r2<- BB 5206 mov r3, r0, lsr #8 @ r3<- CC 5207 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5208 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5209 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5210 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5211 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5212 .if 0 5213 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5214 beq common_errDivideByZero 5215 .endif 5216 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5217 5218 @ optional op; may set condition codes 5219 bl fmod @ result<- op, r0-r3 changed 5220 GET_INST_OPCODE(ip) @ extract opcode from rINST 5221 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5222 GOTO_OPCODE(ip) @ jump to next instruction 5223 /* 14-17 instructions */ 5224 5225 5226/* ------------------------------ */ 5227 .balign 64 5228.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5229/* File: armv6t2/OP_ADD_INT_2ADDR.S */ 5230/* File: armv6t2/binop2addr.S */ 5231 /* 5232 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5233 * that specifies an instruction that performs "result = r0 op r1". 5234 * This could be an ARM instruction or a function call. (If the result 5235 * comes back in a register other than r0, you can override "result".) 5236 * 5237 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5238 * vCC (r1). Useful for integer division and modulus. 5239 * 5240 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5241 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5242 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5243 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5244 */ 5245 /* binop/2addr vA, vB */ 5246 mov r3, rINST, lsr #12 @ r3<- B 5247 ubfx r9, rINST, #8, #4 @ r9<- A 5248 GET_VREG(r1, r3) @ r1<- vB 5249 GET_VREG(r0, r9) @ r0<- vA 5250 .if 0 5251 cmp r1, #0 @ is second operand zero? 5252 beq common_errDivideByZero 5253 .endif 5254 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5255 5256 @ optional op; may set condition codes 5257 add r0, r0, r1 @ r0<- op, r0-r3 changed 5258 GET_INST_OPCODE(ip) @ extract opcode from rINST 5259 SET_VREG(r0, r9) @ vAA<- r0 5260 GOTO_OPCODE(ip) @ jump to next instruction 5261 /* 10-13 instructions */ 5262 5263 5264/* ------------------------------ */ 5265 .balign 64 5266.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5267/* File: armv6t2/OP_SUB_INT_2ADDR.S */ 5268/* File: armv6t2/binop2addr.S */ 5269 /* 5270 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5271 * that specifies an instruction that performs "result = r0 op r1". 5272 * This could be an ARM instruction or a function call. (If the result 5273 * comes back in a register other than r0, you can override "result".) 5274 * 5275 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5276 * vCC (r1). Useful for integer division and modulus. 5277 * 5278 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5279 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5280 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5281 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5282 */ 5283 /* binop/2addr vA, vB */ 5284 mov r3, rINST, lsr #12 @ r3<- B 5285 ubfx r9, rINST, #8, #4 @ r9<- A 5286 GET_VREG(r1, r3) @ r1<- vB 5287 GET_VREG(r0, r9) @ r0<- vA 5288 .if 0 5289 cmp r1, #0 @ is second operand zero? 5290 beq common_errDivideByZero 5291 .endif 5292 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5293 5294 @ optional op; may set condition codes 5295 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5296 GET_INST_OPCODE(ip) @ extract opcode from rINST 5297 SET_VREG(r0, r9) @ vAA<- r0 5298 GOTO_OPCODE(ip) @ jump to next instruction 5299 /* 10-13 instructions */ 5300 5301 5302/* ------------------------------ */ 5303 .balign 64 5304.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5305/* File: armv6t2/OP_MUL_INT_2ADDR.S */ 5306/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5307/* File: armv6t2/binop2addr.S */ 5308 /* 5309 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5310 * that specifies an instruction that performs "result = r0 op r1". 5311 * This could be an ARM instruction or a function call. (If the result 5312 * comes back in a register other than r0, you can override "result".) 5313 * 5314 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5315 * vCC (r1). Useful for integer division and modulus. 5316 * 5317 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5318 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5319 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5320 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5321 */ 5322 /* binop/2addr vA, vB */ 5323 mov r3, rINST, lsr #12 @ r3<- B 5324 ubfx r9, rINST, #8, #4 @ r9<- A 5325 GET_VREG(r1, r3) @ r1<- vB 5326 GET_VREG(r0, r9) @ r0<- vA 5327 .if 0 5328 cmp r1, #0 @ is second operand zero? 5329 beq common_errDivideByZero 5330 .endif 5331 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5332 5333 @ optional op; may set condition codes 5334 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5335 GET_INST_OPCODE(ip) @ extract opcode from rINST 5336 SET_VREG(r0, r9) @ vAA<- r0 5337 GOTO_OPCODE(ip) @ jump to next instruction 5338 /* 10-13 instructions */ 5339 5340 5341/* ------------------------------ */ 5342 .balign 64 5343.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5344/* File: armv6t2/OP_DIV_INT_2ADDR.S */ 5345/* File: armv6t2/binop2addr.S */ 5346 /* 5347 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5348 * that specifies an instruction that performs "result = r0 op r1". 5349 * This could be an ARM instruction or a function call. (If the result 5350 * comes back in a register other than r0, you can override "result".) 5351 * 5352 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5353 * vCC (r1). Useful for integer division and modulus. 5354 * 5355 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5356 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5357 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5358 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5359 */ 5360 /* binop/2addr vA, vB */ 5361 mov r3, rINST, lsr #12 @ r3<- B 5362 ubfx r9, rINST, #8, #4 @ r9<- A 5363 GET_VREG(r1, r3) @ r1<- vB 5364 GET_VREG(r0, r9) @ r0<- vA 5365 .if 1 5366 cmp r1, #0 @ is second operand zero? 5367 beq common_errDivideByZero 5368 .endif 5369 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5370 5371 @ optional op; may set condition codes 5372 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5373 GET_INST_OPCODE(ip) @ extract opcode from rINST 5374 SET_VREG(r0, r9) @ vAA<- r0 5375 GOTO_OPCODE(ip) @ jump to next instruction 5376 /* 10-13 instructions */ 5377 5378 5379/* ------------------------------ */ 5380 .balign 64 5381.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5382/* File: armv6t2/OP_REM_INT_2ADDR.S */ 5383/* idivmod returns quotient in r0 and remainder in r1 */ 5384/* File: armv6t2/binop2addr.S */ 5385 /* 5386 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5387 * that specifies an instruction that performs "result = r0 op r1". 5388 * This could be an ARM instruction or a function call. (If the result 5389 * comes back in a register other than r0, you can override "result".) 5390 * 5391 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5392 * vCC (r1). Useful for integer division and modulus. 5393 * 5394 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5395 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5396 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5397 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5398 */ 5399 /* binop/2addr vA, vB */ 5400 mov r3, rINST, lsr #12 @ r3<- B 5401 ubfx r9, rINST, #8, #4 @ r9<- A 5402 GET_VREG(r1, r3) @ r1<- vB 5403 GET_VREG(r0, r9) @ r0<- vA 5404 .if 1 5405 cmp r1, #0 @ is second operand zero? 5406 beq common_errDivideByZero 5407 .endif 5408 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5409 5410 @ optional op; may set condition codes 5411 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5412 GET_INST_OPCODE(ip) @ extract opcode from rINST 5413 SET_VREG(r1, r9) @ vAA<- r1 5414 GOTO_OPCODE(ip) @ jump to next instruction 5415 /* 10-13 instructions */ 5416 5417 5418/* ------------------------------ */ 5419 .balign 64 5420.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5421/* File: armv6t2/OP_AND_INT_2ADDR.S */ 5422/* File: armv6t2/binop2addr.S */ 5423 /* 5424 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5425 * that specifies an instruction that performs "result = r0 op r1". 5426 * This could be an ARM instruction or a function call. (If the result 5427 * comes back in a register other than r0, you can override "result".) 5428 * 5429 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5430 * vCC (r1). Useful for integer division and modulus. 5431 * 5432 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5433 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5434 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5435 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5436 */ 5437 /* binop/2addr vA, vB */ 5438 mov r3, rINST, lsr #12 @ r3<- B 5439 ubfx r9, rINST, #8, #4 @ r9<- A 5440 GET_VREG(r1, r3) @ r1<- vB 5441 GET_VREG(r0, r9) @ r0<- vA 5442 .if 0 5443 cmp r1, #0 @ is second operand zero? 5444 beq common_errDivideByZero 5445 .endif 5446 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5447 5448 @ optional op; may set condition codes 5449 and r0, r0, r1 @ r0<- op, r0-r3 changed 5450 GET_INST_OPCODE(ip) @ extract opcode from rINST 5451 SET_VREG(r0, r9) @ vAA<- r0 5452 GOTO_OPCODE(ip) @ jump to next instruction 5453 /* 10-13 instructions */ 5454 5455 5456/* ------------------------------ */ 5457 .balign 64 5458.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5459/* File: armv6t2/OP_OR_INT_2ADDR.S */ 5460/* File: armv6t2/binop2addr.S */ 5461 /* 5462 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5463 * that specifies an instruction that performs "result = r0 op r1". 5464 * This could be an ARM instruction or a function call. (If the result 5465 * comes back in a register other than r0, you can override "result".) 5466 * 5467 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5468 * vCC (r1). Useful for integer division and modulus. 5469 * 5470 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5471 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5472 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5473 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5474 */ 5475 /* binop/2addr vA, vB */ 5476 mov r3, rINST, lsr #12 @ r3<- B 5477 ubfx r9, rINST, #8, #4 @ r9<- A 5478 GET_VREG(r1, r3) @ r1<- vB 5479 GET_VREG(r0, r9) @ r0<- vA 5480 .if 0 5481 cmp r1, #0 @ is second operand zero? 5482 beq common_errDivideByZero 5483 .endif 5484 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5485 5486 @ optional op; may set condition codes 5487 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5488 GET_INST_OPCODE(ip) @ extract opcode from rINST 5489 SET_VREG(r0, r9) @ vAA<- r0 5490 GOTO_OPCODE(ip) @ jump to next instruction 5491 /* 10-13 instructions */ 5492 5493 5494/* ------------------------------ */ 5495 .balign 64 5496.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5497/* File: armv6t2/OP_XOR_INT_2ADDR.S */ 5498/* File: armv6t2/binop2addr.S */ 5499 /* 5500 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5501 * that specifies an instruction that performs "result = r0 op r1". 5502 * This could be an ARM instruction or a function call. (If the result 5503 * comes back in a register other than r0, you can override "result".) 5504 * 5505 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5506 * vCC (r1). Useful for integer division and modulus. 5507 * 5508 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5509 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5510 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5511 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5512 */ 5513 /* binop/2addr vA, vB */ 5514 mov r3, rINST, lsr #12 @ r3<- B 5515 ubfx r9, rINST, #8, #4 @ r9<- A 5516 GET_VREG(r1, r3) @ r1<- vB 5517 GET_VREG(r0, r9) @ r0<- vA 5518 .if 0 5519 cmp r1, #0 @ is second operand zero? 5520 beq common_errDivideByZero 5521 .endif 5522 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5523 5524 @ optional op; may set condition codes 5525 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5526 GET_INST_OPCODE(ip) @ extract opcode from rINST 5527 SET_VREG(r0, r9) @ vAA<- r0 5528 GOTO_OPCODE(ip) @ jump to next instruction 5529 /* 10-13 instructions */ 5530 5531 5532/* ------------------------------ */ 5533 .balign 64 5534.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5535/* File: armv6t2/OP_SHL_INT_2ADDR.S */ 5536/* File: armv6t2/binop2addr.S */ 5537 /* 5538 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5539 * that specifies an instruction that performs "result = r0 op r1". 5540 * This could be an ARM instruction or a function call. (If the result 5541 * comes back in a register other than r0, you can override "result".) 5542 * 5543 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5544 * vCC (r1). Useful for integer division and modulus. 5545 * 5546 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5547 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5548 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5549 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5550 */ 5551 /* binop/2addr vA, vB */ 5552 mov r3, rINST, lsr #12 @ r3<- B 5553 ubfx r9, rINST, #8, #4 @ r9<- A 5554 GET_VREG(r1, r3) @ r1<- vB 5555 GET_VREG(r0, r9) @ r0<- vA 5556 .if 0 5557 cmp r1, #0 @ is second operand zero? 5558 beq common_errDivideByZero 5559 .endif 5560 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5561 5562 and r1, r1, #31 @ optional op; may set condition codes 5563 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5564 GET_INST_OPCODE(ip) @ extract opcode from rINST 5565 SET_VREG(r0, r9) @ vAA<- r0 5566 GOTO_OPCODE(ip) @ jump to next instruction 5567 /* 10-13 instructions */ 5568 5569 5570/* ------------------------------ */ 5571 .balign 64 5572.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5573/* File: armv6t2/OP_SHR_INT_2ADDR.S */ 5574/* File: armv6t2/binop2addr.S */ 5575 /* 5576 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5577 * that specifies an instruction that performs "result = r0 op r1". 5578 * This could be an ARM instruction or a function call. (If the result 5579 * comes back in a register other than r0, you can override "result".) 5580 * 5581 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5582 * vCC (r1). Useful for integer division and modulus. 5583 * 5584 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5585 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5586 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5587 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5588 */ 5589 /* binop/2addr vA, vB */ 5590 mov r3, rINST, lsr #12 @ r3<- B 5591 ubfx r9, rINST, #8, #4 @ r9<- A 5592 GET_VREG(r1, r3) @ r1<- vB 5593 GET_VREG(r0, r9) @ r0<- vA 5594 .if 0 5595 cmp r1, #0 @ is second operand zero? 5596 beq common_errDivideByZero 5597 .endif 5598 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5599 5600 and r1, r1, #31 @ optional op; may set condition codes 5601 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5602 GET_INST_OPCODE(ip) @ extract opcode from rINST 5603 SET_VREG(r0, r9) @ vAA<- r0 5604 GOTO_OPCODE(ip) @ jump to next instruction 5605 /* 10-13 instructions */ 5606 5607 5608/* ------------------------------ */ 5609 .balign 64 5610.L_OP_USHR_INT_2ADDR: /* 0xba */ 5611/* File: armv6t2/OP_USHR_INT_2ADDR.S */ 5612/* File: armv6t2/binop2addr.S */ 5613 /* 5614 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5615 * that specifies an instruction that performs "result = r0 op r1". 5616 * This could be an ARM instruction or a function call. (If the result 5617 * comes back in a register other than r0, you can override "result".) 5618 * 5619 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5620 * vCC (r1). Useful for integer division and modulus. 5621 * 5622 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5623 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5624 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5625 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5626 */ 5627 /* binop/2addr vA, vB */ 5628 mov r3, rINST, lsr #12 @ r3<- B 5629 ubfx r9, rINST, #8, #4 @ r9<- A 5630 GET_VREG(r1, r3) @ r1<- vB 5631 GET_VREG(r0, r9) @ r0<- vA 5632 .if 0 5633 cmp r1, #0 @ is second operand zero? 5634 beq common_errDivideByZero 5635 .endif 5636 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5637 5638 and r1, r1, #31 @ optional op; may set condition codes 5639 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5640 GET_INST_OPCODE(ip) @ extract opcode from rINST 5641 SET_VREG(r0, r9) @ vAA<- r0 5642 GOTO_OPCODE(ip) @ jump to next instruction 5643 /* 10-13 instructions */ 5644 5645 5646/* ------------------------------ */ 5647 .balign 64 5648.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5649/* File: armv6t2/OP_ADD_LONG_2ADDR.S */ 5650/* File: armv6t2/binopWide2addr.S */ 5651 /* 5652 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5653 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5654 * This could be an ARM instruction or a function call. (If the result 5655 * comes back in a register other than r0, you can override "result".) 5656 * 5657 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5658 * vCC (r1). Useful for integer division and modulus. 5659 * 5660 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5661 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5662 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5663 * rem-double/2addr 5664 */ 5665 /* binop/2addr vA, vB */ 5666 mov r1, rINST, lsr #12 @ r1<- B 5667 ubfx r9, rINST, #8, #4 @ r9<- A 5668 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5669 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5670 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5671 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5672 .if 0 5673 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5674 beq common_errDivideByZero 5675 .endif 5676 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5677 5678 adds r0, r0, r2 @ optional op; may set condition codes 5679 adc r1, r1, r3 @ result<- op, r0-r3 changed 5680 GET_INST_OPCODE(ip) @ extract opcode from rINST 5681 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5682 GOTO_OPCODE(ip) @ jump to next instruction 5683 /* 12-15 instructions */ 5684 5685 5686/* ------------------------------ */ 5687 .balign 64 5688.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5689/* File: armv6t2/OP_SUB_LONG_2ADDR.S */ 5690/* File: armv6t2/binopWide2addr.S */ 5691 /* 5692 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5693 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5694 * This could be an ARM instruction or a function call. (If the result 5695 * comes back in a register other than r0, you can override "result".) 5696 * 5697 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5698 * vCC (r1). Useful for integer division and modulus. 5699 * 5700 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5701 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5702 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5703 * rem-double/2addr 5704 */ 5705 /* binop/2addr vA, vB */ 5706 mov r1, rINST, lsr #12 @ r1<- B 5707 ubfx r9, rINST, #8, #4 @ r9<- A 5708 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5709 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5710 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5711 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5712 .if 0 5713 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5714 beq common_errDivideByZero 5715 .endif 5716 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5717 5718 subs r0, r0, r2 @ optional op; may set condition codes 5719 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5720 GET_INST_OPCODE(ip) @ extract opcode from rINST 5721 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5722 GOTO_OPCODE(ip) @ jump to next instruction 5723 /* 12-15 instructions */ 5724 5725 5726/* ------------------------------ */ 5727 .balign 64 5728.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 5729/* File: armv6t2/OP_MUL_LONG_2ADDR.S */ 5730 /* 5731 * Signed 64-bit integer multiply, "/2addr" version. 5732 * 5733 * See OP_MUL_LONG for an explanation. 5734 * 5735 * We get a little tight on registers, so to avoid looking up &fp[A] 5736 * again we stuff it into rINST. 5737 */ 5738 /* mul-long/2addr vA, vB */ 5739 mov r1, rINST, lsr #12 @ r1<- B 5740 ubfx r9, rINST, #8, #4 @ r9<- A 5741 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5742 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 5743 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5744 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 5745 mul ip, r2, r1 @ ip<- ZxW 5746 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 5747 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 5748 mov r0, rINST @ r0<- &fp[A] (free up rINST) 5749 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5750 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 5751 GET_INST_OPCODE(ip) @ extract opcode from rINST 5752 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 5753 GOTO_OPCODE(ip) @ jump to next instruction 5754 5755/* ------------------------------ */ 5756 .balign 64 5757.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 5758/* File: armv6t2/OP_DIV_LONG_2ADDR.S */ 5759/* File: armv6t2/binopWide2addr.S */ 5760 /* 5761 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5762 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5763 * This could be an ARM instruction or a function call. (If the result 5764 * comes back in a register other than r0, you can override "result".) 5765 * 5766 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5767 * vCC (r1). Useful for integer division and modulus. 5768 * 5769 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5770 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5771 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5772 * rem-double/2addr 5773 */ 5774 /* binop/2addr vA, vB */ 5775 mov r1, rINST, lsr #12 @ r1<- B 5776 ubfx r9, rINST, #8, #4 @ r9<- A 5777 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5778 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5779 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5780 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5781 .if 1 5782 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5783 beq common_errDivideByZero 5784 .endif 5785 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5786 5787 @ optional op; may set condition codes 5788 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5789 GET_INST_OPCODE(ip) @ extract opcode from rINST 5790 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5791 GOTO_OPCODE(ip) @ jump to next instruction 5792 /* 12-15 instructions */ 5793 5794 5795/* ------------------------------ */ 5796 .balign 64 5797.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5798/* File: armv6t2/OP_REM_LONG_2ADDR.S */ 5799/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 5800/* File: armv6t2/binopWide2addr.S */ 5801 /* 5802 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5803 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5804 * This could be an ARM instruction or a function call. (If the result 5805 * comes back in a register other than r0, you can override "result".) 5806 * 5807 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5808 * vCC (r1). Useful for integer division and modulus. 5809 * 5810 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5811 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5812 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5813 * rem-double/2addr 5814 */ 5815 /* binop/2addr vA, vB */ 5816 mov r1, rINST, lsr #12 @ r1<- B 5817 ubfx r9, rINST, #8, #4 @ r9<- A 5818 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5819 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5820 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5821 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5822 .if 1 5823 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5824 beq common_errDivideByZero 5825 .endif 5826 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5827 5828 @ optional op; may set condition codes 5829 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5830 GET_INST_OPCODE(ip) @ extract opcode from rINST 5831 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 5832 GOTO_OPCODE(ip) @ jump to next instruction 5833 /* 12-15 instructions */ 5834 5835 5836/* ------------------------------ */ 5837 .balign 64 5838.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 5839/* File: armv6t2/OP_AND_LONG_2ADDR.S */ 5840/* File: armv6t2/binopWide2addr.S */ 5841 /* 5842 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5843 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5844 * This could be an ARM instruction or a function call. (If the result 5845 * comes back in a register other than r0, you can override "result".) 5846 * 5847 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5848 * vCC (r1). Useful for integer division and modulus. 5849 * 5850 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5851 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5852 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5853 * rem-double/2addr 5854 */ 5855 /* binop/2addr vA, vB */ 5856 mov r1, rINST, lsr #12 @ r1<- B 5857 ubfx r9, rINST, #8, #4 @ r9<- A 5858 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5859 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5860 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5861 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5862 .if 0 5863 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5864 beq common_errDivideByZero 5865 .endif 5866 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5867 5868 and r0, r0, r2 @ optional op; may set condition codes 5869 and r1, r1, r3 @ result<- op, r0-r3 changed 5870 GET_INST_OPCODE(ip) @ extract opcode from rINST 5871 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5872 GOTO_OPCODE(ip) @ jump to next instruction 5873 /* 12-15 instructions */ 5874 5875 5876/* ------------------------------ */ 5877 .balign 64 5878.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 5879/* File: armv6t2/OP_OR_LONG_2ADDR.S */ 5880/* File: armv6t2/binopWide2addr.S */ 5881 /* 5882 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5883 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5884 * This could be an ARM instruction or a function call. (If the result 5885 * comes back in a register other than r0, you can override "result".) 5886 * 5887 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5888 * vCC (r1). Useful for integer division and modulus. 5889 * 5890 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5891 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5892 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5893 * rem-double/2addr 5894 */ 5895 /* binop/2addr vA, vB */ 5896 mov r1, rINST, lsr #12 @ r1<- B 5897 ubfx r9, rINST, #8, #4 @ r9<- A 5898 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5899 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5900 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5901 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5902 .if 0 5903 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5904 beq common_errDivideByZero 5905 .endif 5906 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5907 5908 orr r0, r0, r2 @ optional op; may set condition codes 5909 orr r1, r1, r3 @ result<- op, r0-r3 changed 5910 GET_INST_OPCODE(ip) @ extract opcode from rINST 5911 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5912 GOTO_OPCODE(ip) @ jump to next instruction 5913 /* 12-15 instructions */ 5914 5915 5916/* ------------------------------ */ 5917 .balign 64 5918.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 5919/* File: armv6t2/OP_XOR_LONG_2ADDR.S */ 5920/* File: armv6t2/binopWide2addr.S */ 5921 /* 5922 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5923 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5924 * This could be an ARM instruction or a function call. (If the result 5925 * comes back in a register other than r0, you can override "result".) 5926 * 5927 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5928 * vCC (r1). Useful for integer division and modulus. 5929 * 5930 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5931 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5932 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5933 * rem-double/2addr 5934 */ 5935 /* binop/2addr vA, vB */ 5936 mov r1, rINST, lsr #12 @ r1<- B 5937 ubfx r9, rINST, #8, #4 @ r9<- A 5938 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5939 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5940 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5941 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5942 .if 0 5943 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5944 beq common_errDivideByZero 5945 .endif 5946 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5947 5948 eor r0, r0, r2 @ optional op; may set condition codes 5949 eor r1, r1, r3 @ result<- op, r0-r3 changed 5950 GET_INST_OPCODE(ip) @ extract opcode from rINST 5951 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5952 GOTO_OPCODE(ip) @ jump to next instruction 5953 /* 12-15 instructions */ 5954 5955 5956/* ------------------------------ */ 5957 .balign 64 5958.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 5959/* File: armv6t2/OP_SHL_LONG_2ADDR.S */ 5960 /* 5961 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 5962 * 32-bit shift distance. 5963 */ 5964 /* shl-long/2addr vA, vB */ 5965 mov r3, rINST, lsr #12 @ r3<- B 5966 ubfx r9, rINST, #8, #4 @ r9<- A 5967 GET_VREG(r2, r3) @ r2<- vB 5968 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5969 and r2, r2, #63 @ r2<- r2 & 0x3f 5970 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5971 5972 mov r1, r1, asl r2 @ r1<- r1 << r2 5973 rsb r3, r2, #32 @ r3<- 32 - r2 5974 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 5975 subs ip, r2, #32 @ ip<- r2 - 32 5976 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5977 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 5978 mov r0, r0, asl r2 @ r0<- r0 << r2 5979 b .LOP_SHL_LONG_2ADDR_finish 5980 5981/* ------------------------------ */ 5982 .balign 64 5983.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 5984/* File: armv6t2/OP_SHR_LONG_2ADDR.S */ 5985 /* 5986 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 5987 * 32-bit shift distance. 5988 */ 5989 /* shr-long/2addr vA, vB */ 5990 mov r3, rINST, lsr #12 @ r3<- B 5991 ubfx r9, rINST, #8, #4 @ r9<- A 5992 GET_VREG(r2, r3) @ r2<- vB 5993 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5994 and r2, r2, #63 @ r2<- r2 & 0x3f 5995 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5996 5997 mov r0, r0, lsr r2 @ r0<- r2 >> r2 5998 rsb r3, r2, #32 @ r3<- 32 - r2 5999 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6000 subs ip, r2, #32 @ ip<- r2 - 32 6001 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6002 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6003 mov r1, r1, asr r2 @ r1<- r1 >> r2 6004 b .LOP_SHR_LONG_2ADDR_finish 6005 6006/* ------------------------------ */ 6007 .balign 64 6008.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6009/* File: armv6t2/OP_USHR_LONG_2ADDR.S */ 6010 /* 6011 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6012 * 32-bit shift distance. 6013 */ 6014 /* ushr-long/2addr vA, vB */ 6015 mov r3, rINST, lsr #12 @ r3<- B 6016 ubfx r9, rINST, #8, #4 @ r9<- A 6017 GET_VREG(r2, r3) @ r2<- vB 6018 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6019 and r2, r2, #63 @ r2<- r2 & 0x3f 6020 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6021 6022 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6023 rsb r3, r2, #32 @ r3<- 32 - r2 6024 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6025 subs ip, r2, #32 @ ip<- r2 - 32 6026 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6027 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6028 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6029 b .LOP_USHR_LONG_2ADDR_finish 6030 6031/* ------------------------------ */ 6032 .balign 64 6033.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6034/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */ 6035/* File: arm-vfp/fbinop2addr.S */ 6036 /* 6037 * Generic 32-bit floating point "/2addr" binary operation. Provide 6038 * an "instr" line that specifies an instruction that performs 6039 * "s2 = s0 op s1". 6040 * 6041 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6042 */ 6043 /* binop/2addr vA, vB */ 6044 mov r3, rINST, lsr #12 @ r3<- B 6045 mov r9, rINST, lsr #8 @ r9<- A+ 6046 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6047 and r9, r9, #15 @ r9<- A 6048 flds s1, [r3] @ s1<- vB 6049 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6050 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6051 flds s0, [r9] @ s0<- vA 6052 6053 fadds s2, s0, s1 @ s2<- op 6054 GET_INST_OPCODE(ip) @ extract opcode from rINST 6055 fsts s2, [r9] @ vAA<- s2 6056 GOTO_OPCODE(ip) @ jump to next instruction 6057 6058 6059/* ------------------------------ */ 6060 .balign 64 6061.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6062/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */ 6063/* File: arm-vfp/fbinop2addr.S */ 6064 /* 6065 * Generic 32-bit floating point "/2addr" binary operation. Provide 6066 * an "instr" line that specifies an instruction that performs 6067 * "s2 = s0 op s1". 6068 * 6069 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6070 */ 6071 /* binop/2addr vA, vB */ 6072 mov r3, rINST, lsr #12 @ r3<- B 6073 mov r9, rINST, lsr #8 @ r9<- A+ 6074 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6075 and r9, r9, #15 @ r9<- A 6076 flds s1, [r3] @ s1<- vB 6077 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6078 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6079 flds s0, [r9] @ s0<- vA 6080 6081 fsubs s2, s0, s1 @ s2<- op 6082 GET_INST_OPCODE(ip) @ extract opcode from rINST 6083 fsts s2, [r9] @ vAA<- s2 6084 GOTO_OPCODE(ip) @ jump to next instruction 6085 6086 6087/* ------------------------------ */ 6088 .balign 64 6089.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6090/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */ 6091/* File: arm-vfp/fbinop2addr.S */ 6092 /* 6093 * Generic 32-bit floating point "/2addr" binary operation. Provide 6094 * an "instr" line that specifies an instruction that performs 6095 * "s2 = s0 op s1". 6096 * 6097 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6098 */ 6099 /* binop/2addr vA, vB */ 6100 mov r3, rINST, lsr #12 @ r3<- B 6101 mov r9, rINST, lsr #8 @ r9<- A+ 6102 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6103 and r9, r9, #15 @ r9<- A 6104 flds s1, [r3] @ s1<- vB 6105 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6106 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6107 flds s0, [r9] @ s0<- vA 6108 6109 fmuls s2, s0, s1 @ s2<- op 6110 GET_INST_OPCODE(ip) @ extract opcode from rINST 6111 fsts s2, [r9] @ vAA<- s2 6112 GOTO_OPCODE(ip) @ jump to next instruction 6113 6114 6115/* ------------------------------ */ 6116 .balign 64 6117.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6118/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */ 6119/* File: arm-vfp/fbinop2addr.S */ 6120 /* 6121 * Generic 32-bit floating point "/2addr" binary operation. Provide 6122 * an "instr" line that specifies an instruction that performs 6123 * "s2 = s0 op s1". 6124 * 6125 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6126 */ 6127 /* binop/2addr vA, vB */ 6128 mov r3, rINST, lsr #12 @ r3<- B 6129 mov r9, rINST, lsr #8 @ r9<- A+ 6130 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6131 and r9, r9, #15 @ r9<- A 6132 flds s1, [r3] @ s1<- vB 6133 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6134 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6135 flds s0, [r9] @ s0<- vA 6136 6137 fdivs s2, s0, s1 @ s2<- op 6138 GET_INST_OPCODE(ip) @ extract opcode from rINST 6139 fsts s2, [r9] @ vAA<- s2 6140 GOTO_OPCODE(ip) @ jump to next instruction 6141 6142 6143/* ------------------------------ */ 6144 .balign 64 6145.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6146/* File: armv6t2/OP_REM_FLOAT_2ADDR.S */ 6147/* EABI doesn't define a float remainder function, but libm does */ 6148/* File: armv6t2/binop2addr.S */ 6149 /* 6150 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6151 * that specifies an instruction that performs "result = r0 op r1". 6152 * This could be an ARM instruction or a function call. (If the result 6153 * comes back in a register other than r0, you can override "result".) 6154 * 6155 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6156 * vCC (r1). Useful for integer division and modulus. 6157 * 6158 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6159 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6160 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6161 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6162 */ 6163 /* binop/2addr vA, vB */ 6164 mov r3, rINST, lsr #12 @ r3<- B 6165 ubfx r9, rINST, #8, #4 @ r9<- A 6166 GET_VREG(r1, r3) @ r1<- vB 6167 GET_VREG(r0, r9) @ r0<- vA 6168 .if 0 6169 cmp r1, #0 @ is second operand zero? 6170 beq common_errDivideByZero 6171 .endif 6172 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6173 6174 @ optional op; may set condition codes 6175 bl fmodf @ r0<- op, r0-r3 changed 6176 GET_INST_OPCODE(ip) @ extract opcode from rINST 6177 SET_VREG(r0, r9) @ vAA<- r0 6178 GOTO_OPCODE(ip) @ jump to next instruction 6179 /* 10-13 instructions */ 6180 6181 6182/* ------------------------------ */ 6183 .balign 64 6184.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6185/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */ 6186/* File: arm-vfp/fbinopWide2addr.S */ 6187 /* 6188 * Generic 64-bit floating point "/2addr" binary operation. Provide 6189 * an "instr" line that specifies an instruction that performs 6190 * "d2 = d0 op d1". 6191 * 6192 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6193 * div-double/2addr 6194 */ 6195 /* binop/2addr vA, vB */ 6196 mov r3, rINST, lsr #12 @ r3<- B 6197 mov r9, rINST, lsr #8 @ r9<- A+ 6198 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6199 and r9, r9, #15 @ r9<- A 6200 fldd d1, [r3] @ d1<- vB 6201 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6202 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6203 fldd d0, [r9] @ d0<- vA 6204 6205 faddd d2, d0, d1 @ d2<- op 6206 GET_INST_OPCODE(ip) @ extract opcode from rINST 6207 fstd d2, [r9] @ vAA<- d2 6208 GOTO_OPCODE(ip) @ jump to next instruction 6209 6210 6211/* ------------------------------ */ 6212 .balign 64 6213.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6214/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */ 6215/* File: arm-vfp/fbinopWide2addr.S */ 6216 /* 6217 * Generic 64-bit floating point "/2addr" binary operation. Provide 6218 * an "instr" line that specifies an instruction that performs 6219 * "d2 = d0 op d1". 6220 * 6221 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6222 * div-double/2addr 6223 */ 6224 /* binop/2addr vA, vB */ 6225 mov r3, rINST, lsr #12 @ r3<- B 6226 mov r9, rINST, lsr #8 @ r9<- A+ 6227 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6228 and r9, r9, #15 @ r9<- A 6229 fldd d1, [r3] @ d1<- vB 6230 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6231 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6232 fldd d0, [r9] @ d0<- vA 6233 6234 fsubd d2, d0, d1 @ d2<- op 6235 GET_INST_OPCODE(ip) @ extract opcode from rINST 6236 fstd d2, [r9] @ vAA<- d2 6237 GOTO_OPCODE(ip) @ jump to next instruction 6238 6239 6240/* ------------------------------ */ 6241 .balign 64 6242.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6243/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */ 6244/* File: arm-vfp/fbinopWide2addr.S */ 6245 /* 6246 * Generic 64-bit floating point "/2addr" binary operation. Provide 6247 * an "instr" line that specifies an instruction that performs 6248 * "d2 = d0 op d1". 6249 * 6250 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6251 * div-double/2addr 6252 */ 6253 /* binop/2addr vA, vB */ 6254 mov r3, rINST, lsr #12 @ r3<- B 6255 mov r9, rINST, lsr #8 @ r9<- A+ 6256 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6257 and r9, r9, #15 @ r9<- A 6258 fldd d1, [r3] @ d1<- vB 6259 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6260 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6261 fldd d0, [r9] @ d0<- vA 6262 6263 fmuld d2, d0, d1 @ d2<- op 6264 GET_INST_OPCODE(ip) @ extract opcode from rINST 6265 fstd d2, [r9] @ vAA<- d2 6266 GOTO_OPCODE(ip) @ jump to next instruction 6267 6268 6269/* ------------------------------ */ 6270 .balign 64 6271.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6272/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */ 6273/* File: arm-vfp/fbinopWide2addr.S */ 6274 /* 6275 * Generic 64-bit floating point "/2addr" binary operation. Provide 6276 * an "instr" line that specifies an instruction that performs 6277 * "d2 = d0 op d1". 6278 * 6279 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6280 * div-double/2addr 6281 */ 6282 /* binop/2addr vA, vB */ 6283 mov r3, rINST, lsr #12 @ r3<- B 6284 mov r9, rINST, lsr #8 @ r9<- A+ 6285 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6286 and r9, r9, #15 @ r9<- A 6287 fldd d1, [r3] @ d1<- vB 6288 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6289 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6290 fldd d0, [r9] @ d0<- vA 6291 6292 fdivd d2, d0, d1 @ d2<- op 6293 GET_INST_OPCODE(ip) @ extract opcode from rINST 6294 fstd d2, [r9] @ vAA<- d2 6295 GOTO_OPCODE(ip) @ jump to next instruction 6296 6297 6298/* ------------------------------ */ 6299 .balign 64 6300.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6301/* File: armv6t2/OP_REM_DOUBLE_2ADDR.S */ 6302/* EABI doesn't define a double remainder function, but libm does */ 6303/* File: armv6t2/binopWide2addr.S */ 6304 /* 6305 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6306 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6307 * This could be an ARM instruction or a function call. (If the result 6308 * comes back in a register other than r0, you can override "result".) 6309 * 6310 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6311 * vCC (r1). Useful for integer division and modulus. 6312 * 6313 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6314 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6315 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6316 * rem-double/2addr 6317 */ 6318 /* binop/2addr vA, vB */ 6319 mov r1, rINST, lsr #12 @ r1<- B 6320 ubfx r9, rINST, #8, #4 @ r9<- A 6321 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6322 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6323 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6324 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6325 .if 0 6326 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6327 beq common_errDivideByZero 6328 .endif 6329 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6330 6331 @ optional op; may set condition codes 6332 bl fmod @ result<- op, r0-r3 changed 6333 GET_INST_OPCODE(ip) @ extract opcode from rINST 6334 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6335 GOTO_OPCODE(ip) @ jump to next instruction 6336 /* 12-15 instructions */ 6337 6338 6339/* ------------------------------ */ 6340 .balign 64 6341.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6342/* File: armv6t2/OP_ADD_INT_LIT16.S */ 6343/* File: armv6t2/binopLit16.S */ 6344 /* 6345 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6346 * that specifies an instruction that performs "result = r0 op r1". 6347 * This could be an ARM instruction or a function call. (If the result 6348 * comes back in a register other than r0, you can override "result".) 6349 * 6350 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6351 * vCC (r1). Useful for integer division and modulus. 6352 * 6353 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6354 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6355 */ 6356 /* binop/lit16 vA, vB, #+CCCC */ 6357 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6358 mov r2, rINST, lsr #12 @ r2<- B 6359 ubfx r9, rINST, #8, #4 @ r9<- A 6360 GET_VREG(r0, r2) @ r0<- vB 6361 .if 0 6362 cmp r1, #0 @ is second operand zero? 6363 beq common_errDivideByZero 6364 .endif 6365 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6366 6367 add r0, r0, r1 @ r0<- op, r0-r3 changed 6368 GET_INST_OPCODE(ip) @ extract opcode from rINST 6369 SET_VREG(r0, r9) @ vAA<- r0 6370 GOTO_OPCODE(ip) @ jump to next instruction 6371 /* 10-13 instructions */ 6372 6373 6374/* ------------------------------ */ 6375 .balign 64 6376.L_OP_RSUB_INT: /* 0xd1 */ 6377/* File: armv6t2/OP_RSUB_INT.S */ 6378/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6379/* File: armv6t2/binopLit16.S */ 6380 /* 6381 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6382 * that specifies an instruction that performs "result = r0 op r1". 6383 * This could be an ARM instruction or a function call. (If the result 6384 * comes back in a register other than r0, you can override "result".) 6385 * 6386 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6387 * vCC (r1). Useful for integer division and modulus. 6388 * 6389 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6390 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6391 */ 6392 /* binop/lit16 vA, vB, #+CCCC */ 6393 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6394 mov r2, rINST, lsr #12 @ r2<- B 6395 ubfx r9, rINST, #8, #4 @ r9<- A 6396 GET_VREG(r0, r2) @ r0<- vB 6397 .if 0 6398 cmp r1, #0 @ is second operand zero? 6399 beq common_errDivideByZero 6400 .endif 6401 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6402 6403 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6404 GET_INST_OPCODE(ip) @ extract opcode from rINST 6405 SET_VREG(r0, r9) @ vAA<- r0 6406 GOTO_OPCODE(ip) @ jump to next instruction 6407 /* 10-13 instructions */ 6408 6409 6410/* ------------------------------ */ 6411 .balign 64 6412.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6413/* File: armv6t2/OP_MUL_INT_LIT16.S */ 6414/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6415/* File: armv6t2/binopLit16.S */ 6416 /* 6417 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6418 * that specifies an instruction that performs "result = r0 op r1". 6419 * This could be an ARM instruction or a function call. (If the result 6420 * comes back in a register other than r0, you can override "result".) 6421 * 6422 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6423 * vCC (r1). Useful for integer division and modulus. 6424 * 6425 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6426 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6427 */ 6428 /* binop/lit16 vA, vB, #+CCCC */ 6429 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6430 mov r2, rINST, lsr #12 @ r2<- B 6431 ubfx r9, rINST, #8, #4 @ r9<- A 6432 GET_VREG(r0, r2) @ r0<- vB 6433 .if 0 6434 cmp r1, #0 @ is second operand zero? 6435 beq common_errDivideByZero 6436 .endif 6437 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6438 6439 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6440 GET_INST_OPCODE(ip) @ extract opcode from rINST 6441 SET_VREG(r0, r9) @ vAA<- r0 6442 GOTO_OPCODE(ip) @ jump to next instruction 6443 /* 10-13 instructions */ 6444 6445 6446/* ------------------------------ */ 6447 .balign 64 6448.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6449/* File: armv6t2/OP_DIV_INT_LIT16.S */ 6450/* File: armv6t2/binopLit16.S */ 6451 /* 6452 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6453 * that specifies an instruction that performs "result = r0 op r1". 6454 * This could be an ARM instruction or a function call. (If the result 6455 * comes back in a register other than r0, you can override "result".) 6456 * 6457 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6458 * vCC (r1). Useful for integer division and modulus. 6459 * 6460 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6461 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6462 */ 6463 /* binop/lit16 vA, vB, #+CCCC */ 6464 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6465 mov r2, rINST, lsr #12 @ r2<- B 6466 ubfx r9, rINST, #8, #4 @ r9<- A 6467 GET_VREG(r0, r2) @ r0<- vB 6468 .if 1 6469 cmp r1, #0 @ is second operand zero? 6470 beq common_errDivideByZero 6471 .endif 6472 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6473 6474 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6475 GET_INST_OPCODE(ip) @ extract opcode from rINST 6476 SET_VREG(r0, r9) @ vAA<- r0 6477 GOTO_OPCODE(ip) @ jump to next instruction 6478 /* 10-13 instructions */ 6479 6480 6481/* ------------------------------ */ 6482 .balign 64 6483.L_OP_REM_INT_LIT16: /* 0xd4 */ 6484/* File: armv6t2/OP_REM_INT_LIT16.S */ 6485/* idivmod returns quotient in r0 and remainder in r1 */ 6486/* File: armv6t2/binopLit16.S */ 6487 /* 6488 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6489 * that specifies an instruction that performs "result = r0 op r1". 6490 * This could be an ARM instruction or a function call. (If the result 6491 * comes back in a register other than r0, you can override "result".) 6492 * 6493 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6494 * vCC (r1). Useful for integer division and modulus. 6495 * 6496 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6497 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6498 */ 6499 /* binop/lit16 vA, vB, #+CCCC */ 6500 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6501 mov r2, rINST, lsr #12 @ r2<- B 6502 ubfx r9, rINST, #8, #4 @ r9<- A 6503 GET_VREG(r0, r2) @ r0<- vB 6504 .if 1 6505 cmp r1, #0 @ is second operand zero? 6506 beq common_errDivideByZero 6507 .endif 6508 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6509 6510 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6511 GET_INST_OPCODE(ip) @ extract opcode from rINST 6512 SET_VREG(r1, r9) @ vAA<- r1 6513 GOTO_OPCODE(ip) @ jump to next instruction 6514 /* 10-13 instructions */ 6515 6516 6517/* ------------------------------ */ 6518 .balign 64 6519.L_OP_AND_INT_LIT16: /* 0xd5 */ 6520/* File: armv6t2/OP_AND_INT_LIT16.S */ 6521/* File: armv6t2/binopLit16.S */ 6522 /* 6523 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6524 * that specifies an instruction that performs "result = r0 op r1". 6525 * This could be an ARM instruction or a function call. (If the result 6526 * comes back in a register other than r0, you can override "result".) 6527 * 6528 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6529 * vCC (r1). Useful for integer division and modulus. 6530 * 6531 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6532 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6533 */ 6534 /* binop/lit16 vA, vB, #+CCCC */ 6535 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6536 mov r2, rINST, lsr #12 @ r2<- B 6537 ubfx r9, rINST, #8, #4 @ r9<- A 6538 GET_VREG(r0, r2) @ r0<- vB 6539 .if 0 6540 cmp r1, #0 @ is second operand zero? 6541 beq common_errDivideByZero 6542 .endif 6543 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6544 6545 and r0, r0, r1 @ r0<- op, r0-r3 changed 6546 GET_INST_OPCODE(ip) @ extract opcode from rINST 6547 SET_VREG(r0, r9) @ vAA<- r0 6548 GOTO_OPCODE(ip) @ jump to next instruction 6549 /* 10-13 instructions */ 6550 6551 6552/* ------------------------------ */ 6553 .balign 64 6554.L_OP_OR_INT_LIT16: /* 0xd6 */ 6555/* File: armv6t2/OP_OR_INT_LIT16.S */ 6556/* File: armv6t2/binopLit16.S */ 6557 /* 6558 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6559 * that specifies an instruction that performs "result = r0 op r1". 6560 * This could be an ARM instruction or a function call. (If the result 6561 * comes back in a register other than r0, you can override "result".) 6562 * 6563 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6564 * vCC (r1). Useful for integer division and modulus. 6565 * 6566 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6567 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6568 */ 6569 /* binop/lit16 vA, vB, #+CCCC */ 6570 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6571 mov r2, rINST, lsr #12 @ r2<- B 6572 ubfx r9, rINST, #8, #4 @ r9<- A 6573 GET_VREG(r0, r2) @ r0<- vB 6574 .if 0 6575 cmp r1, #0 @ is second operand zero? 6576 beq common_errDivideByZero 6577 .endif 6578 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6579 6580 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6581 GET_INST_OPCODE(ip) @ extract opcode from rINST 6582 SET_VREG(r0, r9) @ vAA<- r0 6583 GOTO_OPCODE(ip) @ jump to next instruction 6584 /* 10-13 instructions */ 6585 6586 6587/* ------------------------------ */ 6588 .balign 64 6589.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6590/* File: armv6t2/OP_XOR_INT_LIT16.S */ 6591/* File: armv6t2/binopLit16.S */ 6592 /* 6593 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6594 * that specifies an instruction that performs "result = r0 op r1". 6595 * This could be an ARM instruction or a function call. (If the result 6596 * comes back in a register other than r0, you can override "result".) 6597 * 6598 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6599 * vCC (r1). Useful for integer division and modulus. 6600 * 6601 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6602 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6603 */ 6604 /* binop/lit16 vA, vB, #+CCCC */ 6605 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6606 mov r2, rINST, lsr #12 @ r2<- B 6607 ubfx r9, rINST, #8, #4 @ r9<- A 6608 GET_VREG(r0, r2) @ r0<- vB 6609 .if 0 6610 cmp r1, #0 @ is second operand zero? 6611 beq common_errDivideByZero 6612 .endif 6613 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6614 6615 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6616 GET_INST_OPCODE(ip) @ extract opcode from rINST 6617 SET_VREG(r0, r9) @ vAA<- r0 6618 GOTO_OPCODE(ip) @ jump to next instruction 6619 /* 10-13 instructions */ 6620 6621 6622/* ------------------------------ */ 6623 .balign 64 6624.L_OP_ADD_INT_LIT8: /* 0xd8 */ 6625/* File: armv5te/OP_ADD_INT_LIT8.S */ 6626/* File: armv5te/binopLit8.S */ 6627 /* 6628 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6629 * that specifies an instruction that performs "result = r0 op r1". 6630 * This could be an ARM instruction or a function call. (If the result 6631 * comes back in a register other than r0, you can override "result".) 6632 * 6633 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6634 * vCC (r1). Useful for integer division and modulus. 6635 * 6636 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6637 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6638 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6639 */ 6640 /* binop/lit8 vAA, vBB, #+CC */ 6641 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6642 mov r9, rINST, lsr #8 @ r9<- AA 6643 and r2, r3, #255 @ r2<- BB 6644 GET_VREG(r0, r2) @ r0<- vBB 6645 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6646 .if 0 6647 @cmp r1, #0 @ is second operand zero? 6648 beq common_errDivideByZero 6649 .endif 6650 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6651 6652 @ optional op; may set condition codes 6653 add r0, r0, r1 @ r0<- op, r0-r3 changed 6654 GET_INST_OPCODE(ip) @ extract opcode from rINST 6655 SET_VREG(r0, r9) @ vAA<- r0 6656 GOTO_OPCODE(ip) @ jump to next instruction 6657 /* 10-12 instructions */ 6658 6659 6660/* ------------------------------ */ 6661 .balign 64 6662.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 6663/* File: armv5te/OP_RSUB_INT_LIT8.S */ 6664/* File: armv5te/binopLit8.S */ 6665 /* 6666 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6667 * that specifies an instruction that performs "result = r0 op r1". 6668 * This could be an ARM instruction or a function call. (If the result 6669 * comes back in a register other than r0, you can override "result".) 6670 * 6671 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6672 * vCC (r1). Useful for integer division and modulus. 6673 * 6674 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6675 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6676 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6677 */ 6678 /* binop/lit8 vAA, vBB, #+CC */ 6679 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6680 mov r9, rINST, lsr #8 @ r9<- AA 6681 and r2, r3, #255 @ r2<- BB 6682 GET_VREG(r0, r2) @ r0<- vBB 6683 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6684 .if 0 6685 @cmp r1, #0 @ is second operand zero? 6686 beq common_errDivideByZero 6687 .endif 6688 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6689 6690 @ optional op; may set condition codes 6691 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6692 GET_INST_OPCODE(ip) @ extract opcode from rINST 6693 SET_VREG(r0, r9) @ vAA<- r0 6694 GOTO_OPCODE(ip) @ jump to next instruction 6695 /* 10-12 instructions */ 6696 6697 6698/* ------------------------------ */ 6699 .balign 64 6700.L_OP_MUL_INT_LIT8: /* 0xda */ 6701/* File: armv5te/OP_MUL_INT_LIT8.S */ 6702/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6703/* File: armv5te/binopLit8.S */ 6704 /* 6705 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6706 * that specifies an instruction that performs "result = r0 op r1". 6707 * This could be an ARM instruction or a function call. (If the result 6708 * comes back in a register other than r0, you can override "result".) 6709 * 6710 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6711 * vCC (r1). Useful for integer division and modulus. 6712 * 6713 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6714 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6715 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6716 */ 6717 /* binop/lit8 vAA, vBB, #+CC */ 6718 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6719 mov r9, rINST, lsr #8 @ r9<- AA 6720 and r2, r3, #255 @ r2<- BB 6721 GET_VREG(r0, r2) @ r0<- vBB 6722 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6723 .if 0 6724 @cmp r1, #0 @ is second operand zero? 6725 beq common_errDivideByZero 6726 .endif 6727 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6728 6729 @ optional op; may set condition codes 6730 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6731 GET_INST_OPCODE(ip) @ extract opcode from rINST 6732 SET_VREG(r0, r9) @ vAA<- r0 6733 GOTO_OPCODE(ip) @ jump to next instruction 6734 /* 10-12 instructions */ 6735 6736 6737/* ------------------------------ */ 6738 .balign 64 6739.L_OP_DIV_INT_LIT8: /* 0xdb */ 6740/* File: armv5te/OP_DIV_INT_LIT8.S */ 6741/* File: armv5te/binopLit8.S */ 6742 /* 6743 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6744 * that specifies an instruction that performs "result = r0 op r1". 6745 * This could be an ARM instruction or a function call. (If the result 6746 * comes back in a register other than r0, you can override "result".) 6747 * 6748 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6749 * vCC (r1). Useful for integer division and modulus. 6750 * 6751 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6752 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6753 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6754 */ 6755 /* binop/lit8 vAA, vBB, #+CC */ 6756 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6757 mov r9, rINST, lsr #8 @ r9<- AA 6758 and r2, r3, #255 @ r2<- BB 6759 GET_VREG(r0, r2) @ r0<- vBB 6760 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6761 .if 1 6762 @cmp r1, #0 @ is second operand zero? 6763 beq common_errDivideByZero 6764 .endif 6765 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6766 6767 @ optional op; may set condition codes 6768 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6769 GET_INST_OPCODE(ip) @ extract opcode from rINST 6770 SET_VREG(r0, r9) @ vAA<- r0 6771 GOTO_OPCODE(ip) @ jump to next instruction 6772 /* 10-12 instructions */ 6773 6774 6775/* ------------------------------ */ 6776 .balign 64 6777.L_OP_REM_INT_LIT8: /* 0xdc */ 6778/* File: armv5te/OP_REM_INT_LIT8.S */ 6779/* idivmod returns quotient in r0 and remainder in r1 */ 6780/* File: armv5te/binopLit8.S */ 6781 /* 6782 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6783 * that specifies an instruction that performs "result = r0 op r1". 6784 * This could be an ARM instruction or a function call. (If the result 6785 * comes back in a register other than r0, you can override "result".) 6786 * 6787 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6788 * vCC (r1). Useful for integer division and modulus. 6789 * 6790 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6791 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6792 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6793 */ 6794 /* binop/lit8 vAA, vBB, #+CC */ 6795 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6796 mov r9, rINST, lsr #8 @ r9<- AA 6797 and r2, r3, #255 @ r2<- BB 6798 GET_VREG(r0, r2) @ r0<- vBB 6799 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6800 .if 1 6801 @cmp r1, #0 @ is second operand zero? 6802 beq common_errDivideByZero 6803 .endif 6804 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6805 6806 @ optional op; may set condition codes 6807 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6808 GET_INST_OPCODE(ip) @ extract opcode from rINST 6809 SET_VREG(r1, r9) @ vAA<- r1 6810 GOTO_OPCODE(ip) @ jump to next instruction 6811 /* 10-12 instructions */ 6812 6813 6814/* ------------------------------ */ 6815 .balign 64 6816.L_OP_AND_INT_LIT8: /* 0xdd */ 6817/* File: armv5te/OP_AND_INT_LIT8.S */ 6818/* File: armv5te/binopLit8.S */ 6819 /* 6820 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6821 * that specifies an instruction that performs "result = r0 op r1". 6822 * This could be an ARM instruction or a function call. (If the result 6823 * comes back in a register other than r0, you can override "result".) 6824 * 6825 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6826 * vCC (r1). Useful for integer division and modulus. 6827 * 6828 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6829 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6830 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6831 */ 6832 /* binop/lit8 vAA, vBB, #+CC */ 6833 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6834 mov r9, rINST, lsr #8 @ r9<- AA 6835 and r2, r3, #255 @ r2<- BB 6836 GET_VREG(r0, r2) @ r0<- vBB 6837 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6838 .if 0 6839 @cmp r1, #0 @ is second operand zero? 6840 beq common_errDivideByZero 6841 .endif 6842 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6843 6844 @ optional op; may set condition codes 6845 and r0, r0, r1 @ r0<- op, r0-r3 changed 6846 GET_INST_OPCODE(ip) @ extract opcode from rINST 6847 SET_VREG(r0, r9) @ vAA<- r0 6848 GOTO_OPCODE(ip) @ jump to next instruction 6849 /* 10-12 instructions */ 6850 6851 6852/* ------------------------------ */ 6853 .balign 64 6854.L_OP_OR_INT_LIT8: /* 0xde */ 6855/* File: armv5te/OP_OR_INT_LIT8.S */ 6856/* File: armv5te/binopLit8.S */ 6857 /* 6858 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6859 * that specifies an instruction that performs "result = r0 op r1". 6860 * This could be an ARM instruction or a function call. (If the result 6861 * comes back in a register other than r0, you can override "result".) 6862 * 6863 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6864 * vCC (r1). Useful for integer division and modulus. 6865 * 6866 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6867 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6868 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6869 */ 6870 /* binop/lit8 vAA, vBB, #+CC */ 6871 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6872 mov r9, rINST, lsr #8 @ r9<- AA 6873 and r2, r3, #255 @ r2<- BB 6874 GET_VREG(r0, r2) @ r0<- vBB 6875 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6876 .if 0 6877 @cmp r1, #0 @ is second operand zero? 6878 beq common_errDivideByZero 6879 .endif 6880 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6881 6882 @ optional op; may set condition codes 6883 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6884 GET_INST_OPCODE(ip) @ extract opcode from rINST 6885 SET_VREG(r0, r9) @ vAA<- r0 6886 GOTO_OPCODE(ip) @ jump to next instruction 6887 /* 10-12 instructions */ 6888 6889 6890/* ------------------------------ */ 6891 .balign 64 6892.L_OP_XOR_INT_LIT8: /* 0xdf */ 6893/* File: armv5te/OP_XOR_INT_LIT8.S */ 6894/* File: armv5te/binopLit8.S */ 6895 /* 6896 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6897 * that specifies an instruction that performs "result = r0 op r1". 6898 * This could be an ARM instruction or a function call. (If the result 6899 * comes back in a register other than r0, you can override "result".) 6900 * 6901 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6902 * vCC (r1). Useful for integer division and modulus. 6903 * 6904 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6905 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6906 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6907 */ 6908 /* binop/lit8 vAA, vBB, #+CC */ 6909 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6910 mov r9, rINST, lsr #8 @ r9<- AA 6911 and r2, r3, #255 @ r2<- BB 6912 GET_VREG(r0, r2) @ r0<- vBB 6913 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6914 .if 0 6915 @cmp r1, #0 @ is second operand zero? 6916 beq common_errDivideByZero 6917 .endif 6918 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6919 6920 @ optional op; may set condition codes 6921 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6922 GET_INST_OPCODE(ip) @ extract opcode from rINST 6923 SET_VREG(r0, r9) @ vAA<- r0 6924 GOTO_OPCODE(ip) @ jump to next instruction 6925 /* 10-12 instructions */ 6926 6927 6928/* ------------------------------ */ 6929 .balign 64 6930.L_OP_SHL_INT_LIT8: /* 0xe0 */ 6931/* File: armv5te/OP_SHL_INT_LIT8.S */ 6932/* File: armv5te/binopLit8.S */ 6933 /* 6934 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6935 * that specifies an instruction that performs "result = r0 op r1". 6936 * This could be an ARM instruction or a function call. (If the result 6937 * comes back in a register other than r0, you can override "result".) 6938 * 6939 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6940 * vCC (r1). Useful for integer division and modulus. 6941 * 6942 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6943 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6944 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6945 */ 6946 /* binop/lit8 vAA, vBB, #+CC */ 6947 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6948 mov r9, rINST, lsr #8 @ r9<- AA 6949 and r2, r3, #255 @ r2<- BB 6950 GET_VREG(r0, r2) @ r0<- vBB 6951 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6952 .if 0 6953 @cmp r1, #0 @ is second operand zero? 6954 beq common_errDivideByZero 6955 .endif 6956 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6957 6958 and r1, r1, #31 @ optional op; may set condition codes 6959 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 6960 GET_INST_OPCODE(ip) @ extract opcode from rINST 6961 SET_VREG(r0, r9) @ vAA<- r0 6962 GOTO_OPCODE(ip) @ jump to next instruction 6963 /* 10-12 instructions */ 6964 6965 6966/* ------------------------------ */ 6967 .balign 64 6968.L_OP_SHR_INT_LIT8: /* 0xe1 */ 6969/* File: armv5te/OP_SHR_INT_LIT8.S */ 6970/* File: armv5te/binopLit8.S */ 6971 /* 6972 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6973 * that specifies an instruction that performs "result = r0 op r1". 6974 * This could be an ARM instruction or a function call. (If the result 6975 * comes back in a register other than r0, you can override "result".) 6976 * 6977 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6978 * vCC (r1). Useful for integer division and modulus. 6979 * 6980 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6981 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6982 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6983 */ 6984 /* binop/lit8 vAA, vBB, #+CC */ 6985 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6986 mov r9, rINST, lsr #8 @ r9<- AA 6987 and r2, r3, #255 @ r2<- BB 6988 GET_VREG(r0, r2) @ r0<- vBB 6989 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6990 .if 0 6991 @cmp r1, #0 @ is second operand zero? 6992 beq common_errDivideByZero 6993 .endif 6994 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6995 6996 and r1, r1, #31 @ optional op; may set condition codes 6997 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 6998 GET_INST_OPCODE(ip) @ extract opcode from rINST 6999 SET_VREG(r0, r9) @ vAA<- r0 7000 GOTO_OPCODE(ip) @ jump to next instruction 7001 /* 10-12 instructions */ 7002 7003 7004/* ------------------------------ */ 7005 .balign 64 7006.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7007/* File: armv5te/OP_USHR_INT_LIT8.S */ 7008/* File: armv5te/binopLit8.S */ 7009 /* 7010 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7011 * that specifies an instruction that performs "result = r0 op r1". 7012 * This could be an ARM instruction or a function call. (If the result 7013 * comes back in a register other than r0, you can override "result".) 7014 * 7015 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7016 * vCC (r1). Useful for integer division and modulus. 7017 * 7018 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7019 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7020 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7021 */ 7022 /* binop/lit8 vAA, vBB, #+CC */ 7023 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7024 mov r9, rINST, lsr #8 @ r9<- AA 7025 and r2, r3, #255 @ r2<- BB 7026 GET_VREG(r0, r2) @ r0<- vBB 7027 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7028 .if 0 7029 @cmp r1, #0 @ is second operand zero? 7030 beq common_errDivideByZero 7031 .endif 7032 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7033 7034 and r1, r1, #31 @ optional op; may set condition codes 7035 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7036 GET_INST_OPCODE(ip) @ extract opcode from rINST 7037 SET_VREG(r0, r9) @ vAA<- r0 7038 GOTO_OPCODE(ip) @ jump to next instruction 7039 /* 10-12 instructions */ 7040 7041 7042/* ------------------------------ */ 7043 .balign 64 7044.L_OP_IGET_VOLATILE: /* 0xe3 */ 7045/* File: armv5te/OP_IGET_VOLATILE.S */ 7046/* File: armv5te/OP_IGET.S */ 7047 /* 7048 * General 32-bit instance field get. 7049 * 7050 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7051 */ 7052 /* op vA, vB, field@CCCC */ 7053 mov r0, rINST, lsr #12 @ r0<- B 7054 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7055 FETCH(r1, 1) @ r1<- field ref CCCC 7056 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7057 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7058 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7059 cmp r0, #0 @ is resolved entry null? 7060 bne .LOP_IGET_VOLATILE_finish @ no, already resolved 70618: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7062 EXPORT_PC() @ resolve() could throw 7063 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7064 bl dvmResolveInstField @ r0<- resolved InstField ptr 7065 cmp r0, #0 7066 bne .LOP_IGET_VOLATILE_finish 7067 b common_exceptionThrown 7068 7069 7070/* ------------------------------ */ 7071 .balign 64 7072.L_OP_IPUT_VOLATILE: /* 0xe4 */ 7073/* File: armv5te/OP_IPUT_VOLATILE.S */ 7074/* File: armv5te/OP_IPUT.S */ 7075 /* 7076 * General 32-bit instance field put. 7077 * 7078 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 7079 */ 7080 /* op vA, vB, field@CCCC */ 7081 mov r0, rINST, lsr #12 @ r0<- B 7082 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7083 FETCH(r1, 1) @ r1<- field ref CCCC 7084 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7085 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7086 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7087 cmp r0, #0 @ is resolved entry null? 7088 bne .LOP_IPUT_VOLATILE_finish @ no, already resolved 70898: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7090 EXPORT_PC() @ resolve() could throw 7091 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7092 bl dvmResolveInstField @ r0<- resolved InstField ptr 7093 cmp r0, #0 @ success? 7094 bne .LOP_IPUT_VOLATILE_finish @ yes, finish up 7095 b common_exceptionThrown 7096 7097 7098/* ------------------------------ */ 7099 .balign 64 7100.L_OP_SGET_VOLATILE: /* 0xe5 */ 7101/* File: armv5te/OP_SGET_VOLATILE.S */ 7102/* File: armv5te/OP_SGET.S */ 7103 /* 7104 * General 32-bit SGET handler. 7105 * 7106 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7107 */ 7108 /* op vAA, field@BBBB */ 7109 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7110 FETCH(r1, 1) @ r1<- field ref BBBB 7111 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7112 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7113 cmp r0, #0 @ is resolved entry null? 7114 beq .LOP_SGET_VOLATILE_resolve @ yes, do resolve 7115.LOP_SGET_VOLATILE_finish: @ field ptr in r0 7116 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7117 SMP_DMB @ acquiring load 7118 mov r2, rINST, lsr #8 @ r2<- AA 7119 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7120 SET_VREG(r1, r2) @ fp[AA]<- r1 7121 GET_INST_OPCODE(ip) @ extract opcode from rINST 7122 GOTO_OPCODE(ip) @ jump to next instruction 7123 7124 7125/* ------------------------------ */ 7126 .balign 64 7127.L_OP_SPUT_VOLATILE: /* 0xe6 */ 7128/* File: armv5te/OP_SPUT_VOLATILE.S */ 7129/* File: armv5te/OP_SPUT.S */ 7130 /* 7131 * General 32-bit SPUT handler. 7132 * 7133 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 7134 */ 7135 /* op vAA, field@BBBB */ 7136 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7137 FETCH(r1, 1) @ r1<- field ref BBBB 7138 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7139 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7140 cmp r0, #0 @ is resolved entry null? 7141 beq .LOP_SPUT_VOLATILE_resolve @ yes, do resolve 7142.LOP_SPUT_VOLATILE_finish: @ field ptr in r0 7143 mov r2, rINST, lsr #8 @ r2<- AA 7144 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7145 GET_VREG(r1, r2) @ r1<- fp[AA] 7146 GET_INST_OPCODE(ip) @ extract opcode from rINST 7147 SMP_DMB @ releasing store 7148 str r1, [r0, #offStaticField_value] @ field<- vAA 7149 GOTO_OPCODE(ip) @ jump to next instruction 7150 7151 7152/* ------------------------------ */ 7153 .balign 64 7154.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ 7155/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */ 7156/* File: armv5te/OP_IGET.S */ 7157 /* 7158 * General 32-bit instance field get. 7159 * 7160 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7161 */ 7162 /* op vA, vB, field@CCCC */ 7163 mov r0, rINST, lsr #12 @ r0<- B 7164 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7165 FETCH(r1, 1) @ r1<- field ref CCCC 7166 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7167 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7168 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7169 cmp r0, #0 @ is resolved entry null? 7170 bne .LOP_IGET_OBJECT_VOLATILE_finish @ no, already resolved 71718: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7172 EXPORT_PC() @ resolve() could throw 7173 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7174 bl dvmResolveInstField @ r0<- resolved InstField ptr 7175 cmp r0, #0 7176 bne .LOP_IGET_OBJECT_VOLATILE_finish 7177 b common_exceptionThrown 7178 7179 7180/* ------------------------------ */ 7181 .balign 64 7182.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */ 7183/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */ 7184/* File: armv5te/OP_IGET_WIDE.S */ 7185 /* 7186 * Wide 32-bit instance field get. 7187 */ 7188 /* iget-wide vA, vB, field@CCCC */ 7189 mov r0, rINST, lsr #12 @ r0<- B 7190 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7191 FETCH(r1, 1) @ r1<- field ref CCCC 7192 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7193 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7194 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7195 cmp r0, #0 @ is resolved entry null? 7196 bne .LOP_IGET_WIDE_VOLATILE_finish @ no, already resolved 71978: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7198 EXPORT_PC() @ resolve() could throw 7199 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7200 bl dvmResolveInstField @ r0<- resolved InstField ptr 7201 cmp r0, #0 7202 bne .LOP_IGET_WIDE_VOLATILE_finish 7203 b common_exceptionThrown 7204 7205 7206/* ------------------------------ */ 7207 .balign 64 7208.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */ 7209/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */ 7210/* File: armv5te/OP_IPUT_WIDE.S */ 7211 /* iput-wide vA, vB, field@CCCC */ 7212 mov r0, rINST, lsr #12 @ r0<- B 7213 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7214 FETCH(r1, 1) @ r1<- field ref CCCC 7215 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7216 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7217 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7218 cmp r0, #0 @ is resolved entry null? 7219 bne .LOP_IPUT_WIDE_VOLATILE_finish @ no, already resolved 72208: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7221 EXPORT_PC() @ resolve() could throw 7222 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7223 bl dvmResolveInstField @ r0<- resolved InstField ptr 7224 cmp r0, #0 @ success? 7225 bne .LOP_IPUT_WIDE_VOLATILE_finish @ yes, finish up 7226 b common_exceptionThrown 7227 7228 7229/* ------------------------------ */ 7230 .balign 64 7231.L_OP_SGET_WIDE_VOLATILE: /* 0xea */ 7232/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */ 7233/* File: armv5te/OP_SGET_WIDE.S */ 7234 /* 7235 * 64-bit SGET handler. 7236 */ 7237 /* sget-wide vAA, field@BBBB */ 7238 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7239 FETCH(r1, 1) @ r1<- field ref BBBB 7240 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7241 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7242 cmp r0, #0 @ is resolved entry null? 7243 beq .LOP_SGET_WIDE_VOLATILE_resolve @ yes, do resolve 7244.LOP_SGET_WIDE_VOLATILE_finish: 7245 mov r9, rINST, lsr #8 @ r9<- AA 7246 .if 1 7247 add r0, r0, #offStaticField_value @ r0<- pointer to data 7248 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 7249 .else 7250 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 7251 .endif 7252 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7253 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7254 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 7255 GET_INST_OPCODE(ip) @ extract opcode from rINST 7256 GOTO_OPCODE(ip) @ jump to next instruction 7257 7258 7259/* ------------------------------ */ 7260 .balign 64 7261.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */ 7262/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */ 7263/* File: armv5te/OP_SPUT_WIDE.S */ 7264 /* 7265 * 64-bit SPUT handler. 7266 */ 7267 /* sput-wide vAA, field@BBBB */ 7268 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 7269 FETCH(r1, 1) @ r1<- field ref BBBB 7270 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 7271 mov r9, rINST, lsr #8 @ r9<- AA 7272 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 7273 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7274 cmp r2, #0 @ is resolved entry null? 7275 beq .LOP_SPUT_WIDE_VOLATILE_resolve @ yes, do resolve 7276.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9 7277 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7278 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 7279 GET_INST_OPCODE(r10) @ extract opcode from rINST 7280 .if 1 7281 add r2, r2, #offStaticField_value @ r2<- pointer to data 7282 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 7283 .else 7284 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 7285 .endif 7286 GOTO_OPCODE(r10) @ jump to next instruction 7287 7288 7289/* ------------------------------ */ 7290 .balign 64 7291.L_OP_BREAKPOINT: /* 0xec */ 7292/* File: armv5te/OP_BREAKPOINT.S */ 7293/* File: armv5te/unused.S */ 7294 bl common_abort 7295 7296 7297/* ------------------------------ */ 7298 .balign 64 7299.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7300/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7301 /* 7302 * Handle a throw-verification-error instruction. This throws an 7303 * exception for an error discovered during verification. The 7304 * exception is indicated by AA, with some detail provided by BBBB. 7305 */ 7306 /* op AA, ref@BBBB */ 7307 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7308 FETCH(r2, 1) @ r2<- BBBB 7309 EXPORT_PC() @ export the PC 7310 mov r1, rINST, lsr #8 @ r1<- AA 7311 bl dvmThrowVerificationError @ always throws 7312 b common_exceptionThrown @ handle exception 7313 7314/* ------------------------------ */ 7315 .balign 64 7316.L_OP_EXECUTE_INLINE: /* 0xee */ 7317/* File: armv5te/OP_EXECUTE_INLINE.S */ 7318 /* 7319 * Execute a "native inline" instruction. 7320 * 7321 * We need to call an InlineOp4Func: 7322 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7323 * 7324 * The first four args are in r0-r3, pointer to return value storage 7325 * is on the stack. The function's return value is a flag that tells 7326 * us if an exception was thrown. 7327 */ 7328 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7329 FETCH(r10, 1) @ r10<- BBBB 7330 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7331 EXPORT_PC() @ can throw 7332 sub sp, sp, #8 @ make room for arg, +64 bit align 7333 mov r0, rINST, lsr #12 @ r0<- B 7334 str r1, [sp] @ push &glue->retval 7335 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7336 add sp, sp, #8 @ pop stack 7337 cmp r0, #0 @ test boolean result of inline 7338 beq common_exceptionThrown @ returned false, handle exception 7339 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7340 GET_INST_OPCODE(ip) @ extract opcode from rINST 7341 GOTO_OPCODE(ip) @ jump to next instruction 7342 7343/* ------------------------------ */ 7344 .balign 64 7345.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ 7346/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */ 7347 /* 7348 * Execute a "native inline" instruction, using "/range" semantics. 7349 * Same idea as execute-inline, but we get the args differently. 7350 * 7351 * We need to call an InlineOp4Func: 7352 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7353 * 7354 * The first four args are in r0-r3, pointer to return value storage 7355 * is on the stack. The function's return value is a flag that tells 7356 * us if an exception was thrown. 7357 */ 7358 /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */ 7359 FETCH(r10, 1) @ r10<- BBBB 7360 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7361 EXPORT_PC() @ can throw 7362 sub sp, sp, #8 @ make room for arg, +64 bit align 7363 mov r0, rINST, lsr #8 @ r0<- AA 7364 str r1, [sp] @ push &glue->retval 7365 bl .LOP_EXECUTE_INLINE_RANGE_continue @ make call; will return after 7366 add sp, sp, #8 @ pop stack 7367 cmp r0, #0 @ test boolean result of inline 7368 beq common_exceptionThrown @ returned false, handle exception 7369 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7370 GET_INST_OPCODE(ip) @ extract opcode from rINST 7371 GOTO_OPCODE(ip) @ jump to next instruction 7372 7373/* ------------------------------ */ 7374 .balign 64 7375.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7376/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7377 /* 7378 * invoke-direct-empty is a no-op in a "standard" interpreter. 7379 */ 7380 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7381 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7382 GOTO_OPCODE(ip) @ execute it 7383 7384/* ------------------------------ */ 7385 .balign 64 7386.L_OP_RETURN_VOID_BARRIER: /* 0xf1 */ 7387/* File: armv5te/OP_RETURN_VOID_BARRIER.S */ 7388 SMP_DMB_ST 7389 b common_returnFromMethod 7390 7391/* ------------------------------ */ 7392 .balign 64 7393.L_OP_IGET_QUICK: /* 0xf2 */ 7394/* File: armv6t2/OP_IGET_QUICK.S */ 7395 /* For: iget-quick, iget-object-quick */ 7396 /* op vA, vB, offset@CCCC */ 7397 mov r2, rINST, lsr #12 @ r2<- B 7398 FETCH(r1, 1) @ r1<- field byte offset 7399 GET_VREG(r3, r2) @ r3<- object we're operating on 7400 ubfx r2, rINST, #8, #4 @ r2<- A 7401 cmp r3, #0 @ check object for null 7402 beq common_errNullObject @ object was null 7403 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7404 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7405 GET_INST_OPCODE(ip) @ extract opcode from rINST 7406 SET_VREG(r0, r2) @ fp[A]<- r0 7407 GOTO_OPCODE(ip) @ jump to next instruction 7408 7409/* ------------------------------ */ 7410 .balign 64 7411.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7412/* File: armv6t2/OP_IGET_WIDE_QUICK.S */ 7413 /* iget-wide-quick vA, vB, offset@CCCC */ 7414 mov r2, rINST, lsr #12 @ r2<- B 7415 FETCH(ip, 1) @ ip<- field byte offset 7416 GET_VREG(r3, r2) @ r3<- object we're operating on 7417 ubfx r2, rINST, #8, #4 @ r2<- A 7418 cmp r3, #0 @ check object for null 7419 beq common_errNullObject @ object was null 7420 ldrd r0, [r3, ip] @ r0<- obj.field (64 bits, aligned) 7421 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7422 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7423 GET_INST_OPCODE(ip) @ extract opcode from rINST 7424 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7425 GOTO_OPCODE(ip) @ jump to next instruction 7426 7427/* ------------------------------ */ 7428 .balign 64 7429.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7430/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7431/* File: armv5te/OP_IGET_QUICK.S */ 7432 /* For: iget-quick, iget-object-quick */ 7433 /* op vA, vB, offset@CCCC */ 7434 mov r2, rINST, lsr #12 @ r2<- B 7435 GET_VREG(r3, r2) @ r3<- object we're operating on 7436 FETCH(r1, 1) @ r1<- field byte offset 7437 cmp r3, #0 @ check object for null 7438 mov r2, rINST, lsr #8 @ r2<- A(+) 7439 beq common_errNullObject @ object was null 7440 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7441 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7442 and r2, r2, #15 7443 GET_INST_OPCODE(ip) @ extract opcode from rINST 7444 SET_VREG(r0, r2) @ fp[A]<- r0 7445 GOTO_OPCODE(ip) @ jump to next instruction 7446 7447 7448/* ------------------------------ */ 7449 .balign 64 7450.L_OP_IPUT_QUICK: /* 0xf5 */ 7451/* File: armv6t2/OP_IPUT_QUICK.S */ 7452 /* For: iput-quick, iput-object-quick */ 7453 /* op vA, vB, offset@CCCC */ 7454 mov r2, rINST, lsr #12 @ r2<- B 7455 FETCH(r1, 1) @ r1<- field byte offset 7456 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7457 ubfx r2, rINST, #8, #4 @ r2<- A 7458 cmp r3, #0 @ check object for null 7459 beq common_errNullObject @ object was null 7460 GET_VREG(r0, r2) @ r0<- fp[A] 7461 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7462 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7463 GET_INST_OPCODE(ip) @ extract opcode from rINST 7464 GOTO_OPCODE(ip) @ jump to next instruction 7465 7466/* ------------------------------ */ 7467 .balign 64 7468.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7469/* File: armv6t2/OP_IPUT_WIDE_QUICK.S */ 7470 /* iput-wide-quick vA, vB, offset@CCCC */ 7471 mov r1, rINST, lsr #12 @ r1<- B 7472 ubfx r0, rINST, #8, #4 @ r0<- A 7473 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7474 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7475 cmp r2, #0 @ check object for null 7476 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7477 beq common_errNullObject @ object was null 7478 FETCH(r3, 1) @ r3<- field byte offset 7479 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7480 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7481 GET_INST_OPCODE(ip) @ extract opcode from rINST 7482 GOTO_OPCODE(ip) @ jump to next instruction 7483 7484/* ------------------------------ */ 7485 .balign 64 7486.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7487/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7488 /* For: iput-object-quick */ 7489 /* op vA, vB, offset@CCCC */ 7490 mov r2, rINST, lsr #12 @ r2<- B 7491 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7492 FETCH(r1, 1) @ r1<- field byte offset 7493 cmp r3, #0 @ check object for null 7494 mov r2, rINST, lsr #8 @ r2<- A(+) 7495 beq common_errNullObject @ object was null 7496 and r2, r2, #15 7497 GET_VREG(r0, r2) @ r0<- fp[A] 7498 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 7499 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7500 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7501 cmp r0, #0 7502 strneb r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head 7503 GET_INST_OPCODE(ip) @ extract opcode from rINST 7504 GOTO_OPCODE(ip) @ jump to next instruction 7505 7506/* ------------------------------ */ 7507 .balign 64 7508.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7509/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7510 /* 7511 * Handle an optimized virtual method call. 7512 * 7513 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7514 */ 7515 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7516 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7517 FETCH(r3, 2) @ r3<- FEDC or CCCC 7518 FETCH(r1, 1) @ r1<- BBBB 7519 .if (!0) 7520 and r3, r3, #15 @ r3<- C (or stays CCCC) 7521 .endif 7522 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7523 cmp r2, #0 @ is "this" null? 7524 beq common_errNullObject @ null "this", throw exception 7525 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7526 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7527 EXPORT_PC() @ invoke must export 7528 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7529 bl common_invokeMethodNoRange @ continue on 7530 7531/* ------------------------------ */ 7532 .balign 64 7533.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7534/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7535/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7536 /* 7537 * Handle an optimized virtual method call. 7538 * 7539 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7540 */ 7541 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7542 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7543 FETCH(r3, 2) @ r3<- FEDC or CCCC 7544 FETCH(r1, 1) @ r1<- BBBB 7545 .if (!1) 7546 and r3, r3, #15 @ r3<- C (or stays CCCC) 7547 .endif 7548 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7549 cmp r2, #0 @ is "this" null? 7550 beq common_errNullObject @ null "this", throw exception 7551 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7552 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7553 EXPORT_PC() @ invoke must export 7554 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7555 bl common_invokeMethodRange @ continue on 7556 7557 7558/* ------------------------------ */ 7559 .balign 64 7560.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7561/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7562 /* 7563 * Handle an optimized "super" method call. 7564 * 7565 * for: [opt] invoke-super-quick, invoke-super-quick/range 7566 */ 7567 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7568 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7569 FETCH(r10, 2) @ r10<- GFED or CCCC 7570 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7571 .if (!0) 7572 and r10, r10, #15 @ r10<- D (or stays CCCC) 7573 .endif 7574 FETCH(r1, 1) @ r1<- BBBB 7575 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7576 EXPORT_PC() @ must export for invoke 7577 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7578 GET_VREG(r3, r10) @ r3<- "this" 7579 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7580 cmp r3, #0 @ null "this" ref? 7581 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7582 beq common_errNullObject @ "this" is null, throw exception 7583 bl common_invokeMethodNoRange @ continue on 7584 7585/* ------------------------------ */ 7586 .balign 64 7587.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7588/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7589/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7590 /* 7591 * Handle an optimized "super" method call. 7592 * 7593 * for: [opt] invoke-super-quick, invoke-super-quick/range 7594 */ 7595 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7596 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7597 FETCH(r10, 2) @ r10<- GFED or CCCC 7598 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7599 .if (!1) 7600 and r10, r10, #15 @ r10<- D (or stays CCCC) 7601 .endif 7602 FETCH(r1, 1) @ r1<- BBBB 7603 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7604 EXPORT_PC() @ must export for invoke 7605 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7606 GET_VREG(r3, r10) @ r3<- "this" 7607 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7608 cmp r3, #0 @ null "this" ref? 7609 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7610 beq common_errNullObject @ "this" is null, throw exception 7611 bl common_invokeMethodRange @ continue on 7612 7613 7614/* ------------------------------ */ 7615 .balign 64 7616.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ 7617/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */ 7618/* File: armv5te/OP_IPUT_OBJECT.S */ 7619 /* 7620 * 32-bit instance field put. 7621 * 7622 * for: iput-object, iput-object-volatile 7623 */ 7624 /* op vA, vB, field@CCCC */ 7625 mov r0, rINST, lsr #12 @ r0<- B 7626 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7627 FETCH(r1, 1) @ r1<- field ref CCCC 7628 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7629 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7630 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7631 cmp r0, #0 @ is resolved entry null? 7632 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ no, already resolved 76338: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7634 EXPORT_PC() @ resolve() could throw 7635 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7636 bl dvmResolveInstField @ r0<- resolved InstField ptr 7637 cmp r0, #0 @ success? 7638 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ yes, finish up 7639 b common_exceptionThrown 7640 7641 7642/* ------------------------------ */ 7643 .balign 64 7644.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ 7645/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */ 7646/* File: armv5te/OP_SGET.S */ 7647 /* 7648 * General 32-bit SGET handler. 7649 * 7650 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7651 */ 7652 /* op vAA, field@BBBB */ 7653 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7654 FETCH(r1, 1) @ r1<- field ref BBBB 7655 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7656 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7657 cmp r0, #0 @ is resolved entry null? 7658 beq .LOP_SGET_OBJECT_VOLATILE_resolve @ yes, do resolve 7659.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0 7660 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7661 SMP_DMB @ acquiring load 7662 mov r2, rINST, lsr #8 @ r2<- AA 7663 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7664 SET_VREG(r1, r2) @ fp[AA]<- r1 7665 GET_INST_OPCODE(ip) @ extract opcode from rINST 7666 GOTO_OPCODE(ip) @ jump to next instruction 7667 7668 7669/* ------------------------------ */ 7670 .balign 64 7671.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ 7672/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */ 7673/* File: armv5te/OP_SPUT_OBJECT.S */ 7674 /* 7675 * 32-bit SPUT handler for objects 7676 * 7677 * for: sput-object, sput-object-volatile 7678 */ 7679 /* op vAA, field@BBBB */ 7680 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7681 FETCH(r1, 1) @ r1<- field ref BBBB 7682 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7683 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7684 cmp r0, #0 @ is resolved entry null? 7685 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ no, continue 7686 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 7687 EXPORT_PC() @ resolve() could throw, so export now 7688 ldr r0, [r9, #offMethod_clazz] @ r0<- method->clazz 7689 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 7690 cmp r0, #0 @ success? 7691 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish 7692 b common_exceptionThrown @ no, handle exception 7693 7694 7695 7696/* ------------------------------ */ 7697 .balign 64 7698.L_OP_UNUSED_FF: /* 0xff */ 7699/* File: armv5te/OP_UNUSED_FF.S */ 7700/* File: armv5te/unused.S */ 7701 bl common_abort 7702 7703 7704 7705 .balign 64 7706 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7707 .global dvmAsmInstructionEnd 7708dvmAsmInstructionEnd: 7709 7710/* 7711 * =========================================================================== 7712 * Sister implementations 7713 * =========================================================================== 7714 */ 7715 .global dvmAsmSisterStart 7716 .type dvmAsmSisterStart, %function 7717 .text 7718 .balign 4 7719dvmAsmSisterStart: 7720 7721/* continuation for OP_CONST_STRING */ 7722 7723 /* 7724 * Continuation if the String has not yet been resolved. 7725 * r1: BBBB (String ref) 7726 * r9: target register 7727 */ 7728.LOP_CONST_STRING_resolve: 7729 EXPORT_PC() 7730 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7731 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7732 bl dvmResolveString @ r0<- String reference 7733 cmp r0, #0 @ failed? 7734 beq common_exceptionThrown @ yup, handle the exception 7735 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7736 GET_INST_OPCODE(ip) @ extract opcode from rINST 7737 SET_VREG(r0, r9) @ vAA<- r0 7738 GOTO_OPCODE(ip) @ jump to next instruction 7739 7740/* continuation for OP_CONST_STRING_JUMBO */ 7741 7742 /* 7743 * Continuation if the String has not yet been resolved. 7744 * r1: BBBBBBBB (String ref) 7745 * r9: target register 7746 */ 7747.LOP_CONST_STRING_JUMBO_resolve: 7748 EXPORT_PC() 7749 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7750 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7751 bl dvmResolveString @ r0<- String reference 7752 cmp r0, #0 @ failed? 7753 beq common_exceptionThrown @ yup, handle the exception 7754 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7755 GET_INST_OPCODE(ip) @ extract opcode from rINST 7756 SET_VREG(r0, r9) @ vAA<- r0 7757 GOTO_OPCODE(ip) @ jump to next instruction 7758 7759/* continuation for OP_CONST_CLASS */ 7760 7761 /* 7762 * Continuation if the Class has not yet been resolved. 7763 * r1: BBBB (Class ref) 7764 * r9: target register 7765 */ 7766.LOP_CONST_CLASS_resolve: 7767 EXPORT_PC() 7768 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7769 mov r2, #1 @ r2<- true 7770 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7771 bl dvmResolveClass @ r0<- Class reference 7772 cmp r0, #0 @ failed? 7773 beq common_exceptionThrown @ yup, handle the exception 7774 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7775 GET_INST_OPCODE(ip) @ extract opcode from rINST 7776 SET_VREG(r0, r9) @ vAA<- r0 7777 GOTO_OPCODE(ip) @ jump to next instruction 7778 7779/* continuation for OP_CHECK_CAST */ 7780 7781 /* 7782 * Trivial test failed, need to perform full check. This is common. 7783 * r0 holds obj->clazz 7784 * r1 holds class resolved from BBBB 7785 * r9 holds object 7786 */ 7787.LOP_CHECK_CAST_fullcheck: 7788 bl dvmInstanceofNonTrivial @ r0<- boolean result 7789 cmp r0, #0 @ failed? 7790 bne .LOP_CHECK_CAST_okay @ no, success 7791 7792 @ A cast has failed. We need to throw a ClassCastException with the 7793 @ class of the object that failed to be cast. 7794 EXPORT_PC() @ about to throw 7795 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 7796 ldr r0, .LstrClassCastExceptionPtr 7797 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 7798 bl dvmThrowExceptionWithClassMessage 7799 b common_exceptionThrown 7800 7801 /* 7802 * Resolution required. This is the least-likely path. 7803 * 7804 * r2 holds BBBB 7805 * r9 holds object 7806 */ 7807.LOP_CHECK_CAST_resolve: 7808 EXPORT_PC() @ resolve() could throw 7809 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7810 mov r1, r2 @ r1<- BBBB 7811 mov r2, #0 @ r2<- false 7812 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7813 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7814 cmp r0, #0 @ got null? 7815 beq common_exceptionThrown @ yes, handle exception 7816 mov r1, r0 @ r1<- class resolved from BBB 7817 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7818 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7819 7820.LstrClassCastExceptionPtr: 7821 .word .LstrClassCastException 7822 7823/* continuation for OP_INSTANCE_OF */ 7824 7825 /* 7826 * Trivial test failed, need to perform full check. This is common. 7827 * r0 holds obj->clazz 7828 * r1 holds class resolved from BBBB 7829 * r9 holds A 7830 */ 7831.LOP_INSTANCE_OF_fullcheck: 7832 bl dvmInstanceofNonTrivial @ r0<- boolean result 7833 @ fall through to OP_INSTANCE_OF_store 7834 7835 /* 7836 * r0 holds boolean result 7837 * r9 holds A 7838 */ 7839.LOP_INSTANCE_OF_store: 7840 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7841 SET_VREG(r0, r9) @ vA<- r0 7842 GET_INST_OPCODE(ip) @ extract opcode from rINST 7843 GOTO_OPCODE(ip) @ jump to next instruction 7844 7845 /* 7846 * Trivial test succeeded, save and bail. 7847 * r9 holds A 7848 */ 7849.LOP_INSTANCE_OF_trivial: 7850 mov r0, #1 @ indicate success 7851 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7852 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7853 SET_VREG(r0, r9) @ vA<- r0 7854 GET_INST_OPCODE(ip) @ extract opcode from rINST 7855 GOTO_OPCODE(ip) @ jump to next instruction 7856 7857 /* 7858 * Resolution required. This is the least-likely path. 7859 * 7860 * r3 holds BBBB 7861 * r9 holds A 7862 */ 7863.LOP_INSTANCE_OF_resolve: 7864 EXPORT_PC() @ resolve() could throw 7865 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7866 mov r1, r3 @ r1<- BBBB 7867 mov r2, #1 @ r2<- true 7868 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7869 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7870 cmp r0, #0 @ got null? 7871 beq common_exceptionThrown @ yes, handle exception 7872 mov r1, r0 @ r1<- class resolved from BBB 7873 mov r3, rINST, lsr #12 @ r3<- B 7874 GET_VREG(r0, r3) @ r0<- vB (object) 7875 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7876 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7877 7878/* continuation for OP_NEW_INSTANCE */ 7879 7880 .balign 32 @ minimize cache lines 7881.LOP_NEW_INSTANCE_finish: @ r0=new object 7882 mov r3, rINST, lsr #8 @ r3<- AA 7883 cmp r0, #0 @ failed? 7884 beq common_exceptionThrown @ yes, handle the exception 7885 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7886 GET_INST_OPCODE(ip) @ extract opcode from rINST 7887 SET_VREG(r0, r3) @ vAA<- r0 7888 GOTO_OPCODE(ip) @ jump to next instruction 7889 7890 /* 7891 * Class initialization required. 7892 * 7893 * r0 holds class object 7894 */ 7895.LOP_NEW_INSTANCE_needinit: 7896 mov r9, r0 @ save r0 7897 bl dvmInitClass @ initialize class 7898 cmp r0, #0 @ check boolean result 7899 mov r0, r9 @ restore r0 7900 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7901 b common_exceptionThrown @ failed, deal with init exception 7902 7903 /* 7904 * Resolution required. This is the least-likely path. 7905 * 7906 * r1 holds BBBB 7907 */ 7908.LOP_NEW_INSTANCE_resolve: 7909 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7910 mov r2, #0 @ r2<- false 7911 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7912 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7913 cmp r0, #0 @ got null? 7914 bne .LOP_NEW_INSTANCE_resolved @ no, continue 7915 b common_exceptionThrown @ yes, handle exception 7916 7917.LstrInstantiationErrorPtr: 7918 .word .LstrInstantiationError 7919 7920/* continuation for OP_NEW_ARRAY */ 7921 7922 7923 /* 7924 * Resolve class. (This is an uncommon case.) 7925 * 7926 * r1 holds array length 7927 * r2 holds class ref CCCC 7928 */ 7929.LOP_NEW_ARRAY_resolve: 7930 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7931 mov r9, r1 @ r9<- length (save) 7932 mov r1, r2 @ r1<- CCCC 7933 mov r2, #0 @ r2<- false 7934 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7935 bl dvmResolveClass @ r0<- call(clazz, ref) 7936 cmp r0, #0 @ got null? 7937 mov r1, r9 @ r1<- length (restore) 7938 beq common_exceptionThrown @ yes, handle exception 7939 @ fall through to OP_NEW_ARRAY_finish 7940 7941 /* 7942 * Finish allocation. 7943 * 7944 * r0 holds class 7945 * r1 holds array length 7946 */ 7947.LOP_NEW_ARRAY_finish: 7948 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 7949 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 7950 cmp r0, #0 @ failed? 7951 mov r2, rINST, lsr #8 @ r2<- A+ 7952 beq common_exceptionThrown @ yes, handle the exception 7953 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7954 and r2, r2, #15 @ r2<- A 7955 GET_INST_OPCODE(ip) @ extract opcode from rINST 7956 SET_VREG(r0, r2) @ vA<- r0 7957 GOTO_OPCODE(ip) @ jump to next instruction 7958 7959/* continuation for OP_FILLED_NEW_ARRAY */ 7960 7961 /* 7962 * On entry: 7963 * r0 holds array class 7964 * r10 holds AA or BA 7965 */ 7966.LOP_FILLED_NEW_ARRAY_continue: 7967 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 7968 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 7969 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 7970 .if 0 7971 mov r1, r10 @ r1<- AA (length) 7972 .else 7973 mov r1, r10, lsr #4 @ r1<- B (length) 7974 .endif 7975 cmp rINST, #'I' @ array of ints? 7976 cmpne rINST, #'L' @ array of objects? 7977 cmpne rINST, #'[' @ array of arrays? 7978 mov r9, r1 @ save length in r9 7979 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 7980 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 7981 cmp r0, #0 @ null return? 7982 beq common_exceptionThrown @ alloc failed, handle exception 7983 7984 FETCH(r1, 2) @ r1<- FEDC or CCCC 7985 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 7986 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 7987 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 7988 subs r9, r9, #1 @ length--, check for neg 7989 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7990 bmi 2f @ was zero, bail 7991 7992 @ copy values from registers into the array 7993 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 7994 .if 0 7995 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 79961: ldr r3, [r2], #4 @ r3<- *r2++ 7997 subs r9, r9, #1 @ count-- 7998 str r3, [r0], #4 @ *contents++ = vX 7999 bpl 1b 8000 @ continue at 2 8001 .else 8002 cmp r9, #4 @ length was initially 5? 8003 and r2, r10, #15 @ r2<- A 8004 bne 1f @ <= 4 args, branch 8005 GET_VREG(r3, r2) @ r3<- vA 8006 sub r9, r9, #1 @ count-- 8007 str r3, [r0, #16] @ contents[4] = vA 80081: and r2, r1, #15 @ r2<- F/E/D/C 8009 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8010 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8011 subs r9, r9, #1 @ count-- 8012 str r3, [r0], #4 @ *contents++ = vX 8013 bpl 1b 8014 @ continue at 2 8015 .endif 8016 80172: 8018 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 8019 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 8020 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8021 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8022 cmp r1, #'I' @ Is int array? 8023 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 8024 GOTO_OPCODE(ip) @ execute it 8025 8026 /* 8027 * Throw an exception indicating that we have not implemented this 8028 * mode of filled-new-array. 8029 */ 8030.LOP_FILLED_NEW_ARRAY_notimpl: 8031 ldr r0, .L_strInternalError 8032 ldr r1, .L_strFilledNewArrayNotImpl 8033 bl dvmThrowException 8034 b common_exceptionThrown 8035 8036 .if (!0) @ define in one or the other, not both 8037.L_strFilledNewArrayNotImpl: 8038 .word .LstrFilledNewArrayNotImpl 8039.L_strInternalError: 8040 .word .LstrInternalError 8041 .endif 8042 8043/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 8044 8045 /* 8046 * On entry: 8047 * r0 holds array class 8048 * r10 holds AA or BA 8049 */ 8050.LOP_FILLED_NEW_ARRAY_RANGE_continue: 8051 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8052 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8053 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 8054 .if 1 8055 mov r1, r10 @ r1<- AA (length) 8056 .else 8057 mov r1, r10, lsr #4 @ r1<- B (length) 8058 .endif 8059 cmp rINST, #'I' @ array of ints? 8060 cmpne rINST, #'L' @ array of objects? 8061 cmpne rINST, #'[' @ array of arrays? 8062 mov r9, r1 @ save length in r9 8063 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 8064 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8065 cmp r0, #0 @ null return? 8066 beq common_exceptionThrown @ alloc failed, handle exception 8067 8068 FETCH(r1, 2) @ r1<- FEDC or CCCC 8069 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8070 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 8071 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8072 subs r9, r9, #1 @ length--, check for neg 8073 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8074 bmi 2f @ was zero, bail 8075 8076 @ copy values from registers into the array 8077 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8078 .if 1 8079 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 80801: ldr r3, [r2], #4 @ r3<- *r2++ 8081 subs r9, r9, #1 @ count-- 8082 str r3, [r0], #4 @ *contents++ = vX 8083 bpl 1b 8084 @ continue at 2 8085 .else 8086 cmp r9, #4 @ length was initially 5? 8087 and r2, r10, #15 @ r2<- A 8088 bne 1f @ <= 4 args, branch 8089 GET_VREG(r3, r2) @ r3<- vA 8090 sub r9, r9, #1 @ count-- 8091 str r3, [r0, #16] @ contents[4] = vA 80921: and r2, r1, #15 @ r2<- F/E/D/C 8093 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8094 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8095 subs r9, r9, #1 @ count-- 8096 str r3, [r0], #4 @ *contents++ = vX 8097 bpl 1b 8098 @ continue at 2 8099 .endif 8100 81012: 8102 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 8103 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 8104 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8105 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8106 cmp r1, #'I' @ Is int array? 8107 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 8108 GOTO_OPCODE(ip) @ execute it 8109 8110 /* 8111 * Throw an exception indicating that we have not implemented this 8112 * mode of filled-new-array. 8113 */ 8114.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8115 ldr r0, .L_strInternalError 8116 ldr r1, .L_strFilledNewArrayNotImpl 8117 bl dvmThrowException 8118 b common_exceptionThrown 8119 8120 .if (!1) @ define in one or the other, not both 8121.L_strFilledNewArrayNotImpl: 8122 .word .LstrFilledNewArrayNotImpl 8123.L_strInternalError: 8124 .word .LstrInternalError 8125 .endif 8126 8127/* continuation for OP_CMPL_FLOAT */ 8128.LOP_CMPL_FLOAT_finish: 8129 SET_VREG(r0, r9) @ vAA<- r0 8130 GOTO_OPCODE(ip) @ jump to next instruction 8131 8132/* continuation for OP_CMPG_FLOAT */ 8133.LOP_CMPG_FLOAT_finish: 8134 SET_VREG(r0, r9) @ vAA<- r0 8135 GOTO_OPCODE(ip) @ jump to next instruction 8136 8137/* continuation for OP_CMPL_DOUBLE */ 8138.LOP_CMPL_DOUBLE_finish: 8139 SET_VREG(r0, r9) @ vAA<- r0 8140 GOTO_OPCODE(ip) @ jump to next instruction 8141 8142/* continuation for OP_CMPG_DOUBLE */ 8143.LOP_CMPG_DOUBLE_finish: 8144 SET_VREG(r0, r9) @ vAA<- r0 8145 GOTO_OPCODE(ip) @ jump to next instruction 8146 8147/* continuation for OP_CMP_LONG */ 8148 8149.LOP_CMP_LONG_less: 8150 mvn r1, #0 @ r1<- -1 8151 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8152 @ instead, we just replicate the tail end. 8153 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8154 SET_VREG(r1, r9) @ vAA<- r1 8155 GET_INST_OPCODE(ip) @ extract opcode from rINST 8156 GOTO_OPCODE(ip) @ jump to next instruction 8157 8158.LOP_CMP_LONG_greater: 8159 mov r1, #1 @ r1<- 1 8160 @ fall through to _finish 8161 8162.LOP_CMP_LONG_finish: 8163 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8164 SET_VREG(r1, r9) @ vAA<- r1 8165 GET_INST_OPCODE(ip) @ extract opcode from rINST 8166 GOTO_OPCODE(ip) @ jump to next instruction 8167 8168/* continuation for OP_AGET_WIDE */ 8169 8170.LOP_AGET_WIDE_finish: 8171 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8172 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8173 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8174 GET_INST_OPCODE(ip) @ extract opcode from rINST 8175 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8176 GOTO_OPCODE(ip) @ jump to next instruction 8177 8178/* continuation for OP_APUT_WIDE */ 8179 8180.LOP_APUT_WIDE_finish: 8181 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8182 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8183 GET_INST_OPCODE(ip) @ extract opcode from rINST 8184 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8185 GOTO_OPCODE(ip) @ jump to next instruction 8186 8187/* continuation for OP_APUT_OBJECT */ 8188 /* 8189 * On entry: 8190 * rINST = vBB (arrayObj) 8191 * r9 = vAA (obj) 8192 * r10 = offset into array (vBB + vCC * width) 8193 */ 8194.LOP_APUT_OBJECT_finish: 8195 cmp r9, #0 @ storing null reference? 8196 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8197 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8198 ldr r1, [rINST, #offObject_clazz] @ r1<- arrayObj->clazz 8199 bl dvmCanPutArrayElement @ test object type vs. array type 8200 cmp r0, #0 @ okay? 8201 beq common_errArrayStore @ no 8202 mov r1, rINST @ r1<- arrayObj 8203 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8204 ldr r2, [rGLUE, #offGlue_cardTable] @ get biased CT base 8205 add r10, #offArrayObject_contents @ r0<- pointer to slot 8206 GET_INST_OPCODE(ip) @ extract opcode from rINST 8207 str r9, [r10] @ vBB[vCC]<- vAA 8208 strb r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head 8209 GOTO_OPCODE(ip) @ jump to next instruction 8210.LOP_APUT_OBJECT_skip_check: 8211 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8212 GET_INST_OPCODE(ip) @ extract opcode from rINST 8213 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8214 GOTO_OPCODE(ip) @ jump to next instruction 8215 8216/* continuation for OP_IGET */ 8217 8218 /* 8219 * Currently: 8220 * r0 holds resolved field 8221 * r9 holds object 8222 */ 8223.LOP_IGET_finish: 8224 @bl common_squeak0 8225 cmp r9, #0 @ check object for null 8226 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8227 beq common_errNullObject @ object was null 8228 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8229 ubfx r2, rINST, #8, #4 @ r2<- A 8230 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8231 GET_INST_OPCODE(ip) @ extract opcode from rINST 8232 SET_VREG(r0, r2) @ fp[A]<- r0 8233 GOTO_OPCODE(ip) @ jump to next instruction 8234 8235/* continuation for OP_IGET_WIDE */ 8236 8237 /* 8238 * Currently: 8239 * r0 holds resolved field 8240 * r9 holds object 8241 */ 8242.LOP_IGET_WIDE_finish: 8243 cmp r9, #0 @ check object for null 8244 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8245 beq common_errNullObject @ object was null 8246 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8247 ubfx r2, rINST, #8, #4 @ r2<- A 8248 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8249 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8250 GET_INST_OPCODE(ip) @ extract opcode from rINST 8251 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8252 GOTO_OPCODE(ip) @ jump to next instruction 8253 8254/* continuation for OP_IGET_OBJECT */ 8255 8256 /* 8257 * Currently: 8258 * r0 holds resolved field 8259 * r9 holds object 8260 */ 8261.LOP_IGET_OBJECT_finish: 8262 @bl common_squeak0 8263 cmp r9, #0 @ check object for null 8264 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8265 beq common_errNullObject @ object was null 8266 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8267 @ no-op @ acquiring load 8268 mov r2, rINST, lsr #8 @ r2<- A+ 8269 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8270 and r2, r2, #15 @ r2<- A 8271 GET_INST_OPCODE(ip) @ extract opcode from rINST 8272 SET_VREG(r0, r2) @ fp[A]<- r0 8273 GOTO_OPCODE(ip) @ jump to next instruction 8274 8275/* continuation for OP_IGET_BOOLEAN */ 8276 8277 /* 8278 * Currently: 8279 * r0 holds resolved field 8280 * r9 holds object 8281 */ 8282.LOP_IGET_BOOLEAN_finish: 8283 @bl common_squeak1 8284 cmp r9, #0 @ check object for null 8285 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8286 beq common_errNullObject @ object was null 8287 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8288 @ no-op @ acquiring load 8289 mov r2, rINST, lsr #8 @ r2<- A+ 8290 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8291 and r2, r2, #15 @ r2<- A 8292 GET_INST_OPCODE(ip) @ extract opcode from rINST 8293 SET_VREG(r0, r2) @ fp[A]<- r0 8294 GOTO_OPCODE(ip) @ jump to next instruction 8295 8296/* continuation for OP_IGET_BYTE */ 8297 8298 /* 8299 * Currently: 8300 * r0 holds resolved field 8301 * r9 holds object 8302 */ 8303.LOP_IGET_BYTE_finish: 8304 @bl common_squeak2 8305 cmp r9, #0 @ check object for null 8306 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8307 beq common_errNullObject @ object was null 8308 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8309 @ no-op @ acquiring load 8310 mov r2, rINST, lsr #8 @ r2<- A+ 8311 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8312 and r2, r2, #15 @ r2<- A 8313 GET_INST_OPCODE(ip) @ extract opcode from rINST 8314 SET_VREG(r0, r2) @ fp[A]<- r0 8315 GOTO_OPCODE(ip) @ jump to next instruction 8316 8317/* continuation for OP_IGET_CHAR */ 8318 8319 /* 8320 * Currently: 8321 * r0 holds resolved field 8322 * r9 holds object 8323 */ 8324.LOP_IGET_CHAR_finish: 8325 @bl common_squeak3 8326 cmp r9, #0 @ check object for null 8327 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8328 beq common_errNullObject @ object was null 8329 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8330 @ no-op @ acquiring load 8331 mov r2, rINST, lsr #8 @ r2<- A+ 8332 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8333 and r2, r2, #15 @ r2<- A 8334 GET_INST_OPCODE(ip) @ extract opcode from rINST 8335 SET_VREG(r0, r2) @ fp[A]<- r0 8336 GOTO_OPCODE(ip) @ jump to next instruction 8337 8338/* continuation for OP_IGET_SHORT */ 8339 8340 /* 8341 * Currently: 8342 * r0 holds resolved field 8343 * r9 holds object 8344 */ 8345.LOP_IGET_SHORT_finish: 8346 @bl common_squeak4 8347 cmp r9, #0 @ check object for null 8348 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8349 beq common_errNullObject @ object was null 8350 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8351 @ no-op @ acquiring load 8352 mov r2, rINST, lsr #8 @ r2<- A+ 8353 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8354 and r2, r2, #15 @ r2<- A 8355 GET_INST_OPCODE(ip) @ extract opcode from rINST 8356 SET_VREG(r0, r2) @ fp[A]<- r0 8357 GOTO_OPCODE(ip) @ jump to next instruction 8358 8359/* continuation for OP_IPUT */ 8360 8361 /* 8362 * Currently: 8363 * r0 holds resolved field 8364 * r9 holds object 8365 */ 8366.LOP_IPUT_finish: 8367 @bl common_squeak0 8368 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8369 ubfx r1, rINST, #8, #4 @ r1<- A 8370 cmp r9, #0 @ check object for null 8371 GET_VREG(r0, r1) @ r0<- fp[A] 8372 beq common_errNullObject @ object was null 8373 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8374 GET_INST_OPCODE(ip) @ extract opcode from rINST 8375 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8376 GOTO_OPCODE(ip) @ jump to next instruction 8377 8378/* continuation for OP_IPUT_WIDE */ 8379 8380 /* 8381 * Currently: 8382 * r0 holds resolved field 8383 * r9 holds object 8384 */ 8385.LOP_IPUT_WIDE_finish: 8386 ubfx r2, rINST, #8, #4 @ r2<- A 8387 cmp r9, #0 @ check object for null 8388 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8389 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8390 beq common_errNullObject @ object was null 8391 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8392 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8393 GET_INST_OPCODE(ip) @ extract opcode from rINST 8394 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0 8395 GOTO_OPCODE(ip) @ jump to next instruction 8396 8397/* continuation for OP_IPUT_OBJECT */ 8398 8399 /* 8400 * Currently: 8401 * r0 holds resolved field 8402 * r9 holds object 8403 */ 8404.LOP_IPUT_OBJECT_finish: 8405 @bl common_squeak0 8406 mov r1, rINST, lsr #8 @ r1<- A+ 8407 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8408 and r1, r1, #15 @ r1<- A 8409 cmp r9, #0 @ check object for null 8410 GET_VREG(r0, r1) @ r0<- fp[A] 8411 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8412 beq common_errNullObject @ object was null 8413 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8414 GET_INST_OPCODE(ip) @ extract opcode from rINST 8415 @ no-op @ releasing store 8416 str r0, [r9, r3] @ obj.field (32 bits)<- r0 8417 cmp r0, #0 @ stored a null reference? 8418 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 8419 GOTO_OPCODE(ip) @ jump to next instruction 8420 8421/* continuation for OP_IPUT_BOOLEAN */ 8422 8423 /* 8424 * Currently: 8425 * r0 holds resolved field 8426 * r9 holds object 8427 */ 8428.LOP_IPUT_BOOLEAN_finish: 8429 @bl common_squeak1 8430 mov r1, rINST, lsr #8 @ r1<- A+ 8431 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8432 and r1, r1, #15 @ r1<- A 8433 cmp r9, #0 @ check object for null 8434 GET_VREG(r0, r1) @ r0<- fp[A] 8435 beq common_errNullObject @ object was null 8436 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8437 GET_INST_OPCODE(ip) @ extract opcode from rINST 8438 @ no-op @ releasing store 8439 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8440 GOTO_OPCODE(ip) @ jump to next instruction 8441 8442/* continuation for OP_IPUT_BYTE */ 8443 8444 /* 8445 * Currently: 8446 * r0 holds resolved field 8447 * r9 holds object 8448 */ 8449.LOP_IPUT_BYTE_finish: 8450 @bl common_squeak2 8451 mov r1, rINST, lsr #8 @ r1<- A+ 8452 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8453 and r1, r1, #15 @ r1<- A 8454 cmp r9, #0 @ check object for null 8455 GET_VREG(r0, r1) @ r0<- fp[A] 8456 beq common_errNullObject @ object was null 8457 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8458 GET_INST_OPCODE(ip) @ extract opcode from rINST 8459 @ no-op @ releasing store 8460 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8461 GOTO_OPCODE(ip) @ jump to next instruction 8462 8463/* continuation for OP_IPUT_CHAR */ 8464 8465 /* 8466 * Currently: 8467 * r0 holds resolved field 8468 * r9 holds object 8469 */ 8470.LOP_IPUT_CHAR_finish: 8471 @bl common_squeak3 8472 mov r1, rINST, lsr #8 @ r1<- A+ 8473 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8474 and r1, r1, #15 @ r1<- A 8475 cmp r9, #0 @ check object for null 8476 GET_VREG(r0, r1) @ r0<- fp[A] 8477 beq common_errNullObject @ object was null 8478 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8479 GET_INST_OPCODE(ip) @ extract opcode from rINST 8480 @ no-op @ releasing store 8481 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8482 GOTO_OPCODE(ip) @ jump to next instruction 8483 8484/* continuation for OP_IPUT_SHORT */ 8485 8486 /* 8487 * Currently: 8488 * r0 holds resolved field 8489 * r9 holds object 8490 */ 8491.LOP_IPUT_SHORT_finish: 8492 @bl common_squeak4 8493 mov r1, rINST, lsr #8 @ r1<- A+ 8494 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8495 and r1, r1, #15 @ r1<- A 8496 cmp r9, #0 @ check object for null 8497 GET_VREG(r0, r1) @ r0<- fp[A] 8498 beq common_errNullObject @ object was null 8499 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8500 GET_INST_OPCODE(ip) @ extract opcode from rINST 8501 @ no-op @ releasing store 8502 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8503 GOTO_OPCODE(ip) @ jump to next instruction 8504 8505/* continuation for OP_SGET */ 8506 8507 /* 8508 * Continuation if the field has not yet been resolved. 8509 * r1: BBBB field ref 8510 */ 8511.LOP_SGET_resolve: 8512 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8513 EXPORT_PC() @ resolve() could throw, so export now 8514 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8515 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8516 cmp r0, #0 @ success? 8517 bne .LOP_SGET_finish @ yes, finish 8518 b common_exceptionThrown @ no, handle exception 8519 8520/* continuation for OP_SGET_WIDE */ 8521 8522 /* 8523 * Continuation if the field has not yet been resolved. 8524 * r1: BBBB field ref 8525 * 8526 * Returns StaticField pointer in r0. 8527 */ 8528.LOP_SGET_WIDE_resolve: 8529 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8530 EXPORT_PC() @ resolve() could throw, so export now 8531 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8532 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8533 cmp r0, #0 @ success? 8534 bne .LOP_SGET_WIDE_finish @ yes, finish 8535 b common_exceptionThrown @ no, handle exception 8536 8537/* continuation for OP_SGET_OBJECT */ 8538 8539 /* 8540 * Continuation if the field has not yet been resolved. 8541 * r1: BBBB field ref 8542 */ 8543.LOP_SGET_OBJECT_resolve: 8544 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8545 EXPORT_PC() @ resolve() could throw, so export now 8546 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8547 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8548 cmp r0, #0 @ success? 8549 bne .LOP_SGET_OBJECT_finish @ yes, finish 8550 b common_exceptionThrown @ no, handle exception 8551 8552/* continuation for OP_SGET_BOOLEAN */ 8553 8554 /* 8555 * Continuation if the field has not yet been resolved. 8556 * r1: BBBB field ref 8557 */ 8558.LOP_SGET_BOOLEAN_resolve: 8559 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8560 EXPORT_PC() @ resolve() could throw, so export now 8561 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8562 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8563 cmp r0, #0 @ success? 8564 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8565 b common_exceptionThrown @ no, handle exception 8566 8567/* continuation for OP_SGET_BYTE */ 8568 8569 /* 8570 * Continuation if the field has not yet been resolved. 8571 * r1: BBBB field ref 8572 */ 8573.LOP_SGET_BYTE_resolve: 8574 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8575 EXPORT_PC() @ resolve() could throw, so export now 8576 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8577 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8578 cmp r0, #0 @ success? 8579 bne .LOP_SGET_BYTE_finish @ yes, finish 8580 b common_exceptionThrown @ no, handle exception 8581 8582/* continuation for OP_SGET_CHAR */ 8583 8584 /* 8585 * Continuation if the field has not yet been resolved. 8586 * r1: BBBB field ref 8587 */ 8588.LOP_SGET_CHAR_resolve: 8589 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8590 EXPORT_PC() @ resolve() could throw, so export now 8591 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8592 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8593 cmp r0, #0 @ success? 8594 bne .LOP_SGET_CHAR_finish @ yes, finish 8595 b common_exceptionThrown @ no, handle exception 8596 8597/* continuation for OP_SGET_SHORT */ 8598 8599 /* 8600 * Continuation if the field has not yet been resolved. 8601 * r1: BBBB field ref 8602 */ 8603.LOP_SGET_SHORT_resolve: 8604 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8605 EXPORT_PC() @ resolve() could throw, so export now 8606 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8607 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8608 cmp r0, #0 @ success? 8609 bne .LOP_SGET_SHORT_finish @ yes, finish 8610 b common_exceptionThrown @ no, handle exception 8611 8612/* continuation for OP_SPUT */ 8613 8614 /* 8615 * Continuation if the field has not yet been resolved. 8616 * r1: BBBB field ref 8617 */ 8618.LOP_SPUT_resolve: 8619 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8620 EXPORT_PC() @ resolve() could throw, so export now 8621 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8622 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8623 cmp r0, #0 @ success? 8624 bne .LOP_SPUT_finish @ yes, finish 8625 b common_exceptionThrown @ no, handle exception 8626 8627/* continuation for OP_SPUT_WIDE */ 8628 8629 /* 8630 * Continuation if the field has not yet been resolved. 8631 * r1: BBBB field ref 8632 * r9: &fp[AA] 8633 * 8634 * Returns StaticField pointer in r2. 8635 */ 8636.LOP_SPUT_WIDE_resolve: 8637 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8638 EXPORT_PC() @ resolve() could throw, so export now 8639 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8640 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8641 cmp r0, #0 @ success? 8642 mov r2, r0 @ copy to r2 8643 bne .LOP_SPUT_WIDE_finish @ yes, finish 8644 b common_exceptionThrown @ no, handle exception 8645 8646/* continuation for OP_SPUT_OBJECT */ 8647.LOP_SPUT_OBJECT_finish: @ field ptr in r0 8648 mov r2, rINST, lsr #8 @ r2<- AA 8649 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8650 GET_VREG(r1, r2) @ r1<- fp[AA] 8651 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8652 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz 8653 GET_INST_OPCODE(ip) @ extract opcode from rINST 8654 @ no-op @ releasing store 8655 str r1, [r0, #offStaticField_value] @ field<- vAA 8656 cmp r1, #0 @ stored a null object? 8657 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 8658 GOTO_OPCODE(ip) @ jump to next instruction 8659 8660/* continuation for OP_SPUT_BOOLEAN */ 8661 8662 /* 8663 * Continuation if the field has not yet been resolved. 8664 * r1: BBBB field ref 8665 */ 8666.LOP_SPUT_BOOLEAN_resolve: 8667 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8668 EXPORT_PC() @ resolve() could throw, so export now 8669 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8670 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8671 cmp r0, #0 @ success? 8672 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 8673 b common_exceptionThrown @ no, handle exception 8674 8675/* continuation for OP_SPUT_BYTE */ 8676 8677 /* 8678 * Continuation if the field has not yet been resolved. 8679 * r1: BBBB field ref 8680 */ 8681.LOP_SPUT_BYTE_resolve: 8682 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8683 EXPORT_PC() @ resolve() could throw, so export now 8684 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8685 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8686 cmp r0, #0 @ success? 8687 bne .LOP_SPUT_BYTE_finish @ yes, finish 8688 b common_exceptionThrown @ no, handle exception 8689 8690/* continuation for OP_SPUT_CHAR */ 8691 8692 /* 8693 * Continuation if the field has not yet been resolved. 8694 * r1: BBBB field ref 8695 */ 8696.LOP_SPUT_CHAR_resolve: 8697 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8698 EXPORT_PC() @ resolve() could throw, so export now 8699 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8700 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8701 cmp r0, #0 @ success? 8702 bne .LOP_SPUT_CHAR_finish @ yes, finish 8703 b common_exceptionThrown @ no, handle exception 8704 8705/* continuation for OP_SPUT_SHORT */ 8706 8707 /* 8708 * Continuation if the field has not yet been resolved. 8709 * r1: BBBB field ref 8710 */ 8711.LOP_SPUT_SHORT_resolve: 8712 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8713 EXPORT_PC() @ resolve() could throw, so export now 8714 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8715 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8716 cmp r0, #0 @ success? 8717 bne .LOP_SPUT_SHORT_finish @ yes, finish 8718 b common_exceptionThrown @ no, handle exception 8719 8720/* continuation for OP_INVOKE_VIRTUAL */ 8721 8722 /* 8723 * At this point: 8724 * r0 = resolved base method 8725 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8726 */ 8727.LOP_INVOKE_VIRTUAL_continue: 8728 GET_VREG(r1, r10) @ r1<- "this" ptr 8729 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8730 cmp r1, #0 @ is "this" null? 8731 beq common_errNullObject @ null "this", throw exception 8732 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8733 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8734 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8735 bl common_invokeMethodNoRange @ continue on 8736 8737/* continuation for OP_INVOKE_SUPER */ 8738 8739 /* 8740 * At this point: 8741 * r0 = resolved base method 8742 * r9 = method->clazz 8743 */ 8744.LOP_INVOKE_SUPER_continue: 8745 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8746 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8747 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8748 EXPORT_PC() @ must export for invoke 8749 cmp r2, r3 @ compare (methodIndex, vtableCount) 8750 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 8751 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8752 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8753 bl common_invokeMethodNoRange @ continue on 8754 8755.LOP_INVOKE_SUPER_resolve: 8756 mov r0, r9 @ r0<- method->clazz 8757 mov r2, #METHOD_VIRTUAL @ resolver method type 8758 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8759 cmp r0, #0 @ got null? 8760 bne .LOP_INVOKE_SUPER_continue @ no, continue 8761 b common_exceptionThrown @ yes, handle exception 8762 8763 /* 8764 * Throw a NoSuchMethodError with the method name as the message. 8765 * r0 = resolved base method 8766 */ 8767.LOP_INVOKE_SUPER_nsm: 8768 ldr r1, [r0, #offMethod_name] @ r1<- method name 8769 b common_errNoSuchMethod 8770 8771/* continuation for OP_INVOKE_DIRECT */ 8772 8773 /* 8774 * On entry: 8775 * r1 = reference (BBBB or CCCC) 8776 * r10 = "this" register 8777 */ 8778.LOP_INVOKE_DIRECT_resolve: 8779 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8780 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8781 mov r2, #METHOD_DIRECT @ resolver method type 8782 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8783 cmp r0, #0 @ got null? 8784 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8785 bne .LOP_INVOKE_DIRECT_finish @ no, continue 8786 b common_exceptionThrown @ yes, handle exception 8787 8788/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 8789 8790 /* 8791 * At this point: 8792 * r0 = resolved base method 8793 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8794 */ 8795.LOP_INVOKE_VIRTUAL_RANGE_continue: 8796 GET_VREG(r1, r10) @ r1<- "this" ptr 8797 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8798 cmp r1, #0 @ is "this" null? 8799 beq common_errNullObject @ null "this", throw exception 8800 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8801 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8802 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8803 bl common_invokeMethodRange @ continue on 8804 8805/* continuation for OP_INVOKE_SUPER_RANGE */ 8806 8807 /* 8808 * At this point: 8809 * r0 = resolved base method 8810 * r9 = method->clazz 8811 */ 8812.LOP_INVOKE_SUPER_RANGE_continue: 8813 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8814 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8815 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8816 EXPORT_PC() @ must export for invoke 8817 cmp r2, r3 @ compare (methodIndex, vtableCount) 8818 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 8819 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8820 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8821 bl common_invokeMethodRange @ continue on 8822 8823.LOP_INVOKE_SUPER_RANGE_resolve: 8824 mov r0, r9 @ r0<- method->clazz 8825 mov r2, #METHOD_VIRTUAL @ resolver method type 8826 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8827 cmp r0, #0 @ got null? 8828 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 8829 b common_exceptionThrown @ yes, handle exception 8830 8831 /* 8832 * Throw a NoSuchMethodError with the method name as the message. 8833 * r0 = resolved base method 8834 */ 8835.LOP_INVOKE_SUPER_RANGE_nsm: 8836 ldr r1, [r0, #offMethod_name] @ r1<- method name 8837 b common_errNoSuchMethod 8838 8839/* continuation for OP_INVOKE_DIRECT_RANGE */ 8840 8841 /* 8842 * On entry: 8843 * r1 = reference (BBBB or CCCC) 8844 * r10 = "this" register 8845 */ 8846.LOP_INVOKE_DIRECT_RANGE_resolve: 8847 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8848 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8849 mov r2, #METHOD_DIRECT @ resolver method type 8850 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8851 cmp r0, #0 @ got null? 8852 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8853 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 8854 b common_exceptionThrown @ yes, handle exception 8855 8856/* continuation for OP_FLOAT_TO_LONG */ 8857/* 8858 * Convert the float in r0 to a long in r0/r1. 8859 * 8860 * We have to clip values to long min/max per the specification. The 8861 * expected common case is a "reasonable" value that converts directly 8862 * to modest integer. The EABI convert function isn't doing this for us. 8863 */ 8864f2l_doconv: 8865 stmfd sp!, {r4, lr} 8866 mov r1, #0x5f000000 @ (float)maxlong 8867 mov r4, r0 8868 bl __aeabi_fcmpge @ is arg >= maxlong? 8869 cmp r0, #0 @ nonzero == yes 8870 mvnne r0, #0 @ return maxlong (7fffffff) 8871 mvnne r1, #0x80000000 8872 ldmnefd sp!, {r4, pc} 8873 8874 mov r0, r4 @ recover arg 8875 mov r1, #0xdf000000 @ (float)minlong 8876 bl __aeabi_fcmple @ is arg <= minlong? 8877 cmp r0, #0 @ nonzero == yes 8878 movne r0, #0 @ return minlong (80000000) 8879 movne r1, #0x80000000 8880 ldmnefd sp!, {r4, pc} 8881 8882 mov r0, r4 @ recover arg 8883 mov r1, r4 8884 bl __aeabi_fcmpeq @ is arg == self? 8885 cmp r0, #0 @ zero == no 8886 moveq r1, #0 @ return zero for NaN 8887 ldmeqfd sp!, {r4, pc} 8888 8889 mov r0, r4 @ recover arg 8890 bl __aeabi_f2lz @ convert float to long 8891 ldmfd sp!, {r4, pc} 8892 8893/* continuation for OP_DOUBLE_TO_LONG */ 8894/* 8895 * Convert the double in r0/r1 to a long in r0/r1. 8896 * 8897 * We have to clip values to long min/max per the specification. The 8898 * expected common case is a "reasonable" value that converts directly 8899 * to modest integer. The EABI convert function isn't doing this for us. 8900 */ 8901d2l_doconv: 8902 stmfd sp!, {r4, r5, lr} @ save regs 8903 mov r3, #0x43000000 @ maxlong, as a double (high word) 8904 add r3, #0x00e00000 @ 0x43e00000 8905 mov r2, #0 @ maxlong, as a double (low word) 8906 sub sp, sp, #4 @ align for EABI 8907 mov r4, r0 @ save a copy of r0 8908 mov r5, r1 @ and r1 8909 bl __aeabi_dcmpge @ is arg >= maxlong? 8910 cmp r0, #0 @ nonzero == yes 8911 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 8912 mvnne r1, #0x80000000 8913 bne 1f 8914 8915 mov r0, r4 @ recover arg 8916 mov r1, r5 8917 mov r3, #0xc3000000 @ minlong, as a double (high word) 8918 add r3, #0x00e00000 @ 0xc3e00000 8919 mov r2, #0 @ minlong, as a double (low word) 8920 bl __aeabi_dcmple @ is arg <= minlong? 8921 cmp r0, #0 @ nonzero == yes 8922 movne r0, #0 @ return minlong (8000000000000000) 8923 movne r1, #0x80000000 8924 bne 1f 8925 8926 mov r0, r4 @ recover arg 8927 mov r1, r5 8928 mov r2, r4 @ compare against self 8929 mov r3, r5 8930 bl __aeabi_dcmpeq @ is arg == self? 8931 cmp r0, #0 @ zero == no 8932 moveq r1, #0 @ return zero for NaN 8933 beq 1f 8934 8935 mov r0, r4 @ recover arg 8936 mov r1, r5 8937 bl __aeabi_d2lz @ convert double to long 8938 89391: 8940 add sp, sp, #4 8941 ldmfd sp!, {r4, r5, pc} 8942 8943/* continuation for OP_MUL_LONG */ 8944 8945.LOP_MUL_LONG_finish: 8946 GET_INST_OPCODE(ip) @ extract opcode from rINST 8947 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 8948 GOTO_OPCODE(ip) @ jump to next instruction 8949 8950/* continuation for OP_SHL_LONG */ 8951 8952.LOP_SHL_LONG_finish: 8953 mov r0, r0, asl r2 @ r0<- r0 << r2 8954 GET_INST_OPCODE(ip) @ extract opcode from rINST 8955 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8956 GOTO_OPCODE(ip) @ jump to next instruction 8957 8958/* continuation for OP_SHR_LONG */ 8959 8960.LOP_SHR_LONG_finish: 8961 mov r1, r1, asr r2 @ r1<- r1 >> r2 8962 GET_INST_OPCODE(ip) @ extract opcode from rINST 8963 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8964 GOTO_OPCODE(ip) @ jump to next instruction 8965 8966/* continuation for OP_USHR_LONG */ 8967 8968.LOP_USHR_LONG_finish: 8969 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 8970 GET_INST_OPCODE(ip) @ extract opcode from rINST 8971 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8972 GOTO_OPCODE(ip) @ jump to next instruction 8973 8974/* continuation for OP_SHL_LONG_2ADDR */ 8975 8976.LOP_SHL_LONG_2ADDR_finish: 8977 GET_INST_OPCODE(ip) @ extract opcode from rINST 8978 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8979 GOTO_OPCODE(ip) @ jump to next instruction 8980 8981/* continuation for OP_SHR_LONG_2ADDR */ 8982 8983.LOP_SHR_LONG_2ADDR_finish: 8984 GET_INST_OPCODE(ip) @ extract opcode from rINST 8985 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8986 GOTO_OPCODE(ip) @ jump to next instruction 8987 8988/* continuation for OP_USHR_LONG_2ADDR */ 8989 8990.LOP_USHR_LONG_2ADDR_finish: 8991 GET_INST_OPCODE(ip) @ extract opcode from rINST 8992 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8993 GOTO_OPCODE(ip) @ jump to next instruction 8994 8995/* continuation for OP_IGET_VOLATILE */ 8996 8997 /* 8998 * Currently: 8999 * r0 holds resolved field 9000 * r9 holds object 9001 */ 9002.LOP_IGET_VOLATILE_finish: 9003 @bl common_squeak0 9004 cmp r9, #0 @ check object for null 9005 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9006 beq common_errNullObject @ object was null 9007 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9008 SMP_DMB @ acquiring load 9009 mov r2, rINST, lsr #8 @ r2<- A+ 9010 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9011 and r2, r2, #15 @ r2<- A 9012 GET_INST_OPCODE(ip) @ extract opcode from rINST 9013 SET_VREG(r0, r2) @ fp[A]<- r0 9014 GOTO_OPCODE(ip) @ jump to next instruction 9015 9016/* continuation for OP_IPUT_VOLATILE */ 9017 9018 /* 9019 * Currently: 9020 * r0 holds resolved field 9021 * r9 holds object 9022 */ 9023.LOP_IPUT_VOLATILE_finish: 9024 @bl common_squeak0 9025 mov r1, rINST, lsr #8 @ r1<- A+ 9026 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9027 and r1, r1, #15 @ r1<- A 9028 cmp r9, #0 @ check object for null 9029 GET_VREG(r0, r1) @ r0<- fp[A] 9030 beq common_errNullObject @ object was null 9031 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9032 GET_INST_OPCODE(ip) @ extract opcode from rINST 9033 SMP_DMB @ releasing store 9034 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 9035 GOTO_OPCODE(ip) @ jump to next instruction 9036 9037/* continuation for OP_SGET_VOLATILE */ 9038 9039 /* 9040 * Continuation if the field has not yet been resolved. 9041 * r1: BBBB field ref 9042 */ 9043.LOP_SGET_VOLATILE_resolve: 9044 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9045 EXPORT_PC() @ resolve() could throw, so export now 9046 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9047 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9048 cmp r0, #0 @ success? 9049 bne .LOP_SGET_VOLATILE_finish @ yes, finish 9050 b common_exceptionThrown @ no, handle exception 9051 9052/* continuation for OP_SPUT_VOLATILE */ 9053 9054 /* 9055 * Continuation if the field has not yet been resolved. 9056 * r1: BBBB field ref 9057 */ 9058.LOP_SPUT_VOLATILE_resolve: 9059 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9060 EXPORT_PC() @ resolve() could throw, so export now 9061 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9062 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9063 cmp r0, #0 @ success? 9064 bne .LOP_SPUT_VOLATILE_finish @ yes, finish 9065 b common_exceptionThrown @ no, handle exception 9066 9067/* continuation for OP_IGET_OBJECT_VOLATILE */ 9068 9069 /* 9070 * Currently: 9071 * r0 holds resolved field 9072 * r9 holds object 9073 */ 9074.LOP_IGET_OBJECT_VOLATILE_finish: 9075 @bl common_squeak0 9076 cmp r9, #0 @ check object for null 9077 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9078 beq common_errNullObject @ object was null 9079 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9080 SMP_DMB @ acquiring load 9081 mov r2, rINST, lsr #8 @ r2<- A+ 9082 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9083 and r2, r2, #15 @ r2<- A 9084 GET_INST_OPCODE(ip) @ extract opcode from rINST 9085 SET_VREG(r0, r2) @ fp[A]<- r0 9086 GOTO_OPCODE(ip) @ jump to next instruction 9087 9088/* continuation for OP_IGET_WIDE_VOLATILE */ 9089 9090 /* 9091 * Currently: 9092 * r0 holds resolved field 9093 * r9 holds object 9094 */ 9095.LOP_IGET_WIDE_VOLATILE_finish: 9096 cmp r9, #0 @ check object for null 9097 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9098 beq common_errNullObject @ object was null 9099 .if 1 9100 add r0, r9, r3 @ r0<- address of field 9101 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 9102 .else 9103 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 9104 .endif 9105 mov r2, rINST, lsr #8 @ r2<- A+ 9106 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9107 and r2, r2, #15 @ r2<- A 9108 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 9109 GET_INST_OPCODE(ip) @ extract opcode from rINST 9110 stmia r3, {r0-r1} @ fp[A]<- r0/r1 9111 GOTO_OPCODE(ip) @ jump to next instruction 9112 9113/* continuation for OP_IPUT_WIDE_VOLATILE */ 9114 9115 /* 9116 * Currently: 9117 * r0 holds resolved field 9118 * r9 holds object 9119 */ 9120.LOP_IPUT_WIDE_VOLATILE_finish: 9121 mov r2, rINST, lsr #8 @ r2<- A+ 9122 cmp r9, #0 @ check object for null 9123 and r2, r2, #15 @ r2<- A 9124 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9125 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 9126 beq common_errNullObject @ object was null 9127 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9128 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 9129 GET_INST_OPCODE(r10) @ extract opcode from rINST 9130 .if 1 9131 add r2, r9, r3 @ r2<- target address 9132 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 9133 .else 9134 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 9135 .endif 9136 GOTO_OPCODE(r10) @ jump to next instruction 9137 9138/* continuation for OP_SGET_WIDE_VOLATILE */ 9139 9140 /* 9141 * Continuation if the field has not yet been resolved. 9142 * r1: BBBB field ref 9143 * 9144 * Returns StaticField pointer in r0. 9145 */ 9146.LOP_SGET_WIDE_VOLATILE_resolve: 9147 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9148 EXPORT_PC() @ resolve() could throw, so export now 9149 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9150 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9151 cmp r0, #0 @ success? 9152 bne .LOP_SGET_WIDE_VOLATILE_finish @ yes, finish 9153 b common_exceptionThrown @ no, handle exception 9154 9155/* continuation for OP_SPUT_WIDE_VOLATILE */ 9156 9157 /* 9158 * Continuation if the field has not yet been resolved. 9159 * r1: BBBB field ref 9160 * r9: &fp[AA] 9161 * 9162 * Returns StaticField pointer in r2. 9163 */ 9164.LOP_SPUT_WIDE_VOLATILE_resolve: 9165 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9166 EXPORT_PC() @ resolve() could throw, so export now 9167 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9168 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9169 cmp r0, #0 @ success? 9170 mov r2, r0 @ copy to r2 9171 bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish 9172 b common_exceptionThrown @ no, handle exception 9173 9174/* continuation for OP_EXECUTE_INLINE */ 9175 9176 /* 9177 * Extract args, call function. 9178 * r0 = #of args (0-4) 9179 * r10 = call index 9180 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9181 * 9182 * Other ideas: 9183 * - Use a jump table from the main piece to jump directly into the 9184 * AND/LDR pairs. Costs a data load, saves a branch. 9185 * - Have five separate pieces that do the loading, so we can work the 9186 * interleave a little better. Increases code size. 9187 */ 9188.LOP_EXECUTE_INLINE_continue: 9189 rsb r0, r0, #4 @ r0<- 4-r0 9190 FETCH(r9, 2) @ r9<- FEDC 9191 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9192 bl common_abort @ (skipped due to ARM prefetch) 91934: and ip, r9, #0xf000 @ isolate F 9194 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 91953: and ip, r9, #0x0f00 @ isolate E 9196 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 91972: and ip, r9, #0x00f0 @ isolate D 9198 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 91991: and ip, r9, #0x000f @ isolate C 9200 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 92010: 9202 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 9203 ldr pc, [r9, r10, lsl #4] @ sizeof=16, "func" is first entry 9204 @ (not reached) 9205 9206.LOP_EXECUTE_INLINE_table: 9207 .word gDvmInlineOpsTable 9208 9209/* continuation for OP_EXECUTE_INLINE_RANGE */ 9210 9211 /* 9212 * Extract args, call function. 9213 * r0 = #of args (0-4) 9214 * r10 = call index 9215 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9216 */ 9217.LOP_EXECUTE_INLINE_RANGE_continue: 9218 rsb r0, r0, #4 @ r0<- 4-r0 9219 FETCH(r9, 2) @ r9<- CCCC 9220 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9221 bl common_abort @ (skipped due to ARM prefetch) 92224: add ip, r9, #3 @ base+3 9223 GET_VREG(r3, ip) @ r3<- vBase[3] 92243: add ip, r9, #2 @ base+2 9225 GET_VREG(r2, ip) @ r2<- vBase[2] 92262: add ip, r9, #1 @ base+1 9227 GET_VREG(r1, ip) @ r1<- vBase[1] 92281: add ip, r9, #0 @ (nop) 9229 GET_VREG(r0, ip) @ r0<- vBase[0] 92300: 9231 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation 9232 ldr pc, [r9, r10, lsl #4] @ sizeof=16, "func" is first entry 9233 @ (not reached) 9234 9235.LOP_EXECUTE_INLINE_RANGE_table: 9236 .word gDvmInlineOpsTable 9237 9238/* continuation for OP_IPUT_OBJECT_VOLATILE */ 9239 9240 /* 9241 * Currently: 9242 * r0 holds resolved field 9243 * r9 holds object 9244 */ 9245.LOP_IPUT_OBJECT_VOLATILE_finish: 9246 @bl common_squeak0 9247 mov r1, rINST, lsr #8 @ r1<- A+ 9248 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9249 and r1, r1, #15 @ r1<- A 9250 cmp r9, #0 @ check object for null 9251 GET_VREG(r0, r1) @ r0<- fp[A] 9252 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 9253 beq common_errNullObject @ object was null 9254 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9255 GET_INST_OPCODE(ip) @ extract opcode from rINST 9256 SMP_DMB @ releasing store 9257 str r0, [r9, r3] @ obj.field (32 bits)<- r0 9258 cmp r0, #0 @ stored a null reference? 9259 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 9260 GOTO_OPCODE(ip) @ jump to next instruction 9261 9262/* continuation for OP_SGET_OBJECT_VOLATILE */ 9263 9264 /* 9265 * Continuation if the field has not yet been resolved. 9266 * r1: BBBB field ref 9267 */ 9268.LOP_SGET_OBJECT_VOLATILE_resolve: 9269 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9270 EXPORT_PC() @ resolve() could throw, so export now 9271 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9272 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9273 cmp r0, #0 @ success? 9274 bne .LOP_SGET_OBJECT_VOLATILE_finish @ yes, finish 9275 b common_exceptionThrown @ no, handle exception 9276 9277/* continuation for OP_SPUT_OBJECT_VOLATILE */ 9278.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0 9279 mov r2, rINST, lsr #8 @ r2<- AA 9280 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9281 GET_VREG(r1, r2) @ r1<- fp[AA] 9282 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 9283 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz 9284 GET_INST_OPCODE(ip) @ extract opcode from rINST 9285 SMP_DMB @ releasing store 9286 str r1, [r0, #offStaticField_value] @ field<- vAA 9287 cmp r1, #0 @ stored a null object? 9288 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 9289 GOTO_OPCODE(ip) @ jump to next instruction 9290 9291 .size dvmAsmSisterStart, .-dvmAsmSisterStart 9292 .global dvmAsmSisterEnd 9293dvmAsmSisterEnd: 9294 9295/* File: armv5te/footer.S */ 9296 9297/* 9298 * =========================================================================== 9299 * Common subroutines and data 9300 * =========================================================================== 9301 */ 9302 9303 9304 9305 .text 9306 .align 2 9307 9308#if defined(WITH_JIT) 9309#if defined(WITH_SELF_VERIFICATION) 9310 .global dvmJitToInterpPunt 9311dvmJitToInterpPunt: 9312 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9313 mov r2,#kSVSPunt @ r2<- interpreter entry point 9314 mov r3, #0 9315 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9316 b jitSVShadowRunEnd @ doesn't return 9317 9318 .global dvmJitToInterpSingleStep 9319dvmJitToInterpSingleStep: 9320 str lr,[rGLUE,#offGlue_jitResumeNPC] 9321 str r1,[rGLUE,#offGlue_jitResumeDPC] 9322 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 9323 b jitSVShadowRunEnd @ doesn't return 9324 9325 .global dvmJitToInterpNoChainNoProfile 9326dvmJitToInterpNoChainNoProfile: 9327 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9328 mov r0,rPC @ pass our target PC 9329 mov r2,#kSVSNoProfile @ r2<- interpreter entry point 9330 mov r3, #0 @ 0 means !inJitCodeCache 9331 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land 9332 b jitSVShadowRunEnd @ doesn't return 9333 9334 .global dvmJitToInterpTraceSelectNoChain 9335dvmJitToInterpTraceSelectNoChain: 9336 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9337 mov r0,rPC @ pass our target PC 9338 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9339 mov r3, #0 @ 0 means !inJitCodeCache 9340 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9341 b jitSVShadowRunEnd @ doesn't return 9342 9343 .global dvmJitToInterpTraceSelect 9344dvmJitToInterpTraceSelect: 9345 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9346 ldr r0,[lr, #-1] @ pass our target PC 9347 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9348 mov r3, #0 @ 0 means !inJitCodeCache 9349 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9350 b jitSVShadowRunEnd @ doesn't return 9351 9352 .global dvmJitToInterpBackwardBranch 9353dvmJitToInterpBackwardBranch: 9354 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9355 ldr r0,[lr, #-1] @ pass our target PC 9356 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 9357 mov r3, #0 @ 0 means !inJitCodeCache 9358 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9359 b jitSVShadowRunEnd @ doesn't return 9360 9361 .global dvmJitToInterpNormal 9362dvmJitToInterpNormal: 9363 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9364 ldr r0,[lr, #-1] @ pass our target PC 9365 mov r2,#kSVSNormal @ r2<- interpreter entry point 9366 mov r3, #0 @ 0 means !inJitCodeCache 9367 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9368 b jitSVShadowRunEnd @ doesn't return 9369 9370 .global dvmJitToInterpNoChain 9371dvmJitToInterpNoChain: 9372 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9373 mov r0,rPC @ pass our target PC 9374 mov r2,#kSVSNoChain @ r2<- interpreter entry point 9375 mov r3, #0 @ 0 means !inJitCodeCache 9376 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9377 b jitSVShadowRunEnd @ doesn't return 9378#else 9379/* 9380 * Return from the translation cache to the interpreter when the compiler is 9381 * having issues translating/executing a Dalvik instruction. We have to skip 9382 * the code cache lookup otherwise it is possible to indefinitely bouce 9383 * between the interpreter and the code cache if the instruction that fails 9384 * to be compiled happens to be at a trace start. 9385 */ 9386 .global dvmJitToInterpPunt 9387dvmJitToInterpPunt: 9388 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9389 mov rPC, r0 9390#if defined(WITH_JIT_TUNING) 9391 mov r0,lr 9392 bl dvmBumpPunt; 9393#endif 9394 EXPORT_PC() 9395 mov r0, #0 9396 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9397 adrl rIBASE, dvmAsmInstructionStart 9398 FETCH_INST() 9399 GET_INST_OPCODE(ip) 9400 GOTO_OPCODE(ip) 9401 9402/* 9403 * Return to the interpreter to handle a single instruction. 9404 * On entry: 9405 * r0 <= PC 9406 * r1 <= PC of resume instruction 9407 * lr <= resume point in translation 9408 */ 9409 .global dvmJitToInterpSingleStep 9410dvmJitToInterpSingleStep: 9411 str lr,[rGLUE,#offGlue_jitResumeNPC] 9412 str r1,[rGLUE,#offGlue_jitResumeDPC] 9413 mov r1,#kInterpEntryInstr 9414 @ enum is 4 byte in aapcs-EABI 9415 str r1, [rGLUE, #offGlue_entryPoint] 9416 mov rPC,r0 9417 EXPORT_PC() 9418 9419 adrl rIBASE, dvmAsmInstructionStart 9420 mov r2,#kJitSingleStep @ Ask for single step and then revert 9421 str r2,[rGLUE,#offGlue_jitState] 9422 mov r1,#1 @ set changeInterp to bail to debug interp 9423 b common_gotoBail 9424 9425/* 9426 * Return from the translation cache and immediately request 9427 * a translation for the exit target. Commonly used for callees. 9428 */ 9429 .global dvmJitToInterpTraceSelectNoChain 9430dvmJitToInterpTraceSelectNoChain: 9431#if defined(WITH_JIT_TUNING) 9432 bl dvmBumpNoChain 9433#endif 9434 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9435 mov r0,rPC 9436 bl dvmJitGetCodeAddr @ Is there a translation? 9437 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9438 mov r1, rPC @ arg1 of translation may need this 9439 mov lr, #0 @ in case target is HANDLER_INTERPRET 9440 cmp r0,#0 @ !0 means translation exists 9441 bxne r0 @ continue native execution if so 9442 b 2f @ branch over to use the interpreter 9443 9444/* 9445 * Return from the translation cache and immediately request 9446 * a translation for the exit target. Commonly used following 9447 * invokes. 9448 */ 9449 .global dvmJitToInterpTraceSelect 9450dvmJitToInterpTraceSelect: 9451 ldr rPC,[lr, #-1] @ get our target PC 9452 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9453 add rINST,lr,#-5 @ save start of chain branch 9454 add rINST, #-4 @ .. which is 9 bytes back 9455 mov r0,rPC 9456 bl dvmJitGetCodeAddr @ Is there a translation? 9457 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9458 cmp r0,#0 9459 beq 2f 9460 mov r1,rINST 9461 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9462 mov r1, rPC @ arg1 of translation may need this 9463 mov lr, #0 @ in case target is HANDLER_INTERPRET 9464 cmp r0,#0 @ successful chain? 9465 bxne r0 @ continue native execution 9466 b toInterpreter @ didn't chain - resume with interpreter 9467 9468/* No translation, so request one if profiling isn't disabled*/ 94692: 9470 adrl rIBASE, dvmAsmInstructionStart 9471 GET_JIT_PROF_TABLE(r0) 9472 FETCH_INST() 9473 cmp r0, #0 9474 movne r2,#kJitTSelectRequestHot @ ask for trace selection 9475 bne common_selectTrace 9476 GET_INST_OPCODE(ip) 9477 GOTO_OPCODE(ip) 9478 9479/* 9480 * Return from the translation cache to the interpreter. 9481 * The return was done with a BLX from thumb mode, and 9482 * the following 32-bit word contains the target rPC value. 9483 * Note that lr (r14) will have its low-order bit set to denote 9484 * its thumb-mode origin. 9485 * 9486 * We'll need to stash our lr origin away, recover the new 9487 * target and then check to see if there is a translation available 9488 * for our new target. If so, we do a translation chain and 9489 * go back to native execution. Otherwise, it's back to the 9490 * interpreter (after treating this entry as a potential 9491 * trace start). 9492 */ 9493 .global dvmJitToInterpNormal 9494dvmJitToInterpNormal: 9495 ldr rPC,[lr, #-1] @ get our target PC 9496 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9497 add rINST,lr,#-5 @ save start of chain branch 9498 add rINST,#-4 @ .. which is 9 bytes back 9499#if defined(WITH_JIT_TUNING) 9500 bl dvmBumpNormal 9501#endif 9502 mov r0,rPC 9503 bl dvmJitGetCodeAddr @ Is there a translation? 9504 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9505 cmp r0,#0 9506 beq toInterpreter @ go if not, otherwise do chain 9507 mov r1,rINST 9508 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9509 mov r1, rPC @ arg1 of translation may need this 9510 mov lr, #0 @ in case target is HANDLER_INTERPRET 9511 cmp r0,#0 @ successful chain? 9512 bxne r0 @ continue native execution 9513 b toInterpreter @ didn't chain - resume with interpreter 9514 9515/* 9516 * Return from the translation cache to the interpreter to do method invocation. 9517 * Check if translation exists for the callee, but don't chain to it. 9518 */ 9519 .global dvmJitToInterpNoChainNoProfile 9520dvmJitToInterpNoChainNoProfile: 9521#if defined(WITH_JIT_TUNING) 9522 bl dvmBumpNoChain 9523#endif 9524 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9525 mov r0,rPC 9526 bl dvmJitGetCodeAddr @ Is there a translation? 9527 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9528 mov r1, rPC @ arg1 of translation may need this 9529 mov lr, #0 @ in case target is HANDLER_INTERPRET 9530 cmp r0,#0 9531 bxne r0 @ continue native execution if so 9532 EXPORT_PC() 9533 adrl rIBASE, dvmAsmInstructionStart 9534 FETCH_INST() 9535 GET_INST_OPCODE(ip) @ extract opcode from rINST 9536 GOTO_OPCODE(ip) @ jump to next instruction 9537 9538/* 9539 * Return from the translation cache to the interpreter to do method invocation. 9540 * Check if translation exists for the callee, but don't chain to it. 9541 */ 9542 .global dvmJitToInterpNoChain 9543dvmJitToInterpNoChain: 9544#if defined(WITH_JIT_TUNING) 9545 bl dvmBumpNoChain 9546#endif 9547 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9548 mov r0,rPC 9549 bl dvmJitGetCodeAddr @ Is there a translation? 9550 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9551 mov r1, rPC @ arg1 of translation may need this 9552 mov lr, #0 @ in case target is HANDLER_INTERPRET 9553 cmp r0,#0 9554 bxne r0 @ continue native execution if so 9555#endif 9556 9557/* 9558 * No translation, restore interpreter regs and start interpreting. 9559 * rGLUE & rFP were preserved in the translated code, and rPC has 9560 * already been restored by the time we get here. We'll need to set 9561 * up rIBASE & rINST, and load the address of the JitTable into r0. 9562 */ 9563toInterpreter: 9564 EXPORT_PC() 9565 adrl rIBASE, dvmAsmInstructionStart 9566 FETCH_INST() 9567 GET_JIT_PROF_TABLE(r0) 9568 @ NOTE: intended fallthrough 9569 9570/* 9571 * Common code to update potential trace start counter, and initiate 9572 * a trace-build if appropriate. On entry, rPC should point to the 9573 * next instruction to execute, and rINST should be already loaded with 9574 * the next opcode word, and r0 holds a pointer to the jit profile 9575 * table (pJitProfTable). 9576 */ 9577common_testUpdateProfile: 9578 cmp r0,#0 9579 GET_INST_OPCODE(ip) 9580 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 9581 9582common_updateProfile: 9583 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 9584 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits 9585 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter 9586 GET_INST_OPCODE(ip) 9587 subs r1,r1,#1 @ decrement counter 9588 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it 9589 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 9590 9591/* 9592 * Here, we switch to the debug interpreter to request 9593 * trace selection. First, though, check to see if there 9594 * is already a native translation in place (and, if so, 9595 * jump to it now). 9596 */ 9597 GET_JIT_THRESHOLD(r1) 9598 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9599 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter 9600 EXPORT_PC() 9601 mov r0,rPC 9602 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC) 9603 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9604 mov r1, rPC @ arg1 of translation may need this 9605 mov lr, #0 @ in case target is HANDLER_INTERPRET 9606 cmp r0,#0 9607#if !defined(WITH_SELF_VERIFICATION) 9608 bxne r0 @ jump to the translation 9609 mov r2,#kJitTSelectRequest @ ask for trace selection 9610 @ fall-through to common_selectTrace 9611#else 9612 moveq r2,#kJitTSelectRequest @ ask for trace selection 9613 beq common_selectTrace 9614 /* 9615 * At this point, we have a target translation. However, if 9616 * that translation is actually the interpret-only pseudo-translation 9617 * we want to treat it the same as no translation. 9618 */ 9619 mov r10, r0 @ save target 9620 bl dvmCompilerGetInterpretTemplate 9621 cmp r0, r10 @ special case? 9622 bne jitSVShadowRunStart @ set up self verification shadow space 9623 @ Need to clear the inJitCodeCache flag 9624 ldr r10, [rGLUE, #offGlue_self] @ r10 <- glue->self 9625 mov r3, #0 @ 0 means not in the JIT code cache 9626 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land 9627 GET_INST_OPCODE(ip) 9628 GOTO_OPCODE(ip) 9629 /* no return */ 9630#endif 9631 9632/* 9633 * On entry: 9634 * r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot 9635 */ 9636common_selectTrace: 9637 str r2,[rGLUE,#offGlue_jitState] 9638 mov r2,#kInterpEntryInstr @ normal entry reason 9639 str r2,[rGLUE,#offGlue_entryPoint] 9640 mov r1,#1 @ set changeInterp 9641 b common_gotoBail 9642 9643#if defined(WITH_SELF_VERIFICATION) 9644/* 9645 * Save PC and registers to shadow memory for self verification mode 9646 * before jumping to native translation. 9647 * On entry: 9648 * rPC, rFP, rGLUE: the values that they should contain 9649 * r10: the address of the target translation. 9650 */ 9651jitSVShadowRunStart: 9652 mov r0,rPC @ r0<- program counter 9653 mov r1,rFP @ r1<- frame pointer 9654 mov r2,rGLUE @ r2<- InterpState pointer 9655 mov r3,r10 @ r3<- target translation 9656 bl dvmSelfVerificationSaveState @ save registers to shadow space 9657 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 9658 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 9659 bx r10 @ jump to the translation 9660 9661/* 9662 * Restore PC, registers, and interpState to original values 9663 * before jumping back to the interpreter. 9664 */ 9665jitSVShadowRunEnd: 9666 mov r1,rFP @ pass ending fp 9667 bl dvmSelfVerificationRestoreState @ restore pc and fp values 9668 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 9669 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 9670 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 9671 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 9672 cmp r1,#0 @ check for punt condition 9673 beq 1f 9674 mov r2,#kJitSelfVerification @ ask for self verification 9675 str r2,[rGLUE,#offGlue_jitState] 9676 mov r2,#kInterpEntryInstr @ normal entry reason 9677 str r2,[rGLUE,#offGlue_entryPoint] 9678 mov r1,#1 @ set changeInterp 9679 b common_gotoBail 9680 96811: @ exit to interpreter without check 9682 EXPORT_PC() 9683 adrl rIBASE, dvmAsmInstructionStart 9684 FETCH_INST() 9685 GET_INST_OPCODE(ip) 9686 GOTO_OPCODE(ip) 9687#endif 9688 9689#endif 9690 9691/* 9692 * Common code when a backward branch is taken. 9693 * 9694 * TODO: we could avoid a branch by just setting r0 and falling through 9695 * into the common_periodicChecks code, and having a test on r0 at the 9696 * end determine if we should return to the caller or update & branch to 9697 * the next instr. 9698 * 9699 * On entry: 9700 * r9 is PC adjustment *in bytes* 9701 */ 9702common_backwardBranch: 9703 mov r0, #kInterpEntryInstr 9704 bl common_periodicChecks 9705#if defined(WITH_JIT) 9706 GET_JIT_PROF_TABLE(r0) 9707 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9708 cmp r0,#0 9709 bne common_updateProfile 9710 GET_INST_OPCODE(ip) 9711 GOTO_OPCODE(ip) 9712#else 9713 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9714 GET_INST_OPCODE(ip) @ extract opcode from rINST 9715 GOTO_OPCODE(ip) @ jump to next instruction 9716#endif 9717 9718 9719/* 9720 * Need to see if the thread needs to be suspended or debugger/profiler 9721 * activity has begun. If so, we suspend the thread or side-exit to 9722 * the debug interpreter as appropriate. 9723 * 9724 * The common case is no activity on any of these, so we want to figure 9725 * that out quickly. If something is up, we can then sort out what. 9726 * 9727 * We want to be fast if the VM was built without debugger or profiler 9728 * support, but we also need to recognize that the system is usually 9729 * shipped with both of these enabled. 9730 * 9731 * TODO: reduce this so we're just checking a single location. 9732 * 9733 * On entry: 9734 * r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling) 9735 * r9 is trampoline PC adjustment *in bytes* 9736 */ 9737common_periodicChecks: 9738 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9739 9740 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9741 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9742 9743 ldr ip, [r3] @ ip<- suspendCount (int) 9744 9745 cmp r1, #0 @ debugger enabled? 9746 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9747 ldr r2, [r2] @ r2<- activeProfilers (int) 9748 orrnes ip, ip, r1 @ ip<- suspendCount | debuggerActive 9749 /* 9750 * Don't switch the interpreter in the libdvm_traceview build even if the 9751 * profiler is active. 9752 * The code here is opted for less intrusion instead of performance. 9753 * That is, *pActiveProfilers is still loaded into r2 even though it is not 9754 * used when WITH_INLINE_PROFILING is defined. 9755 */ 9756#if !defined(WITH_INLINE_PROFILING) 9757 orrs ip, ip, r2 @ ip<- suspend|debugger|profiler; set Z 9758#endif 9759 9760 9761 bxeq lr @ all zero, return 9762 9763 /* 9764 * One or more interesting events have happened. Figure out what. 9765 * 9766 * If debugging or profiling are compiled in, we need to disambiguate. 9767 * 9768 * r0 still holds the reentry type. 9769 */ 9770 ldr ip, [r3] @ ip<- suspendCount (int) 9771 cmp ip, #0 @ want suspend? 9772 beq 1f @ no, must be debugger/profiler 9773 9774 stmfd sp!, {r0, lr} @ preserve r0 and lr 9775#if defined(WITH_JIT) 9776 /* 9777 * Refresh the Jit's cached copy of profile table pointer. This pointer 9778 * doubles as the Jit's on/off switch. 9779 */ 9780 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable 9781 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9782 ldr r3, [r3] @ r3 <- pJitProfTable 9783 EXPORT_PC() @ need for precise GC 9784 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch 9785#else 9786 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9787 EXPORT_PC() @ need for precise GC 9788#endif 9789 bl dvmCheckSuspendPending @ do full check, suspend if necessary 9790 ldmfd sp!, {r0, lr} @ restore r0 and lr 9791 9792 /* 9793 * Reload the debugger/profiler enable flags. We're checking to see 9794 * if either of these got set while we were suspended. 9795 * 9796 * If WITH_INLINE_PROFILING is configured, don't check whether the profiler 9797 * is enabled or not as the profiling will be done inline. 9798 */ 9799 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9800 cmp r1, #0 @ debugger enabled? 9801 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9802 9803#if !defined(WITH_INLINE_PROFILING) 9804 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9805 ldr r2, [r2] @ r2<- activeProfilers (int) 9806 orrs r1, r1, r2 9807#else 9808 cmp r1, #0 @ only consult the debuggerActive flag 9809#endif 9810 9811 beq 2f 9812 98131: @ debugger/profiler enabled, bail out; glue->entryPoint was set above 9814 str r0, [rGLUE, #offGlue_entryPoint] @ store r0, need for debug/prof 9815 add rPC, rPC, r9 @ update rPC 9816 mov r1, #1 @ "want switch" = true 9817 b common_gotoBail @ side exit 9818 98192: 9820 bx lr @ nothing to do, return 9821 9822 9823/* 9824 * The equivalent of "goto bail", this calls through the "bail handler". 9825 * 9826 * State registers will be saved to the "glue" area before bailing. 9827 * 9828 * On entry: 9829 * r1 is "bool changeInterp", indicating if we want to switch to the 9830 * other interpreter or just bail all the way out 9831 */ 9832common_gotoBail: 9833 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9834 mov r0, rGLUE @ r0<- glue ptr 9835 b dvmMterpStdBail @ call(glue, changeInterp) 9836 9837 @add r1, r1, #1 @ using (boolean+1) 9838 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9839 @bl _longjmp @ does not return 9840 @bl common_abort 9841 9842 9843/* 9844 * Common code for method invocation with range. 9845 * 9846 * On entry: 9847 * r0 is "Method* methodToCall", the method we're trying to call 9848 */ 9849common_invokeMethodRange: 9850.LinvokeNewRange: 9851 @ prepare to copy args to "outs" area of current frame 9852 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9853 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9854 beq .LinvokeArgsDone @ if no args, skip the rest 9855 FETCH(r1, 2) @ r1<- CCCC 9856 9857 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9858 @ (very few methods have > 10 args; could unroll for common cases) 9859 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9860 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9861 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 98621: ldr r1, [r3], #4 @ val = *fp++ 9863 subs r2, r2, #1 @ count-- 9864 str r1, [r10], #4 @ *outs++ = val 9865 bne 1b @ ...while count != 0 9866 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9867 b .LinvokeArgsDone 9868 9869/* 9870 * Common code for method invocation without range. 9871 * 9872 * On entry: 9873 * r0 is "Method* methodToCall", the method we're trying to call 9874 */ 9875common_invokeMethodNoRange: 9876.LinvokeNewNoRange: 9877 @ prepare to copy args to "outs" area of current frame 9878 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9879 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9880 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9881 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9882 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9883 beq .LinvokeArgsDone 9884 9885 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9886.LinvokeNonRange: 9887 rsb r2, r2, #5 @ r2<- 5-r2 9888 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9889 bl common_abort @ (skipped due to ARM prefetch) 98905: and ip, rINST, #0x0f00 @ isolate A 9891 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 9892 mov r0, r0 @ nop 9893 str r2, [r10, #-4]! @ *--outs = vA 98944: and ip, r1, #0xf000 @ isolate G 9895 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 9896 mov r0, r0 @ nop 9897 str r2, [r10, #-4]! @ *--outs = vG 98983: and ip, r1, #0x0f00 @ isolate F 9899 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 9900 mov r0, r0 @ nop 9901 str r2, [r10, #-4]! @ *--outs = vF 99022: and ip, r1, #0x00f0 @ isolate E 9903 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 9904 mov r0, r0 @ nop 9905 str r2, [r10, #-4]! @ *--outs = vE 99061: and ip, r1, #0x000f @ isolate D 9907 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 9908 mov r0, r0 @ nop 9909 str r2, [r10, #-4]! @ *--outs = vD 99100: @ fall through to .LinvokeArgsDone 9911 9912.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 9913 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 9914 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 9915 @ find space for the new stack frame, check for overflow 9916 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 9917 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 9918 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 9919@ bl common_dumpRegs 9920 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 9921 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 9922 cmp r3, r9 @ bottom < interpStackEnd? 9923 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 9924 blo .LstackOverflow @ yes, this frame will overflow stack 9925 9926 @ set up newSaveArea 9927#ifdef EASY_GDB 9928 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 9929 str ip, [r10, #offStackSaveArea_prevSave] 9930#endif 9931 str rFP, [r10, #offStackSaveArea_prevFrame] 9932 str rPC, [r10, #offStackSaveArea_savedPc] 9933#if defined(WITH_JIT) 9934 mov r9, #0 9935 str r9, [r10, #offStackSaveArea_returnAddr] 9936#endif 9937#if defined(WITH_INLINE_PROFILING) 9938 stmfd sp!, {r0-r3} @ preserve r0-r3 9939 mov r1, r6 9940 @ r0=methodToCall, r1=rGlue 9941 bl dvmFastMethodTraceEnter 9942 ldmfd sp!, {r0-r3} @ restore r0-r3 9943#endif 9944 str r0, [r10, #offStackSaveArea_method] 9945 tst r3, #ACC_NATIVE 9946 bne .LinvokeNative 9947 9948 /* 9949 stmfd sp!, {r0-r3} 9950 bl common_printNewline 9951 mov r0, rFP 9952 mov r1, #0 9953 bl dvmDumpFp 9954 ldmfd sp!, {r0-r3} 9955 stmfd sp!, {r0-r3} 9956 mov r0, r1 9957 mov r1, r10 9958 bl dvmDumpFp 9959 bl common_printNewline 9960 ldmfd sp!, {r0-r3} 9961 */ 9962 9963 ldrh r9, [r2] @ r9 <- load INST from new PC 9964 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 9965 mov rPC, r2 @ publish new rPC 9966 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 9967 9968 @ Update "glue" values for the new method 9969 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 9970 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 9971 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 9972#if defined(WITH_JIT) 9973 GET_JIT_PROF_TABLE(r0) 9974 mov rFP, r1 @ fp = newFp 9975 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9976 mov rINST, r9 @ publish new rINST 9977 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9978 cmp r0,#0 9979 bne common_updateProfile 9980 GOTO_OPCODE(ip) @ jump to next instruction 9981#else 9982 mov rFP, r1 @ fp = newFp 9983 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9984 mov rINST, r9 @ publish new rINST 9985 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9986 GOTO_OPCODE(ip) @ jump to next instruction 9987#endif 9988 9989.LinvokeNative: 9990 @ Prep for the native call 9991 @ r0=methodToCall, r1=newFp, r10=newSaveArea 9992 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9993 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 9994 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 9995 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 9996 mov r9, r3 @ r9<- glue->self (preserve) 9997 9998 mov r2, r0 @ r2<- methodToCall 9999 mov r0, r1 @ r0<- newFp (points to args) 10000 add r1, rGLUE, #offGlue_retval @ r1<- &retval 10001 10002#ifdef ASSIST_DEBUGGER 10003 /* insert fake function header to help gdb find the stack frame */ 10004 b .Lskip 10005 .type dalvik_mterp, %function 10006dalvik_mterp: 10007 .fnstart 10008 MTERP_ENTRY1 10009 MTERP_ENTRY2 10010.Lskip: 10011#endif 10012 10013#if defined(WITH_INLINE_PROFILING) 10014 @ r2=JNIMethod, r6=rGLUE 10015 stmfd sp!, {r2,r6} 10016#endif 10017 10018 mov lr, pc @ set return addr 10019 ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 10020 10021#if defined(WITH_INLINE_PROFILING) 10022 @ r0=JNIMethod, r1=rGLUE 10023 ldmfd sp!, {r0-r1} 10024 bl dvmFastNativeMethodTraceExit 10025#endif 10026 10027#if defined(WITH_JIT) 10028 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status 10029#endif 10030 10031 @ native return; r9=self, r10=newSaveArea 10032 @ equivalent to dvmPopJniLocals 10033 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 10034 ldr r1, [r9, #offThread_exception] @ check for exception 10035#if defined(WITH_JIT) 10036 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable 10037#endif 10038 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 10039 cmp r1, #0 @ null? 10040 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 10041#if defined(WITH_JIT) 10042 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch 10043#endif 10044 bne common_exceptionThrown @ no, handle exception 10045 10046 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 10047 GET_INST_OPCODE(ip) @ extract opcode from rINST 10048 GOTO_OPCODE(ip) @ jump to next instruction 10049 10050.LstackOverflow: @ r0=methodToCall 10051 mov r1, r0 @ r1<- methodToCall 10052 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 10053 bl dvmHandleStackOverflow 10054 b common_exceptionThrown 10055#ifdef ASSIST_DEBUGGER 10056 .fnend 10057#endif 10058 10059 10060 /* 10061 * Common code for method invocation, calling through "glue code". 10062 * 10063 * TODO: now that we have range and non-range invoke handlers, this 10064 * needs to be split into two. Maybe just create entry points 10065 * that set r9 and jump here? 10066 * 10067 * On entry: 10068 * r0 is "Method* methodToCall", the method we're trying to call 10069 * r9 is "bool methodCallRange", indicating if this is a /range variant 10070 */ 10071 .if 0 10072.LinvokeOld: 10073 sub sp, sp, #8 @ space for args + pad 10074 FETCH(ip, 2) @ ip<- FEDC or CCCC 10075 mov r2, r0 @ A2<- methodToCall 10076 mov r0, rGLUE @ A0<- glue 10077 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 10078 mov r1, r9 @ A1<- methodCallRange 10079 mov r3, rINST, lsr #8 @ A3<- AA 10080 str ip, [sp, #0] @ A4<- ip 10081 bl dvmMterp_invokeMethod @ call the C invokeMethod 10082 add sp, sp, #8 @ remove arg area 10083 b common_resumeAfterGlueCall @ continue to next instruction 10084 .endif 10085 10086 10087 10088/* 10089 * Common code for handling a return instruction. 10090 * 10091 * This does not return. 10092 */ 10093common_returnFromMethod: 10094.LreturnNew: 10095 mov r0, #kInterpEntryReturn 10096 mov r9, #0 10097 bl common_periodicChecks 10098 10099#if defined(WITH_INLINE_PROFILING) 10100 stmfd sp!, {r0-r3} @ preserve r0-r3 10101 mov r0, r6 10102 @ r0=rGlue 10103 bl dvmFastJavaMethodTraceExit 10104 ldmfd sp!, {r0-r3} @ restore r0-r3 10105#endif 10106 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 10107 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 10108 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 10109 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 10110 @ r2<- method we're returning to 10111 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10112 cmp r2, #0 @ is this a break frame? 10113 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 10114 mov r1, #0 @ "want switch" = false 10115 beq common_gotoBail @ break frame, bail out completely 10116 10117 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 10118 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 10119 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 10120 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 10121#if defined(WITH_JIT) 10122 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr 10123 mov rPC, r9 @ publish new rPC 10124 str r1, [rGLUE, #offGlue_methodClassDex] 10125 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land 10126 cmp r10, #0 @ caller is compiled code 10127 blxne r10 10128 GET_INST_OPCODE(ip) @ extract opcode from rINST 10129 GOTO_OPCODE(ip) @ jump to next instruction 10130#else 10131 GET_INST_OPCODE(ip) @ extract opcode from rINST 10132 mov rPC, r9 @ publish new rPC 10133 str r1, [rGLUE, #offGlue_methodClassDex] 10134 GOTO_OPCODE(ip) @ jump to next instruction 10135#endif 10136 10137 /* 10138 * Return handling, calls through "glue code". 10139 */ 10140 .if 0 10141.LreturnOld: 10142 SAVE_PC_FP_TO_GLUE() @ export state 10143 mov r0, rGLUE @ arg to function 10144 bl dvmMterp_returnFromMethod 10145 b common_resumeAfterGlueCall 10146 .endif 10147 10148 10149/* 10150 * Somebody has thrown an exception. Handle it. 10151 * 10152 * If the exception processing code returns to us (instead of falling 10153 * out of the interpreter), continue with whatever the next instruction 10154 * now happens to be. 10155 * 10156 * This does not return. 10157 */ 10158 .global dvmMterpCommonExceptionThrown 10159dvmMterpCommonExceptionThrown: 10160common_exceptionThrown: 10161.LexceptionNew: 10162 mov r0, #kInterpEntryThrow 10163 mov r9, #0 10164 bl common_periodicChecks 10165 10166 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 10167 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 10168 mov r1, r10 @ r1<- self 10169 mov r0, r9 @ r0<- exception 10170 bl dvmAddTrackedAlloc @ don't let the exception be GCed 10171 mov r3, #0 @ r3<- NULL 10172 str r3, [r10, #offThread_exception] @ self->exception = NULL 10173 10174 /* set up args and a local for "&fp" */ 10175 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 10176 str rFP, [sp, #-4]! @ *--sp = fp 10177 mov ip, sp @ ip<- &fp 10178 mov r3, #0 @ r3<- false 10179 str ip, [sp, #-4]! @ *--sp = &fp 10180 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 10181 mov r0, r10 @ r0<- self 10182 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 10183 mov r2, r9 @ r2<- exception 10184 sub r1, rPC, r1 @ r1<- pc - method->insns 10185 mov r1, r1, asr #1 @ r1<- offset in code units 10186 10187 /* call, r0 gets catchRelPc (a code-unit offset) */ 10188 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 10189 10190 /* fix earlier stack overflow if necessary; may trash rFP */ 10191 ldrb r1, [r10, #offThread_stackOverflowed] 10192 cmp r1, #0 @ did we overflow earlier? 10193 beq 1f @ no, skip ahead 10194 mov rFP, r0 @ save relPc result in rFP 10195 mov r0, r10 @ r0<- self 10196 mov r1, r9 @ r1<- exception 10197 bl dvmCleanupStackOverflow @ call(self) 10198 mov r0, rFP @ restore result 101991: 10200 10201 /* update frame pointer and check result from dvmFindCatchBlock */ 10202 ldr rFP, [sp, #4] @ retrieve the updated rFP 10203 cmp r0, #0 @ is catchRelPc < 0? 10204 add sp, sp, #8 @ restore stack 10205 bmi .LnotCaughtLocally 10206 10207 /* adjust locals to match self->curFrame and updated PC */ 10208 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 10209 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 10210 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 10211 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 10212 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 10213 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 10214 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 10215 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 10216 10217 /* release the tracked alloc on the exception */ 10218 mov r0, r9 @ r0<- exception 10219 mov r1, r10 @ r1<- self 10220 bl dvmReleaseTrackedAlloc @ release the exception 10221 10222 /* restore the exception if the handler wants it */ 10223 FETCH_INST() @ load rINST from rPC 10224 GET_INST_OPCODE(ip) @ extract opcode from rINST 10225 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 10226 streq r9, [r10, #offThread_exception] @ yes, restore the exception 10227 GOTO_OPCODE(ip) @ jump to next instruction 10228 10229.LnotCaughtLocally: @ r9=exception, r10=self 10230 /* fix stack overflow if necessary */ 10231 ldrb r1, [r10, #offThread_stackOverflowed] 10232 cmp r1, #0 @ did we overflow earlier? 10233 movne r0, r10 @ if yes: r0<- self 10234 movne r1, r9 @ if yes: r1<- exception 10235 blne dvmCleanupStackOverflow @ if yes: call(self) 10236 10237 @ may want to show "not caught locally" debug messages here 10238#if DVM_SHOW_EXCEPTION >= 2 10239 /* call __android_log_print(prio, tag, format, ...) */ 10240 /* "Exception %s from %s:%d not caught locally" */ 10241 @ dvmLineNumFromPC(method, pc - method->insns) 10242 ldr r0, [rGLUE, #offGlue_method] 10243 ldr r1, [r0, #offMethod_insns] 10244 sub r1, rPC, r1 10245 asr r1, r1, #1 10246 bl dvmLineNumFromPC 10247 str r0, [sp, #-4]! 10248 @ dvmGetMethodSourceFile(method) 10249 ldr r0, [rGLUE, #offGlue_method] 10250 bl dvmGetMethodSourceFile 10251 str r0, [sp, #-4]! 10252 @ exception->clazz->descriptor 10253 ldr r3, [r9, #offObject_clazz] 10254 ldr r3, [r3, #offClassObject_descriptor] 10255 @ 10256 ldr r2, strExceptionNotCaughtLocally 10257 ldr r1, strLogTag 10258 mov r0, #3 @ LOG_DEBUG 10259 bl __android_log_print 10260#endif 10261 str r9, [r10, #offThread_exception] @ restore exception 10262 mov r0, r9 @ r0<- exception 10263 mov r1, r10 @ r1<- self 10264 bl dvmReleaseTrackedAlloc @ release the exception 10265 mov r1, #0 @ "want switch" = false 10266 b common_gotoBail @ bail out 10267 10268 10269 /* 10270 * Exception handling, calls through "glue code". 10271 */ 10272 .if 0 10273.LexceptionOld: 10274 SAVE_PC_FP_TO_GLUE() @ export state 10275 mov r0, rGLUE @ arg to function 10276 bl dvmMterp_exceptionThrown 10277 b common_resumeAfterGlueCall 10278 .endif 10279 10280 10281/* 10282 * After returning from a "glued" function, pull out the updated 10283 * values and start executing at the next instruction. 10284 */ 10285common_resumeAfterGlueCall: 10286 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 10287 FETCH_INST() @ load rINST from rPC 10288 GET_INST_OPCODE(ip) @ extract opcode from rINST 10289 GOTO_OPCODE(ip) @ jump to next instruction 10290 10291/* 10292 * Invalid array index. Note that our calling convention is strange; we use r1 10293 * and r3 because those just happen to be the registers all our callers are 10294 * using. We shuffle them here before calling the C function. 10295 * r1: index 10296 * r3: size 10297 */ 10298common_errArrayIndex: 10299 EXPORT_PC() 10300 mov r0, r1 10301 mov r1, r3 10302 bl dvmThrowAIOOBE 10303 b common_exceptionThrown 10304 10305/* 10306 * Invalid array value. 10307 */ 10308common_errArrayStore: 10309 EXPORT_PC() 10310 ldr r0, strArrayStoreException 10311 mov r1, #0 10312 bl dvmThrowException 10313 b common_exceptionThrown 10314 10315/* 10316 * Integer divide or mod by zero. 10317 */ 10318common_errDivideByZero: 10319 EXPORT_PC() 10320 ldr r0, strArithmeticException 10321 ldr r1, strDivideByZero 10322 bl dvmThrowException 10323 b common_exceptionThrown 10324 10325/* 10326 * Attempt to allocate an array with a negative size. 10327 */ 10328common_errNegativeArraySize: 10329 EXPORT_PC() 10330 ldr r0, strNegativeArraySizeException 10331 mov r1, #0 10332 bl dvmThrowException 10333 b common_exceptionThrown 10334 10335/* 10336 * Invocation of a non-existent method. 10337 */ 10338common_errNoSuchMethod: 10339 EXPORT_PC() 10340 ldr r0, strNoSuchMethodError 10341 mov r1, #0 10342 bl dvmThrowException 10343 b common_exceptionThrown 10344 10345/* 10346 * We encountered a null object when we weren't expecting one. We 10347 * export the PC, throw a NullPointerException, and goto the exception 10348 * processing code. 10349 */ 10350common_errNullObject: 10351 EXPORT_PC() 10352 ldr r0, strNullPointerException 10353 mov r1, #0 10354 bl dvmThrowException 10355 b common_exceptionThrown 10356 10357/* 10358 * For debugging, cause an immediate fault. The source address will 10359 * be in lr (use a bl instruction to jump here). 10360 */ 10361common_abort: 10362 ldr pc, .LdeadFood 10363.LdeadFood: 10364 .word 0xdeadf00d 10365 10366/* 10367 * Spit out a "we were here", preserving all registers. (The attempt 10368 * to save ip won't work, but we need to save an even number of 10369 * registers for EABI 64-bit stack alignment.) 10370 */ 10371 .macro SQUEAK num 10372common_squeak\num: 10373 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10374 ldr r0, strSqueak 10375 mov r1, #\num 10376 bl printf 10377 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10378 bx lr 10379 .endm 10380 10381 SQUEAK 0 10382 SQUEAK 1 10383 SQUEAK 2 10384 SQUEAK 3 10385 SQUEAK 4 10386 SQUEAK 5 10387 10388/* 10389 * Spit out the number in r0, preserving registers. 10390 */ 10391common_printNum: 10392 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10393 mov r1, r0 10394 ldr r0, strSqueak 10395 bl printf 10396 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10397 bx lr 10398 10399/* 10400 * Print a newline, preserving registers. 10401 */ 10402common_printNewline: 10403 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10404 ldr r0, strNewline 10405 bl printf 10406 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10407 bx lr 10408 10409 /* 10410 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 10411 */ 10412common_printHex: 10413 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10414 mov r1, r0 10415 ldr r0, strPrintHex 10416 bl printf 10417 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10418 bx lr 10419 10420/* 10421 * Print the 64-bit quantity in r0-r1, preserving registers. 10422 */ 10423common_printLong: 10424 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10425 mov r3, r1 10426 mov r2, r0 10427 ldr r0, strPrintLong 10428 bl printf 10429 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10430 bx lr 10431 10432/* 10433 * Print full method info. Pass the Method* in r0. Preserves regs. 10434 */ 10435common_printMethod: 10436 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10437 bl dvmMterpPrintMethod 10438 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10439 bx lr 10440 10441/* 10442 * Call a C helper function that dumps regs and possibly some 10443 * additional info. Requires the C function to be compiled in. 10444 */ 10445 .if 0 10446common_dumpRegs: 10447 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10448 bl dvmMterpDumpArmRegs 10449 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10450 bx lr 10451 .endif 10452 10453#if 0 10454/* 10455 * Experiment on VFP mode. 10456 * 10457 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 10458 * 10459 * Updates the bits specified by "mask", setting them to the values in "val". 10460 */ 10461setFPSCR: 10462 and r0, r0, r1 @ make sure no stray bits are set 10463 fmrx r2, fpscr @ get VFP reg 10464 mvn r1, r1 @ bit-invert mask 10465 and r2, r2, r1 @ clear masked bits 10466 orr r2, r2, r0 @ set specified bits 10467 fmxr fpscr, r2 @ set VFP reg 10468 mov r0, r2 @ return new value 10469 bx lr 10470 10471 .align 2 10472 .global dvmConfigureFP 10473 .type dvmConfigureFP, %function 10474dvmConfigureFP: 10475 stmfd sp!, {ip, lr} 10476 /* 0x03000000 sets DN/FZ */ 10477 /* 0x00009f00 clears the six exception enable flags */ 10478 bl common_squeak0 10479 mov r0, #0x03000000 @ r0<- 0x03000000 10480 add r1, r0, #0x9f00 @ r1<- 0x03009f00 10481 bl setFPSCR 10482 ldmfd sp!, {ip, pc} 10483#endif 10484 10485 10486/* 10487 * String references, must be close to the code that uses them. 10488 */ 10489 .align 2 10490strArithmeticException: 10491 .word .LstrArithmeticException 10492strArrayStoreException: 10493 .word .LstrArrayStoreException 10494strDivideByZero: 10495 .word .LstrDivideByZero 10496strNegativeArraySizeException: 10497 .word .LstrNegativeArraySizeException 10498strNoSuchMethodError: 10499 .word .LstrNoSuchMethodError 10500strNullPointerException: 10501 .word .LstrNullPointerException 10502 10503strLogTag: 10504 .word .LstrLogTag 10505strExceptionNotCaughtLocally: 10506 .word .LstrExceptionNotCaughtLocally 10507 10508strNewline: 10509 .word .LstrNewline 10510strSqueak: 10511 .word .LstrSqueak 10512strPrintHex: 10513 .word .LstrPrintHex 10514strPrintLong: 10515 .word .LstrPrintLong 10516 10517/* 10518 * Zero-terminated ASCII string data. 10519 * 10520 * On ARM we have two choices: do like gcc does, and LDR from a .word 10521 * with the address, or use an ADR pseudo-op to get the address 10522 * directly. ADR saves 4 bytes and an indirection, but it's using a 10523 * PC-relative addressing mode and hence has a limited range, which 10524 * makes it not work well with mergeable string sections. 10525 */ 10526 .section .rodata.str1.4,"aMS",%progbits,1 10527 10528.LstrBadEntryPoint: 10529 .asciz "Bad entry point %d\n" 10530.LstrArithmeticException: 10531 .asciz "Ljava/lang/ArithmeticException;" 10532.LstrArrayStoreException: 10533 .asciz "Ljava/lang/ArrayStoreException;" 10534.LstrClassCastException: 10535 .asciz "Ljava/lang/ClassCastException;" 10536.LstrDivideByZero: 10537 .asciz "divide by zero" 10538.LstrFilledNewArrayNotImpl: 10539 .asciz "filled-new-array only implemented for objects and 'int'" 10540.LstrInternalError: 10541 .asciz "Ljava/lang/InternalError;" 10542.LstrInstantiationError: 10543 .asciz "Ljava/lang/InstantiationError;" 10544.LstrNegativeArraySizeException: 10545 .asciz "Ljava/lang/NegativeArraySizeException;" 10546.LstrNoSuchMethodError: 10547 .asciz "Ljava/lang/NoSuchMethodError;" 10548.LstrNullPointerException: 10549 .asciz "Ljava/lang/NullPointerException;" 10550 10551.LstrLogTag: 10552 .asciz "mterp" 10553.LstrExceptionNotCaughtLocally: 10554 .asciz "Exception %s from %s:%d not caught locally\n" 10555 10556.LstrNewline: 10557 .asciz "\n" 10558.LstrSqueak: 10559 .asciz "<%d>" 10560.LstrPrintHex: 10561 .asciz "<0x%x>" 10562.LstrPrintLong: 10563 .asciz "<%lld>" 10564 10565