InterpAsm-armv5te-vfp.S revision b387fe1b970a216c09d2abc98c893ff1fff3e512
1/* 2 * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'. 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: armv5te/platform.S */ 210/* 211 * =========================================================================== 212 * CPU-version-specific defines 213 * =========================================================================== 214 */ 215 216/* 217 * Macro for data memory barrier; not meaningful pre-ARMv6K. 218 */ 219.macro SMP_DMB 220.endm 221 222/* 223 * Macro for data memory barrier; not meaningful pre-ARMv6K. 224 */ 225.macro SMP_DMB_ST 226.endm 227 228/* File: armv5te/entry.S */ 229/* 230 * Copyright (C) 2008 The Android Open Source Project 231 * 232 * Licensed under the Apache License, Version 2.0 (the "License"); 233 * you may not use this file except in compliance with the License. 234 * You may obtain a copy of the License at 235 * 236 * http://www.apache.org/licenses/LICENSE-2.0 237 * 238 * Unless required by applicable law or agreed to in writing, software 239 * distributed under the License is distributed on an "AS IS" BASIS, 240 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 241 * See the License for the specific language governing permissions and 242 * limitations under the License. 243 */ 244/* 245 * Interpreter entry point. 246 */ 247 248/* 249 * We don't have formal stack frames, so gdb scans upward in the code 250 * to find the start of the function (a label with the %function type), 251 * and then looks at the next few instructions to figure out what 252 * got pushed onto the stack. From this it figures out how to restore 253 * the registers, including PC, for the previous stack frame. If gdb 254 * sees a non-function label, it stops scanning, so either we need to 255 * have nothing but assembler-local labels between the entry point and 256 * the break, or we need to fake it out. 257 * 258 * When this is defined, we add some stuff to make gdb less confused. 259 */ 260#define ASSIST_DEBUGGER 1 261 262 .text 263 .align 2 264 .global dvmMterpStdRun 265 .type dvmMterpStdRun, %function 266 267/* 268 * On entry: 269 * r0 MterpGlue* glue 270 * 271 * This function returns a boolean "changeInterp" value. The return comes 272 * via a call to dvmMterpStdBail(). 273 */ 274dvmMterpStdRun: 275#define MTERP_ENTRY1 \ 276 .save {r4-r10,fp,lr}; \ 277 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs 278#define MTERP_ENTRY2 \ 279 .pad #4; \ 280 sub sp, sp, #4 @ align 64 281 282 .fnstart 283 MTERP_ENTRY1 284 MTERP_ENTRY2 285 286 /* save stack pointer, add magic word for debuggerd */ 287 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return 288 289 /* set up "named" registers, figure out entry point */ 290 mov rGLUE, r0 @ set rGLUE 291 ldr r1, [r0, #offGlue_entryPoint] @ enum is 4 bytes in aapcs-EABI 292 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue" 293 adr rIBASE, dvmAsmInstructionStart @ set rIBASE 294 cmp r1, #kInterpEntryInstr @ usual case? 295 bne .Lnot_instr @ no, handle it 296 297#if defined(WITH_JIT) 298.LentryInstr: 299 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 300 /* Entry is always a possible trace start */ 301 GET_JIT_PROF_TABLE(r0) 302 FETCH_INST() 303 mov r1, #0 @ prepare the value for the new state 304 str r1, [r10, #offThread_inJitCodeCache] @ back to the interp land 305 cmp r0,#0 @ is profiling disabled? 306#if !defined(WITH_SELF_VERIFICATION) 307 bne common_updateProfile @ profiling is enabled 308#else 309 ldr r2, [r10, #offThread_shadowSpace] @ to find out the jit exit state 310 beq 1f @ profiling is disabled 311 ldr r3, [r2, #offShadowSpace_jitExitState] @ jit exit state 312 cmp r3, #kSVSTraceSelect @ hot trace following? 313 moveq r2,#kJitTSelectRequestHot @ ask for trace selection 314 beq common_selectTrace @ go build the trace 315 cmp r3, #kSVSNoProfile @ don't profile the next instruction? 316 beq 1f @ intrepret the next instruction 317 b common_updateProfile @ collect profiles 318#endif 3191: 320 GET_INST_OPCODE(ip) 321 GOTO_OPCODE(ip) 322#else 323 /* start executing the instruction at rPC */ 324 FETCH_INST() @ load rINST from rPC 325 GET_INST_OPCODE(ip) @ extract opcode from rINST 326 GOTO_OPCODE(ip) @ jump to next instruction 327#endif 328 329.Lnot_instr: 330 cmp r1, #kInterpEntryReturn @ were we returning from a method? 331 beq common_returnFromMethod 332 333.Lnot_return: 334 cmp r1, #kInterpEntryThrow @ were we throwing an exception? 335 beq common_exceptionThrown 336 337#if defined(WITH_JIT) 338.Lnot_throw: 339 ldr r10,[rGLUE, #offGlue_jitResumeNPC] 340 ldr r2,[rGLUE, #offGlue_jitResumeDPC] 341 cmp r1, #kInterpEntryResume @ resuming after Jit single-step? 342 bne .Lbad_arg 343 cmp rPC,r2 344 bne .LentryInstr @ must have branched, don't resume 345#if defined(WITH_SELF_VERIFICATION) 346 @ glue->entryPoint will be set in dvmSelfVerificationSaveState 347 b jitSVShadowRunStart @ re-enter the translation after the 348 @ single-stepped instruction 349 @noreturn 350#endif 351 mov r1, #kInterpEntryInstr 352 str r1, [rGLUE, #offGlue_entryPoint] 353 bx r10 @ re-enter the translation 354#endif 355 356.Lbad_arg: 357 ldr r0, strBadEntryPoint 358 @ r1 holds value of entryPoint 359 bl printf 360 bl dvmAbort 361 .fnend 362 .size dvmMterpStdRun, .-dvmMterpStdRun 363 364 365 .global dvmMterpStdBail 366 .type dvmMterpStdBail, %function 367 368/* 369 * Restore the stack pointer and PC from the save point established on entry. 370 * This is essentially the same as a longjmp, but should be cheaper. The 371 * last instruction causes us to return to whoever called dvmMterpStdRun. 372 * 373 * We pushed some registers on the stack in dvmMterpStdRun, then saved 374 * SP and LR. Here we restore SP, restore the registers, and then restore 375 * LR to PC. 376 * 377 * On entry: 378 * r0 MterpGlue* glue 379 * r1 bool changeInterp 380 */ 381dvmMterpStdBail: 382 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 383 mov r0, r1 @ return the changeInterp value 384 add sp, sp, #4 @ un-align 64 385 ldmfd sp!, {r4-r10,fp,pc} @ restore 9 regs and return 386 387 388/* 389 * String references. 390 */ 391strBadEntryPoint: 392 .word .LstrBadEntryPoint 393 394 395 .global dvmAsmInstructionStart 396 .type dvmAsmInstructionStart, %function 397dvmAsmInstructionStart = .L_OP_NOP 398 .text 399 400/* ------------------------------ */ 401 .balign 64 402.L_OP_NOP: /* 0x00 */ 403/* File: armv5te/OP_NOP.S */ 404 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST 405 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 406 GOTO_OPCODE(ip) @ execute it 407 408#ifdef ASSIST_DEBUGGER 409 /* insert fake function header to help gdb find the stack frame */ 410 .type dalvik_inst, %function 411dalvik_inst: 412 .fnstart 413 MTERP_ENTRY1 414 MTERP_ENTRY2 415 .fnend 416#endif 417 418/* ------------------------------ */ 419 .balign 64 420.L_OP_MOVE: /* 0x01 */ 421/* File: armv5te/OP_MOVE.S */ 422 /* for move, move-object, long-to-int */ 423 /* op vA, vB */ 424 mov r1, rINST, lsr #12 @ r1<- B from 15:12 425 mov r0, rINST, lsr #8 @ r0<- A from 11:8 426 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 427 GET_VREG(r2, r1) @ r2<- fp[B] 428 and r0, r0, #15 429 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 430 SET_VREG(r2, r0) @ fp[A]<- r2 431 GOTO_OPCODE(ip) @ execute next instruction 432 433/* ------------------------------ */ 434 .balign 64 435.L_OP_MOVE_FROM16: /* 0x02 */ 436/* File: armv5te/OP_MOVE_FROM16.S */ 437 /* for: move/from16, move-object/from16 */ 438 /* op vAA, vBBBB */ 439 FETCH(r1, 1) @ r1<- BBBB 440 mov r0, rINST, lsr #8 @ r0<- AA 441 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 442 GET_VREG(r2, r1) @ r2<- fp[BBBB] 443 GET_INST_OPCODE(ip) @ extract opcode from rINST 444 SET_VREG(r2, r0) @ fp[AA]<- r2 445 GOTO_OPCODE(ip) @ jump to next instruction 446 447/* ------------------------------ */ 448 .balign 64 449.L_OP_MOVE_16: /* 0x03 */ 450/* File: armv5te/OP_MOVE_16.S */ 451 /* for: move/16, move-object/16 */ 452 /* op vAAAA, vBBBB */ 453 FETCH(r1, 2) @ r1<- BBBB 454 FETCH(r0, 1) @ r0<- AAAA 455 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 456 GET_VREG(r2, r1) @ r2<- fp[BBBB] 457 GET_INST_OPCODE(ip) @ extract opcode from rINST 458 SET_VREG(r2, r0) @ fp[AAAA]<- r2 459 GOTO_OPCODE(ip) @ jump to next instruction 460 461/* ------------------------------ */ 462 .balign 64 463.L_OP_MOVE_WIDE: /* 0x04 */ 464/* File: armv5te/OP_MOVE_WIDE.S */ 465 /* move-wide vA, vB */ 466 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 467 mov r2, rINST, lsr #8 @ r2<- A(+) 468 mov r3, rINST, lsr #12 @ r3<- B 469 and r2, r2, #15 470 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 471 add r2, rFP, r2, lsl #2 @ r2<- &fp[A] 472 ldmia r3, {r0-r1} @ r0/r1<- fp[B] 473 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 474 GET_INST_OPCODE(ip) @ extract opcode from rINST 475 stmia r2, {r0-r1} @ fp[A]<- r0/r1 476 GOTO_OPCODE(ip) @ jump to next instruction 477 478/* ------------------------------ */ 479 .balign 64 480.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 481/* File: armv5te/OP_MOVE_WIDE_FROM16.S */ 482 /* move-wide/from16 vAA, vBBBB */ 483 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 484 FETCH(r3, 1) @ r3<- BBBB 485 mov r2, rINST, lsr #8 @ r2<- AA 486 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 487 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 488 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 489 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 490 GET_INST_OPCODE(ip) @ extract opcode from rINST 491 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 492 GOTO_OPCODE(ip) @ jump to next instruction 493 494/* ------------------------------ */ 495 .balign 64 496.L_OP_MOVE_WIDE_16: /* 0x06 */ 497/* File: armv5te/OP_MOVE_WIDE_16.S */ 498 /* move-wide/16 vAAAA, vBBBB */ 499 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 500 FETCH(r3, 2) @ r3<- BBBB 501 FETCH(r2, 1) @ r2<- AAAA 502 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 503 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA] 504 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 505 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 506 GET_INST_OPCODE(ip) @ extract opcode from rINST 507 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1 508 GOTO_OPCODE(ip) @ jump to next instruction 509 510/* ------------------------------ */ 511 .balign 64 512.L_OP_MOVE_OBJECT: /* 0x07 */ 513/* File: armv5te/OP_MOVE_OBJECT.S */ 514/* File: armv5te/OP_MOVE.S */ 515 /* for move, move-object, long-to-int */ 516 /* op vA, vB */ 517 mov r1, rINST, lsr #12 @ r1<- B from 15:12 518 mov r0, rINST, lsr #8 @ r0<- A from 11:8 519 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 520 GET_VREG(r2, r1) @ r2<- fp[B] 521 and r0, r0, #15 522 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 523 SET_VREG(r2, r0) @ fp[A]<- r2 524 GOTO_OPCODE(ip) @ execute next instruction 525 526 527/* ------------------------------ */ 528 .balign 64 529.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 530/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */ 531/* File: armv5te/OP_MOVE_FROM16.S */ 532 /* for: move/from16, move-object/from16 */ 533 /* op vAA, vBBBB */ 534 FETCH(r1, 1) @ r1<- BBBB 535 mov r0, rINST, lsr #8 @ r0<- AA 536 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 537 GET_VREG(r2, r1) @ r2<- fp[BBBB] 538 GET_INST_OPCODE(ip) @ extract opcode from rINST 539 SET_VREG(r2, r0) @ fp[AA]<- r2 540 GOTO_OPCODE(ip) @ jump to next instruction 541 542 543/* ------------------------------ */ 544 .balign 64 545.L_OP_MOVE_OBJECT_16: /* 0x09 */ 546/* File: armv5te/OP_MOVE_OBJECT_16.S */ 547/* File: armv5te/OP_MOVE_16.S */ 548 /* for: move/16, move-object/16 */ 549 /* op vAAAA, vBBBB */ 550 FETCH(r1, 2) @ r1<- BBBB 551 FETCH(r0, 1) @ r0<- AAAA 552 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 553 GET_VREG(r2, r1) @ r2<- fp[BBBB] 554 GET_INST_OPCODE(ip) @ extract opcode from rINST 555 SET_VREG(r2, r0) @ fp[AAAA]<- r2 556 GOTO_OPCODE(ip) @ jump to next instruction 557 558 559/* ------------------------------ */ 560 .balign 64 561.L_OP_MOVE_RESULT: /* 0x0a */ 562/* File: armv5te/OP_MOVE_RESULT.S */ 563 /* for: move-result, move-result-object */ 564 /* op vAA */ 565 mov r2, rINST, lsr #8 @ r2<- AA 566 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 567 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 568 GET_INST_OPCODE(ip) @ extract opcode from rINST 569 SET_VREG(r0, r2) @ fp[AA]<- r0 570 GOTO_OPCODE(ip) @ jump to next instruction 571 572/* ------------------------------ */ 573 .balign 64 574.L_OP_MOVE_RESULT_WIDE: /* 0x0b */ 575/* File: armv5te/OP_MOVE_RESULT_WIDE.S */ 576 /* move-result-wide vAA */ 577 mov r2, rINST, lsr #8 @ r2<- AA 578 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 579 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 580 ldmia r3, {r0-r1} @ r0/r1<- retval.j 581 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 582 GET_INST_OPCODE(ip) @ extract opcode from rINST 583 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 584 GOTO_OPCODE(ip) @ jump to next instruction 585 586/* ------------------------------ */ 587 .balign 64 588.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 589/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */ 590/* File: armv5te/OP_MOVE_RESULT.S */ 591 /* for: move-result, move-result-object */ 592 /* op vAA */ 593 mov r2, rINST, lsr #8 @ r2<- AA 594 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 595 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 596 GET_INST_OPCODE(ip) @ extract opcode from rINST 597 SET_VREG(r0, r2) @ fp[AA]<- r0 598 GOTO_OPCODE(ip) @ jump to next instruction 599 600 601/* ------------------------------ */ 602 .balign 64 603.L_OP_MOVE_EXCEPTION: /* 0x0d */ 604/* File: armv5te/OP_MOVE_EXCEPTION.S */ 605 /* move-exception vAA */ 606 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 607 mov r2, rINST, lsr #8 @ r2<- AA 608 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass 609 mov r1, #0 @ r1<- 0 610 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 611 SET_VREG(r3, r2) @ fp[AA]<- exception obj 612 GET_INST_OPCODE(ip) @ extract opcode from rINST 613 str r1, [r0, #offThread_exception] @ dvmClearException bypass 614 GOTO_OPCODE(ip) @ jump to next instruction 615 616/* ------------------------------ */ 617 .balign 64 618.L_OP_RETURN_VOID: /* 0x0e */ 619/* File: armv5te/OP_RETURN_VOID.S */ 620 b common_returnFromMethod 621 622/* ------------------------------ */ 623 .balign 64 624.L_OP_RETURN: /* 0x0f */ 625/* File: armv5te/OP_RETURN.S */ 626 /* 627 * Return a 32-bit value. Copies the return value into the "glue" 628 * structure, then jumps to the return handler. 629 * 630 * for: return, return-object 631 */ 632 /* op vAA */ 633 mov r2, rINST, lsr #8 @ r2<- AA 634 GET_VREG(r0, r2) @ r0<- vAA 635 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 636 b common_returnFromMethod 637 638/* ------------------------------ */ 639 .balign 64 640.L_OP_RETURN_WIDE: /* 0x10 */ 641/* File: armv5te/OP_RETURN_WIDE.S */ 642 /* 643 * Return a 64-bit value. Copies the return value into the "glue" 644 * structure, then jumps to the return handler. 645 */ 646 /* return-wide vAA */ 647 mov r2, rINST, lsr #8 @ r2<- AA 648 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 649 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 650 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1 651 stmia r3, {r0-r1} @ retval<- r0/r1 652 b common_returnFromMethod 653 654/* ------------------------------ */ 655 .balign 64 656.L_OP_RETURN_OBJECT: /* 0x11 */ 657/* File: armv5te/OP_RETURN_OBJECT.S */ 658/* File: armv5te/OP_RETURN.S */ 659 /* 660 * Return a 32-bit value. Copies the return value into the "glue" 661 * structure, then jumps to the return handler. 662 * 663 * for: return, return-object 664 */ 665 /* op vAA */ 666 mov r2, rINST, lsr #8 @ r2<- AA 667 GET_VREG(r0, r2) @ r0<- vAA 668 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 669 b common_returnFromMethod 670 671 672/* ------------------------------ */ 673 .balign 64 674.L_OP_CONST_4: /* 0x12 */ 675/* File: armv5te/OP_CONST_4.S */ 676 /* const/4 vA, #+B */ 677 mov r1, rINST, lsl #16 @ r1<- Bxxx0000 678 mov r0, rINST, lsr #8 @ r0<- A+ 679 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 680 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended) 681 and r0, r0, #15 682 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 683 SET_VREG(r1, r0) @ fp[A]<- r1 684 GOTO_OPCODE(ip) @ execute next instruction 685 686/* ------------------------------ */ 687 .balign 64 688.L_OP_CONST_16: /* 0x13 */ 689/* File: armv5te/OP_CONST_16.S */ 690 /* const/16 vAA, #+BBBB */ 691 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 692 mov r3, rINST, lsr #8 @ r3<- AA 693 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 694 SET_VREG(r0, r3) @ vAA<- r0 695 GET_INST_OPCODE(ip) @ extract opcode from rINST 696 GOTO_OPCODE(ip) @ jump to next instruction 697 698/* ------------------------------ */ 699 .balign 64 700.L_OP_CONST: /* 0x14 */ 701/* File: armv5te/OP_CONST.S */ 702 /* const vAA, #+BBBBbbbb */ 703 mov r3, rINST, lsr #8 @ r3<- AA 704 FETCH(r0, 1) @ r0<- bbbb (low) 705 FETCH(r1, 2) @ r1<- BBBB (high) 706 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 707 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 708 GET_INST_OPCODE(ip) @ extract opcode from rINST 709 SET_VREG(r0, r3) @ vAA<- r0 710 GOTO_OPCODE(ip) @ jump to next instruction 711 712/* ------------------------------ */ 713 .balign 64 714.L_OP_CONST_HIGH16: /* 0x15 */ 715/* File: armv5te/OP_CONST_HIGH16.S */ 716 /* const/high16 vAA, #+BBBB0000 */ 717 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended) 718 mov r3, rINST, lsr #8 @ r3<- AA 719 mov r0, r0, lsl #16 @ r0<- BBBB0000 720 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 721 SET_VREG(r0, r3) @ vAA<- r0 722 GET_INST_OPCODE(ip) @ extract opcode from rINST 723 GOTO_OPCODE(ip) @ jump to next instruction 724 725/* ------------------------------ */ 726 .balign 64 727.L_OP_CONST_WIDE_16: /* 0x16 */ 728/* File: armv5te/OP_CONST_WIDE_16.S */ 729 /* const-wide/16 vAA, #+BBBB */ 730 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 731 mov r3, rINST, lsr #8 @ r3<- AA 732 mov r1, r0, asr #31 @ r1<- ssssssss 733 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 734 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 735 GET_INST_OPCODE(ip) @ extract opcode from rINST 736 stmia r3, {r0-r1} @ vAA<- r0/r1 737 GOTO_OPCODE(ip) @ jump to next instruction 738 739/* ------------------------------ */ 740 .balign 64 741.L_OP_CONST_WIDE_32: /* 0x17 */ 742/* File: armv5te/OP_CONST_WIDE_32.S */ 743 /* const-wide/32 vAA, #+BBBBbbbb */ 744 FETCH(r0, 1) @ r0<- 0000bbbb (low) 745 mov r3, rINST, lsr #8 @ r3<- AA 746 FETCH_S(r2, 2) @ r2<- ssssBBBB (high) 747 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 748 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb 749 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 750 mov r1, r0, asr #31 @ r1<- ssssssss 751 GET_INST_OPCODE(ip) @ extract opcode from rINST 752 stmia r3, {r0-r1} @ vAA<- r0/r1 753 GOTO_OPCODE(ip) @ jump to next instruction 754 755/* ------------------------------ */ 756 .balign 64 757.L_OP_CONST_WIDE: /* 0x18 */ 758/* File: armv5te/OP_CONST_WIDE.S */ 759 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 760 FETCH(r0, 1) @ r0<- bbbb (low) 761 FETCH(r1, 2) @ r1<- BBBB (low middle) 762 FETCH(r2, 3) @ r2<- hhhh (high middle) 763 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word) 764 FETCH(r3, 4) @ r3<- HHHH (high) 765 mov r9, rINST, lsr #8 @ r9<- AA 766 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word) 767 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 768 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 769 GET_INST_OPCODE(ip) @ extract opcode from rINST 770 stmia r9, {r0-r1} @ vAA<- r0/r1 771 GOTO_OPCODE(ip) @ jump to next instruction 772 773/* ------------------------------ */ 774 .balign 64 775.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 776/* File: armv5te/OP_CONST_WIDE_HIGH16.S */ 777 /* const-wide/high16 vAA, #+BBBB000000000000 */ 778 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended) 779 mov r3, rINST, lsr #8 @ r3<- AA 780 mov r0, #0 @ r0<- 00000000 781 mov r1, r1, lsl #16 @ r1<- BBBB0000 782 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 783 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 784 GET_INST_OPCODE(ip) @ extract opcode from rINST 785 stmia r3, {r0-r1} @ vAA<- r0/r1 786 GOTO_OPCODE(ip) @ jump to next instruction 787 788/* ------------------------------ */ 789 .balign 64 790.L_OP_CONST_STRING: /* 0x1a */ 791/* File: armv5te/OP_CONST_STRING.S */ 792 /* const/string vAA, String@BBBB */ 793 FETCH(r1, 1) @ r1<- BBBB 794 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 795 mov r9, rINST, lsr #8 @ r9<- AA 796 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 797 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 798 cmp r0, #0 @ not yet resolved? 799 beq .LOP_CONST_STRING_resolve 800 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 801 GET_INST_OPCODE(ip) @ extract opcode from rINST 802 SET_VREG(r0, r9) @ vAA<- r0 803 GOTO_OPCODE(ip) @ jump to next instruction 804 805/* ------------------------------ */ 806 .balign 64 807.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 808/* File: armv5te/OP_CONST_STRING_JUMBO.S */ 809 /* const/string vAA, String@BBBBBBBB */ 810 FETCH(r0, 1) @ r0<- bbbb (low) 811 FETCH(r1, 2) @ r1<- BBBB (high) 812 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 813 mov r9, rINST, lsr #8 @ r9<- AA 814 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 815 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 816 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 817 cmp r0, #0 818 beq .LOP_CONST_STRING_JUMBO_resolve 819 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 820 GET_INST_OPCODE(ip) @ extract opcode from rINST 821 SET_VREG(r0, r9) @ vAA<- r0 822 GOTO_OPCODE(ip) @ jump to next instruction 823 824/* ------------------------------ */ 825 .balign 64 826.L_OP_CONST_CLASS: /* 0x1c */ 827/* File: armv5te/OP_CONST_CLASS.S */ 828 /* const/class vAA, Class@BBBB */ 829 FETCH(r1, 1) @ r1<- BBBB 830 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 831 mov r9, rINST, lsr #8 @ r9<- AA 832 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 833 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB] 834 cmp r0, #0 @ not yet resolved? 835 beq .LOP_CONST_CLASS_resolve 836 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 837 GET_INST_OPCODE(ip) @ extract opcode from rINST 838 SET_VREG(r0, r9) @ vAA<- r0 839 GOTO_OPCODE(ip) @ jump to next instruction 840 841/* ------------------------------ */ 842 .balign 64 843.L_OP_MONITOR_ENTER: /* 0x1d */ 844/* File: armv5te/OP_MONITOR_ENTER.S */ 845 /* 846 * Synchronize on an object. 847 */ 848 /* monitor-enter vAA */ 849 mov r2, rINST, lsr #8 @ r2<- AA 850 GET_VREG(r1, r2) @ r1<- vAA (object) 851 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 852 cmp r1, #0 @ null object? 853 EXPORT_PC() @ need for precise GC 854 beq common_errNullObject @ null object, throw an exception 855 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 856 bl dvmLockObject @ call(self, obj) 857 GET_INST_OPCODE(ip) @ extract opcode from rINST 858 GOTO_OPCODE(ip) @ jump to next instruction 859 860/* ------------------------------ */ 861 .balign 64 862.L_OP_MONITOR_EXIT: /* 0x1e */ 863/* File: armv5te/OP_MONITOR_EXIT.S */ 864 /* 865 * Unlock an object. 866 * 867 * Exceptions that occur when unlocking a monitor need to appear as 868 * if they happened at the following instruction. See the Dalvik 869 * instruction spec. 870 */ 871 /* monitor-exit vAA */ 872 mov r2, rINST, lsr #8 @ r2<- AA 873 EXPORT_PC() @ before fetch: export the PC 874 GET_VREG(r1, r2) @ r1<- vAA (object) 875 cmp r1, #0 @ null object? 876 beq 1f @ yes 877 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 878 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 879 cmp r0, #0 @ failed? 880 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 881 beq common_exceptionThrown @ yes, exception is pending 882 GET_INST_OPCODE(ip) @ extract opcode from rINST 883 GOTO_OPCODE(ip) @ jump to next instruction 8841: 885 FETCH_ADVANCE_INST(1) @ advance before throw 886 b common_errNullObject 887 888/* ------------------------------ */ 889 .balign 64 890.L_OP_CHECK_CAST: /* 0x1f */ 891/* File: armv5te/OP_CHECK_CAST.S */ 892 /* 893 * Check to see if a cast from one class to another is allowed. 894 */ 895 /* check-cast vAA, class@BBBB */ 896 mov r3, rINST, lsr #8 @ r3<- AA 897 FETCH(r2, 1) @ r2<- BBBB 898 GET_VREG(r9, r3) @ r9<- object 899 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 900 cmp r9, #0 @ is object null? 901 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 902 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 903 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 904 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 905 cmp r1, #0 @ have we resolved this before? 906 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 907.LOP_CHECK_CAST_resolved: 908 cmp r0, r1 @ same class (trivial success)? 909 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 910.LOP_CHECK_CAST_okay: 911 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 912 GET_INST_OPCODE(ip) @ extract opcode from rINST 913 GOTO_OPCODE(ip) @ jump to next instruction 914 915/* ------------------------------ */ 916 .balign 64 917.L_OP_INSTANCE_OF: /* 0x20 */ 918/* File: armv5te/OP_INSTANCE_OF.S */ 919 /* 920 * Check to see if an object reference is an instance of a class. 921 * 922 * Most common situation is a non-null object, being compared against 923 * an already-resolved class. 924 */ 925 /* instance-of vA, vB, class@CCCC */ 926 mov r3, rINST, lsr #12 @ r3<- B 927 mov r9, rINST, lsr #8 @ r9<- A+ 928 GET_VREG(r0, r3) @ r0<- vB (object) 929 and r9, r9, #15 @ r9<- A 930 cmp r0, #0 @ is object null? 931 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 932 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 933 FETCH(r3, 1) @ r3<- CCCC 934 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 935 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 936 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 937 cmp r1, #0 @ have we resolved this before? 938 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 939.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 940 cmp r0, r1 @ same class (trivial success)? 941 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 942 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 943 944/* ------------------------------ */ 945 .balign 64 946.L_OP_ARRAY_LENGTH: /* 0x21 */ 947/* File: armv5te/OP_ARRAY_LENGTH.S */ 948 /* 949 * Return the length of an array. 950 */ 951 mov r1, rINST, lsr #12 @ r1<- B 952 mov r2, rINST, lsr #8 @ r2<- A+ 953 GET_VREG(r0, r1) @ r0<- vB (object ref) 954 and r2, r2, #15 @ r2<- A 955 cmp r0, #0 @ is object null? 956 beq common_errNullObject @ yup, fail 957 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 958 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 959 GET_INST_OPCODE(ip) @ extract opcode from rINST 960 SET_VREG(r3, r2) @ vB<- length 961 GOTO_OPCODE(ip) @ jump to next instruction 962 963/* ------------------------------ */ 964 .balign 64 965.L_OP_NEW_INSTANCE: /* 0x22 */ 966/* File: armv5te/OP_NEW_INSTANCE.S */ 967 /* 968 * Create a new instance of a class. 969 */ 970 /* new-instance vAA, class@BBBB */ 971 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 972 FETCH(r1, 1) @ r1<- BBBB 973 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 974 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 975 EXPORT_PC() @ req'd for init, resolve, alloc 976 cmp r0, #0 @ already resolved? 977 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 978.LOP_NEW_INSTANCE_resolved: @ r0=class 979 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 980 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 981 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 982.LOP_NEW_INSTANCE_initialized: @ r0=class 983 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 984 bl dvmAllocObject @ r0<- new object 985 b .LOP_NEW_INSTANCE_finish @ continue 986 987/* ------------------------------ */ 988 .balign 64 989.L_OP_NEW_ARRAY: /* 0x23 */ 990/* File: armv5te/OP_NEW_ARRAY.S */ 991 /* 992 * Allocate an array of objects, specified with the array class 993 * and a count. 994 * 995 * The verifier guarantees that this is an array class, so we don't 996 * check for it here. 997 */ 998 /* new-array vA, vB, class@CCCC */ 999 mov r0, rINST, lsr #12 @ r0<- B 1000 FETCH(r2, 1) @ r2<- CCCC 1001 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1002 GET_VREG(r1, r0) @ r1<- vB (array length) 1003 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1004 cmp r1, #0 @ check length 1005 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 1006 bmi common_errNegativeArraySize @ negative length, bail 1007 cmp r0, #0 @ already resolved? 1008 EXPORT_PC() @ req'd for resolve, alloc 1009 bne .LOP_NEW_ARRAY_finish @ resolved, continue 1010 b .LOP_NEW_ARRAY_resolve @ do resolve now 1011 1012/* ------------------------------ */ 1013 .balign 64 1014.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1015/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1016 /* 1017 * Create a new array with elements filled from registers. 1018 * 1019 * for: filled-new-array, filled-new-array/range 1020 */ 1021 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1022 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1023 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1024 FETCH(r1, 1) @ r1<- BBBB 1025 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1026 EXPORT_PC() @ need for resolve and alloc 1027 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1028 mov r10, rINST, lsr #8 @ r10<- AA or BA 1029 cmp r0, #0 @ already resolved? 1030 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10318: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1032 mov r2, #0 @ r2<- false 1033 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1034 bl dvmResolveClass @ r0<- call(clazz, ref) 1035 cmp r0, #0 @ got null? 1036 beq common_exceptionThrown @ yes, handle exception 1037 b .LOP_FILLED_NEW_ARRAY_continue 1038 1039/* ------------------------------ */ 1040 .balign 64 1041.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1042/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1043/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1044 /* 1045 * Create a new array with elements filled from registers. 1046 * 1047 * for: filled-new-array, filled-new-array/range 1048 */ 1049 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1050 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1051 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1052 FETCH(r1, 1) @ r1<- BBBB 1053 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1054 EXPORT_PC() @ need for resolve and alloc 1055 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1056 mov r10, rINST, lsr #8 @ r10<- AA or BA 1057 cmp r0, #0 @ already resolved? 1058 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10598: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1060 mov r2, #0 @ r2<- false 1061 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1062 bl dvmResolveClass @ r0<- call(clazz, ref) 1063 cmp r0, #0 @ got null? 1064 beq common_exceptionThrown @ yes, handle exception 1065 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1066 1067 1068/* ------------------------------ */ 1069 .balign 64 1070.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1071/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1072 /* fill-array-data vAA, +BBBBBBBB */ 1073 FETCH(r0, 1) @ r0<- bbbb (lo) 1074 FETCH(r1, 2) @ r1<- BBBB (hi) 1075 mov r3, rINST, lsr #8 @ r3<- AA 1076 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1077 GET_VREG(r0, r3) @ r0<- vAA (array object) 1078 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1079 EXPORT_PC(); 1080 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1081 cmp r0, #0 @ 0 means an exception is thrown 1082 beq common_exceptionThrown @ has exception 1083 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1084 GET_INST_OPCODE(ip) @ extract opcode from rINST 1085 GOTO_OPCODE(ip) @ jump to next instruction 1086 1087/* ------------------------------ */ 1088 .balign 64 1089.L_OP_THROW: /* 0x27 */ 1090/* File: armv5te/OP_THROW.S */ 1091 /* 1092 * Throw an exception object in the current thread. 1093 */ 1094 /* throw vAA */ 1095 mov r2, rINST, lsr #8 @ r2<- AA 1096 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1097 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1098 EXPORT_PC() @ exception handler can throw 1099 cmp r1, #0 @ null object? 1100 beq common_errNullObject @ yes, throw an NPE instead 1101 @ bypass dvmSetException, just store it 1102 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1103 b common_exceptionThrown 1104 1105/* ------------------------------ */ 1106 .balign 64 1107.L_OP_GOTO: /* 0x28 */ 1108/* File: armv5te/OP_GOTO.S */ 1109 /* 1110 * Unconditional branch, 8-bit offset. 1111 * 1112 * The branch distance is a signed code-unit offset, which we need to 1113 * double to get a byte offset. 1114 */ 1115 /* goto +AA */ 1116 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1117 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1118 mov r9, r9, lsl #1 @ r9<- byte offset 1119 bmi common_backwardBranch @ backward branch, do periodic checks 1120#if defined(WITH_JIT) 1121 GET_JIT_PROF_TABLE(r0) 1122 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1123 cmp r0,#0 1124 bne common_updateProfile 1125 GET_INST_OPCODE(ip) @ extract opcode from rINST 1126 GOTO_OPCODE(ip) @ jump to next instruction 1127#else 1128 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1129 GET_INST_OPCODE(ip) @ extract opcode from rINST 1130 GOTO_OPCODE(ip) @ jump to next instruction 1131#endif 1132 1133/* ------------------------------ */ 1134 .balign 64 1135.L_OP_GOTO_16: /* 0x29 */ 1136/* File: armv5te/OP_GOTO_16.S */ 1137 /* 1138 * Unconditional branch, 16-bit offset. 1139 * 1140 * The branch distance is a signed code-unit offset, which we need to 1141 * double to get a byte offset. 1142 */ 1143 /* goto/16 +AAAA */ 1144 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1145 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1146 bmi common_backwardBranch @ backward branch, do periodic checks 1147#if defined(WITH_JIT) 1148 GET_JIT_PROF_TABLE(r0) 1149 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1150 cmp r0,#0 1151 bne common_updateProfile 1152 GET_INST_OPCODE(ip) @ extract opcode from rINST 1153 GOTO_OPCODE(ip) @ jump to next instruction 1154#else 1155 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1156 GET_INST_OPCODE(ip) @ extract opcode from rINST 1157 GOTO_OPCODE(ip) @ jump to next instruction 1158#endif 1159 1160/* ------------------------------ */ 1161 .balign 64 1162.L_OP_GOTO_32: /* 0x2a */ 1163/* File: armv5te/OP_GOTO_32.S */ 1164 /* 1165 * Unconditional branch, 32-bit offset. 1166 * 1167 * The branch distance is a signed code-unit offset, which we need to 1168 * double to get a byte offset. 1169 * 1170 * Unlike most opcodes, this one is allowed to branch to itself, so 1171 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1172 * instruction doesn't affect the V flag, so we need to clear it 1173 * explicitly. 1174 */ 1175 /* goto/32 +AAAAAAAA */ 1176 FETCH(r0, 1) @ r0<- aaaa (lo) 1177 FETCH(r1, 2) @ r1<- AAAA (hi) 1178 cmp ip, ip @ (clear V flag during stall) 1179 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1180 mov r9, r0, asl #1 @ r9<- byte offset 1181 ble common_backwardBranch @ backward branch, do periodic checks 1182#if defined(WITH_JIT) 1183 GET_JIT_PROF_TABLE(r0) 1184 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1185 cmp r0,#0 1186 bne common_updateProfile 1187 GET_INST_OPCODE(ip) @ extract opcode from rINST 1188 GOTO_OPCODE(ip) @ jump to next instruction 1189#else 1190 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1191 GET_INST_OPCODE(ip) @ extract opcode from rINST 1192 GOTO_OPCODE(ip) @ jump to next instruction 1193#endif 1194 1195/* ------------------------------ */ 1196 .balign 64 1197.L_OP_PACKED_SWITCH: /* 0x2b */ 1198/* File: armv5te/OP_PACKED_SWITCH.S */ 1199 /* 1200 * Handle a packed-switch or sparse-switch instruction. In both cases 1201 * we decode it and hand it off to a helper function. 1202 * 1203 * We don't really expect backward branches in a switch statement, but 1204 * they're perfectly legal, so we check for them here. 1205 * 1206 * for: packed-switch, sparse-switch 1207 */ 1208 /* op vAA, +BBBB */ 1209 FETCH(r0, 1) @ r0<- bbbb (lo) 1210 FETCH(r1, 2) @ r1<- BBBB (hi) 1211 mov r3, rINST, lsr #8 @ r3<- AA 1212 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1213 GET_VREG(r1, r3) @ r1<- vAA 1214 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1215 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1216 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1217 bmi common_backwardBranch @ backward branch, do periodic checks 1218 beq common_backwardBranch @ (want to use BLE but V is unknown) 1219#if defined(WITH_JIT) 1220 GET_JIT_PROF_TABLE(r0) 1221 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1222 cmp r0,#0 1223 bne common_updateProfile 1224 GET_INST_OPCODE(ip) @ extract opcode from rINST 1225 GOTO_OPCODE(ip) @ jump to next instruction 1226#else 1227 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1228 GET_INST_OPCODE(ip) @ extract opcode from rINST 1229 GOTO_OPCODE(ip) @ jump to next instruction 1230#endif 1231 1232/* ------------------------------ */ 1233 .balign 64 1234.L_OP_SPARSE_SWITCH: /* 0x2c */ 1235/* File: armv5te/OP_SPARSE_SWITCH.S */ 1236/* File: armv5te/OP_PACKED_SWITCH.S */ 1237 /* 1238 * Handle a packed-switch or sparse-switch instruction. In both cases 1239 * we decode it and hand it off to a helper function. 1240 * 1241 * We don't really expect backward branches in a switch statement, but 1242 * they're perfectly legal, so we check for them here. 1243 * 1244 * for: packed-switch, sparse-switch 1245 */ 1246 /* op vAA, +BBBB */ 1247 FETCH(r0, 1) @ r0<- bbbb (lo) 1248 FETCH(r1, 2) @ r1<- BBBB (hi) 1249 mov r3, rINST, lsr #8 @ r3<- AA 1250 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1251 GET_VREG(r1, r3) @ r1<- vAA 1252 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1253 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1254 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1255 bmi common_backwardBranch @ backward branch, do periodic checks 1256 beq common_backwardBranch @ (want to use BLE but V is unknown) 1257#if defined(WITH_JIT) 1258 GET_JIT_PROF_TABLE(r0) 1259 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1260 cmp r0,#0 1261 bne common_updateProfile 1262 GET_INST_OPCODE(ip) @ extract opcode from rINST 1263 GOTO_OPCODE(ip) @ jump to next instruction 1264#else 1265 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1266 GET_INST_OPCODE(ip) @ extract opcode from rINST 1267 GOTO_OPCODE(ip) @ jump to next instruction 1268#endif 1269 1270 1271/* ------------------------------ */ 1272 .balign 64 1273.L_OP_CMPL_FLOAT: /* 0x2d */ 1274/* File: arm-vfp/OP_CMPL_FLOAT.S */ 1275 /* 1276 * Compare two floating-point values. Puts 0, 1, or -1 into the 1277 * destination register based on the results of the comparison. 1278 * 1279 * int compare(x, y) { 1280 * if (x == y) { 1281 * return 0; 1282 * } else if (x > y) { 1283 * return 1; 1284 * } else if (x < y) { 1285 * return -1; 1286 * } else { 1287 * return -1; 1288 * } 1289 * } 1290 */ 1291 /* op vAA, vBB, vCC */ 1292 FETCH(r0, 1) @ r0<- CCBB 1293 mov r9, rINST, lsr #8 @ r9<- AA 1294 and r2, r0, #255 @ r2<- BB 1295 mov r3, r0, lsr #8 @ r3<- CC 1296 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1297 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1298 flds s0, [r2] @ s0<- vBB 1299 flds s1, [r3] @ s1<- vCC 1300 fcmpes s0, s1 @ compare (vBB, vCC) 1301 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1302 mvn r0, #0 @ r0<- -1 (default) 1303 GET_INST_OPCODE(ip) @ extract opcode from rINST 1304 fmstat @ export status flags 1305 movgt r0, #1 @ (greater than) r1<- 1 1306 moveq r0, #0 @ (equal) r1<- 0 1307 b .LOP_CMPL_FLOAT_finish @ argh 1308 1309 1310/* ------------------------------ */ 1311 .balign 64 1312.L_OP_CMPG_FLOAT: /* 0x2e */ 1313/* File: arm-vfp/OP_CMPG_FLOAT.S */ 1314 /* 1315 * Compare two floating-point values. Puts 0, 1, or -1 into the 1316 * destination register based on the results of the comparison. 1317 * 1318 * int compare(x, y) { 1319 * if (x == y) { 1320 * return 0; 1321 * } else if (x < y) { 1322 * return -1; 1323 * } else if (x > y) { 1324 * return 1; 1325 * } else { 1326 * return 1; 1327 * } 1328 * } 1329 */ 1330 /* op vAA, vBB, vCC */ 1331 FETCH(r0, 1) @ r0<- CCBB 1332 mov r9, rINST, lsr #8 @ r9<- AA 1333 and r2, r0, #255 @ r2<- BB 1334 mov r3, r0, lsr #8 @ r3<- CC 1335 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1336 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1337 flds s0, [r2] @ s0<- vBB 1338 flds s1, [r3] @ s1<- vCC 1339 fcmpes s0, s1 @ compare (vBB, vCC) 1340 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1341 mov r0, #1 @ r0<- 1 (default) 1342 GET_INST_OPCODE(ip) @ extract opcode from rINST 1343 fmstat @ export status flags 1344 mvnmi r0, #0 @ (less than) r1<- -1 1345 moveq r0, #0 @ (equal) r1<- 0 1346 b .LOP_CMPG_FLOAT_finish @ argh 1347 1348 1349/* ------------------------------ */ 1350 .balign 64 1351.L_OP_CMPL_DOUBLE: /* 0x2f */ 1352/* File: arm-vfp/OP_CMPL_DOUBLE.S */ 1353 /* 1354 * Compare two floating-point values. Puts 0, 1, or -1 into the 1355 * destination register based on the results of the comparison. 1356 * 1357 * int compare(x, y) { 1358 * if (x == y) { 1359 * return 0; 1360 * } else if (x > y) { 1361 * return 1; 1362 * } else if (x < y) { 1363 * return -1; 1364 * } else { 1365 * return -1; 1366 * } 1367 * } 1368 */ 1369 /* op vAA, vBB, vCC */ 1370 FETCH(r0, 1) @ r0<- CCBB 1371 mov r9, rINST, lsr #8 @ r9<- AA 1372 and r2, r0, #255 @ r2<- BB 1373 mov r3, r0, lsr #8 @ r3<- CC 1374 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1375 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1376 fldd d0, [r2] @ d0<- vBB 1377 fldd d1, [r3] @ d1<- vCC 1378 fcmped d0, d1 @ compare (vBB, vCC) 1379 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1380 mvn r0, #0 @ r0<- -1 (default) 1381 GET_INST_OPCODE(ip) @ extract opcode from rINST 1382 fmstat @ export status flags 1383 movgt r0, #1 @ (greater than) r1<- 1 1384 moveq r0, #0 @ (equal) r1<- 0 1385 b .LOP_CMPL_DOUBLE_finish @ argh 1386 1387 1388/* ------------------------------ */ 1389 .balign 64 1390.L_OP_CMPG_DOUBLE: /* 0x30 */ 1391/* File: arm-vfp/OP_CMPG_DOUBLE.S */ 1392 /* 1393 * Compare two floating-point values. Puts 0, 1, or -1 into the 1394 * destination register based on the results of the comparison. 1395 * 1396 * int compare(x, y) { 1397 * if (x == y) { 1398 * return 0; 1399 * } else if (x < y) { 1400 * return -1; 1401 * } else if (x > y) { 1402 * return 1; 1403 * } else { 1404 * return 1; 1405 * } 1406 * } 1407 */ 1408 /* op vAA, vBB, vCC */ 1409 FETCH(r0, 1) @ r0<- CCBB 1410 mov r9, rINST, lsr #8 @ r9<- AA 1411 and r2, r0, #255 @ r2<- BB 1412 mov r3, r0, lsr #8 @ r3<- CC 1413 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1414 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1415 fldd d0, [r2] @ d0<- vBB 1416 fldd d1, [r3] @ d1<- vCC 1417 fcmped d0, d1 @ compare (vBB, vCC) 1418 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1419 mov r0, #1 @ r0<- 1 (default) 1420 GET_INST_OPCODE(ip) @ extract opcode from rINST 1421 fmstat @ export status flags 1422 mvnmi r0, #0 @ (less than) r1<- -1 1423 moveq r0, #0 @ (equal) r1<- 0 1424 b .LOP_CMPG_DOUBLE_finish @ argh 1425 1426 1427/* ------------------------------ */ 1428 .balign 64 1429.L_OP_CMP_LONG: /* 0x31 */ 1430/* File: armv5te/OP_CMP_LONG.S */ 1431 /* 1432 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1433 * register based on the results of the comparison. 1434 * 1435 * We load the full values with LDM, but in practice many values could 1436 * be resolved by only looking at the high word. This could be made 1437 * faster or slower by splitting the LDM into a pair of LDRs. 1438 * 1439 * If we just wanted to set condition flags, we could do this: 1440 * subs ip, r0, r2 1441 * sbcs ip, r1, r3 1442 * subeqs ip, r0, r2 1443 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1444 * integer value, which we can do with 2 conditional mov/mvn instructions 1445 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1446 * us a constant 5-cycle path plus a branch at the end to the 1447 * instruction epilogue code. The multi-compare approach below needs 1448 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1449 * in the worst case (the 64-bit values are equal). 1450 */ 1451 /* cmp-long vAA, vBB, vCC */ 1452 FETCH(r0, 1) @ r0<- CCBB 1453 mov r9, rINST, lsr #8 @ r9<- AA 1454 and r2, r0, #255 @ r2<- BB 1455 mov r3, r0, lsr #8 @ r3<- CC 1456 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1457 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1458 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1459 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1460 cmp r1, r3 @ compare (vBB+1, vCC+1) 1461 blt .LOP_CMP_LONG_less @ signed compare on high part 1462 bgt .LOP_CMP_LONG_greater 1463 subs r1, r0, r2 @ r1<- r0 - r2 1464 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1465 bne .LOP_CMP_LONG_less 1466 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1467 1468/* ------------------------------ */ 1469 .balign 64 1470.L_OP_IF_EQ: /* 0x32 */ 1471/* File: armv5te/OP_IF_EQ.S */ 1472/* File: armv5te/bincmp.S */ 1473 /* 1474 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1475 * fragment that specifies the *reverse* comparison to perform, e.g. 1476 * for "if-le" you would use "gt". 1477 * 1478 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1479 */ 1480 /* if-cmp vA, vB, +CCCC */ 1481 mov r0, rINST, lsr #8 @ r0<- A+ 1482 mov r1, rINST, lsr #12 @ r1<- B 1483 and r0, r0, #15 1484 GET_VREG(r3, r1) @ r3<- vB 1485 GET_VREG(r2, r0) @ r2<- vA 1486 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1487 cmp r2, r3 @ compare (vA, vB) 1488 bne 1f @ branch to 1 if comparison failed 1489 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1490 movs r9, r9, asl #1 @ convert to bytes, check sign 1491 bmi common_backwardBranch @ yes, do periodic checks 14921: 1493#if defined(WITH_JIT) 1494 GET_JIT_PROF_TABLE(r0) 1495 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1496 b common_testUpdateProfile 1497#else 1498 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1499 GET_INST_OPCODE(ip) @ extract opcode from rINST 1500 GOTO_OPCODE(ip) @ jump to next instruction 1501#endif 1502 1503 1504/* ------------------------------ */ 1505 .balign 64 1506.L_OP_IF_NE: /* 0x33 */ 1507/* File: armv5te/OP_IF_NE.S */ 1508/* File: armv5te/bincmp.S */ 1509 /* 1510 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1511 * fragment that specifies the *reverse* comparison to perform, e.g. 1512 * for "if-le" you would use "gt". 1513 * 1514 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1515 */ 1516 /* if-cmp vA, vB, +CCCC */ 1517 mov r0, rINST, lsr #8 @ r0<- A+ 1518 mov r1, rINST, lsr #12 @ r1<- B 1519 and r0, r0, #15 1520 GET_VREG(r3, r1) @ r3<- vB 1521 GET_VREG(r2, r0) @ r2<- vA 1522 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1523 cmp r2, r3 @ compare (vA, vB) 1524 beq 1f @ branch to 1 if comparison failed 1525 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1526 movs r9, r9, asl #1 @ convert to bytes, check sign 1527 bmi common_backwardBranch @ yes, do periodic checks 15281: 1529#if defined(WITH_JIT) 1530 GET_JIT_PROF_TABLE(r0) 1531 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1532 b common_testUpdateProfile 1533#else 1534 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1535 GET_INST_OPCODE(ip) @ extract opcode from rINST 1536 GOTO_OPCODE(ip) @ jump to next instruction 1537#endif 1538 1539 1540/* ------------------------------ */ 1541 .balign 64 1542.L_OP_IF_LT: /* 0x34 */ 1543/* File: armv5te/OP_IF_LT.S */ 1544/* File: armv5te/bincmp.S */ 1545 /* 1546 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1547 * fragment that specifies the *reverse* comparison to perform, e.g. 1548 * for "if-le" you would use "gt". 1549 * 1550 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1551 */ 1552 /* if-cmp vA, vB, +CCCC */ 1553 mov r0, rINST, lsr #8 @ r0<- A+ 1554 mov r1, rINST, lsr #12 @ r1<- B 1555 and r0, r0, #15 1556 GET_VREG(r3, r1) @ r3<- vB 1557 GET_VREG(r2, r0) @ r2<- vA 1558 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1559 cmp r2, r3 @ compare (vA, vB) 1560 bge 1f @ branch to 1 if comparison failed 1561 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1562 movs r9, r9, asl #1 @ convert to bytes, check sign 1563 bmi common_backwardBranch @ yes, do periodic checks 15641: 1565#if defined(WITH_JIT) 1566 GET_JIT_PROF_TABLE(r0) 1567 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1568 b common_testUpdateProfile 1569#else 1570 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1571 GET_INST_OPCODE(ip) @ extract opcode from rINST 1572 GOTO_OPCODE(ip) @ jump to next instruction 1573#endif 1574 1575 1576/* ------------------------------ */ 1577 .balign 64 1578.L_OP_IF_GE: /* 0x35 */ 1579/* File: armv5te/OP_IF_GE.S */ 1580/* File: armv5te/bincmp.S */ 1581 /* 1582 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1583 * fragment that specifies the *reverse* comparison to perform, e.g. 1584 * for "if-le" you would use "gt". 1585 * 1586 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1587 */ 1588 /* if-cmp vA, vB, +CCCC */ 1589 mov r0, rINST, lsr #8 @ r0<- A+ 1590 mov r1, rINST, lsr #12 @ r1<- B 1591 and r0, r0, #15 1592 GET_VREG(r3, r1) @ r3<- vB 1593 GET_VREG(r2, r0) @ r2<- vA 1594 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1595 cmp r2, r3 @ compare (vA, vB) 1596 blt 1f @ branch to 1 if comparison failed 1597 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1598 movs r9, r9, asl #1 @ convert to bytes, check sign 1599 bmi common_backwardBranch @ yes, do periodic checks 16001: 1601#if defined(WITH_JIT) 1602 GET_JIT_PROF_TABLE(r0) 1603 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1604 b common_testUpdateProfile 1605#else 1606 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1607 GET_INST_OPCODE(ip) @ extract opcode from rINST 1608 GOTO_OPCODE(ip) @ jump to next instruction 1609#endif 1610 1611 1612/* ------------------------------ */ 1613 .balign 64 1614.L_OP_IF_GT: /* 0x36 */ 1615/* File: armv5te/OP_IF_GT.S */ 1616/* File: armv5te/bincmp.S */ 1617 /* 1618 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1619 * fragment that specifies the *reverse* comparison to perform, e.g. 1620 * for "if-le" you would use "gt". 1621 * 1622 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1623 */ 1624 /* if-cmp vA, vB, +CCCC */ 1625 mov r0, rINST, lsr #8 @ r0<- A+ 1626 mov r1, rINST, lsr #12 @ r1<- B 1627 and r0, r0, #15 1628 GET_VREG(r3, r1) @ r3<- vB 1629 GET_VREG(r2, r0) @ r2<- vA 1630 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1631 cmp r2, r3 @ compare (vA, vB) 1632 ble 1f @ branch to 1 if comparison failed 1633 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1634 movs r9, r9, asl #1 @ convert to bytes, check sign 1635 bmi common_backwardBranch @ yes, do periodic checks 16361: 1637#if defined(WITH_JIT) 1638 GET_JIT_PROF_TABLE(r0) 1639 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1640 b common_testUpdateProfile 1641#else 1642 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1643 GET_INST_OPCODE(ip) @ extract opcode from rINST 1644 GOTO_OPCODE(ip) @ jump to next instruction 1645#endif 1646 1647 1648/* ------------------------------ */ 1649 .balign 64 1650.L_OP_IF_LE: /* 0x37 */ 1651/* File: armv5te/OP_IF_LE.S */ 1652/* File: armv5te/bincmp.S */ 1653 /* 1654 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1655 * fragment that specifies the *reverse* comparison to perform, e.g. 1656 * for "if-le" you would use "gt". 1657 * 1658 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1659 */ 1660 /* if-cmp vA, vB, +CCCC */ 1661 mov r0, rINST, lsr #8 @ r0<- A+ 1662 mov r1, rINST, lsr #12 @ r1<- B 1663 and r0, r0, #15 1664 GET_VREG(r3, r1) @ r3<- vB 1665 GET_VREG(r2, r0) @ r2<- vA 1666 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1667 cmp r2, r3 @ compare (vA, vB) 1668 bgt 1f @ branch to 1 if comparison failed 1669 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1670 movs r9, r9, asl #1 @ convert to bytes, check sign 1671 bmi common_backwardBranch @ yes, do periodic checks 16721: 1673#if defined(WITH_JIT) 1674 GET_JIT_PROF_TABLE(r0) 1675 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1676 b common_testUpdateProfile 1677#else 1678 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1679 GET_INST_OPCODE(ip) @ extract opcode from rINST 1680 GOTO_OPCODE(ip) @ jump to next instruction 1681#endif 1682 1683 1684/* ------------------------------ */ 1685 .balign 64 1686.L_OP_IF_EQZ: /* 0x38 */ 1687/* File: armv5te/OP_IF_EQZ.S */ 1688/* File: armv5te/zcmp.S */ 1689 /* 1690 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1691 * fragment that specifies the *reverse* comparison to perform, e.g. 1692 * for "if-le" you would use "gt". 1693 * 1694 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1695 */ 1696 /* if-cmp vAA, +BBBB */ 1697 mov r0, rINST, lsr #8 @ r0<- AA 1698 GET_VREG(r2, r0) @ r2<- vAA 1699 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1700 cmp r2, #0 @ compare (vA, 0) 1701 bne 1f @ branch to 1 if comparison failed 1702 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1703 movs r9, r9, asl #1 @ convert to bytes, check sign 1704 bmi common_backwardBranch @ backward branch, do periodic checks 17051: 1706#if defined(WITH_JIT) 1707 GET_JIT_PROF_TABLE(r0) 1708 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1709 cmp r0,#0 1710 bne common_updateProfile 1711 GET_INST_OPCODE(ip) @ extract opcode from rINST 1712 GOTO_OPCODE(ip) @ jump to next instruction 1713#else 1714 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1715 GET_INST_OPCODE(ip) @ extract opcode from rINST 1716 GOTO_OPCODE(ip) @ jump to next instruction 1717#endif 1718 1719 1720/* ------------------------------ */ 1721 .balign 64 1722.L_OP_IF_NEZ: /* 0x39 */ 1723/* File: armv5te/OP_IF_NEZ.S */ 1724/* File: armv5te/zcmp.S */ 1725 /* 1726 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1727 * fragment that specifies the *reverse* comparison to perform, e.g. 1728 * for "if-le" you would use "gt". 1729 * 1730 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1731 */ 1732 /* if-cmp vAA, +BBBB */ 1733 mov r0, rINST, lsr #8 @ r0<- AA 1734 GET_VREG(r2, r0) @ r2<- vAA 1735 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1736 cmp r2, #0 @ compare (vA, 0) 1737 beq 1f @ branch to 1 if comparison failed 1738 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1739 movs r9, r9, asl #1 @ convert to bytes, check sign 1740 bmi common_backwardBranch @ backward branch, do periodic checks 17411: 1742#if defined(WITH_JIT) 1743 GET_JIT_PROF_TABLE(r0) 1744 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1745 cmp r0,#0 1746 bne common_updateProfile 1747 GET_INST_OPCODE(ip) @ extract opcode from rINST 1748 GOTO_OPCODE(ip) @ jump to next instruction 1749#else 1750 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1751 GET_INST_OPCODE(ip) @ extract opcode from rINST 1752 GOTO_OPCODE(ip) @ jump to next instruction 1753#endif 1754 1755 1756/* ------------------------------ */ 1757 .balign 64 1758.L_OP_IF_LTZ: /* 0x3a */ 1759/* File: armv5te/OP_IF_LTZ.S */ 1760/* File: armv5te/zcmp.S */ 1761 /* 1762 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1763 * fragment that specifies the *reverse* comparison to perform, e.g. 1764 * for "if-le" you would use "gt". 1765 * 1766 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1767 */ 1768 /* if-cmp vAA, +BBBB */ 1769 mov r0, rINST, lsr #8 @ r0<- AA 1770 GET_VREG(r2, r0) @ r2<- vAA 1771 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1772 cmp r2, #0 @ compare (vA, 0) 1773 bge 1f @ branch to 1 if comparison failed 1774 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1775 movs r9, r9, asl #1 @ convert to bytes, check sign 1776 bmi common_backwardBranch @ backward branch, do periodic checks 17771: 1778#if defined(WITH_JIT) 1779 GET_JIT_PROF_TABLE(r0) 1780 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1781 cmp r0,#0 1782 bne common_updateProfile 1783 GET_INST_OPCODE(ip) @ extract opcode from rINST 1784 GOTO_OPCODE(ip) @ jump to next instruction 1785#else 1786 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1787 GET_INST_OPCODE(ip) @ extract opcode from rINST 1788 GOTO_OPCODE(ip) @ jump to next instruction 1789#endif 1790 1791 1792/* ------------------------------ */ 1793 .balign 64 1794.L_OP_IF_GEZ: /* 0x3b */ 1795/* File: armv5te/OP_IF_GEZ.S */ 1796/* File: armv5te/zcmp.S */ 1797 /* 1798 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1799 * fragment that specifies the *reverse* comparison to perform, e.g. 1800 * for "if-le" you would use "gt". 1801 * 1802 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1803 */ 1804 /* if-cmp vAA, +BBBB */ 1805 mov r0, rINST, lsr #8 @ r0<- AA 1806 GET_VREG(r2, r0) @ r2<- vAA 1807 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1808 cmp r2, #0 @ compare (vA, 0) 1809 blt 1f @ branch to 1 if comparison failed 1810 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1811 movs r9, r9, asl #1 @ convert to bytes, check sign 1812 bmi common_backwardBranch @ backward branch, do periodic checks 18131: 1814#if defined(WITH_JIT) 1815 GET_JIT_PROF_TABLE(r0) 1816 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1817 cmp r0,#0 1818 bne common_updateProfile 1819 GET_INST_OPCODE(ip) @ extract opcode from rINST 1820 GOTO_OPCODE(ip) @ jump to next instruction 1821#else 1822 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1823 GET_INST_OPCODE(ip) @ extract opcode from rINST 1824 GOTO_OPCODE(ip) @ jump to next instruction 1825#endif 1826 1827 1828/* ------------------------------ */ 1829 .balign 64 1830.L_OP_IF_GTZ: /* 0x3c */ 1831/* File: armv5te/OP_IF_GTZ.S */ 1832/* File: armv5te/zcmp.S */ 1833 /* 1834 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1835 * fragment that specifies the *reverse* comparison to perform, e.g. 1836 * for "if-le" you would use "gt". 1837 * 1838 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1839 */ 1840 /* if-cmp vAA, +BBBB */ 1841 mov r0, rINST, lsr #8 @ r0<- AA 1842 GET_VREG(r2, r0) @ r2<- vAA 1843 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1844 cmp r2, #0 @ compare (vA, 0) 1845 ble 1f @ branch to 1 if comparison failed 1846 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1847 movs r9, r9, asl #1 @ convert to bytes, check sign 1848 bmi common_backwardBranch @ backward branch, do periodic checks 18491: 1850#if defined(WITH_JIT) 1851 GET_JIT_PROF_TABLE(r0) 1852 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1853 cmp r0,#0 1854 bne common_updateProfile 1855 GET_INST_OPCODE(ip) @ extract opcode from rINST 1856 GOTO_OPCODE(ip) @ jump to next instruction 1857#else 1858 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1859 GET_INST_OPCODE(ip) @ extract opcode from rINST 1860 GOTO_OPCODE(ip) @ jump to next instruction 1861#endif 1862 1863 1864/* ------------------------------ */ 1865 .balign 64 1866.L_OP_IF_LEZ: /* 0x3d */ 1867/* File: armv5te/OP_IF_LEZ.S */ 1868/* File: armv5te/zcmp.S */ 1869 /* 1870 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1871 * fragment that specifies the *reverse* comparison to perform, e.g. 1872 * for "if-le" you would use "gt". 1873 * 1874 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1875 */ 1876 /* if-cmp vAA, +BBBB */ 1877 mov r0, rINST, lsr #8 @ r0<- AA 1878 GET_VREG(r2, r0) @ r2<- vAA 1879 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1880 cmp r2, #0 @ compare (vA, 0) 1881 bgt 1f @ branch to 1 if comparison failed 1882 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1883 movs r9, r9, asl #1 @ convert to bytes, check sign 1884 bmi common_backwardBranch @ backward branch, do periodic checks 18851: 1886#if defined(WITH_JIT) 1887 GET_JIT_PROF_TABLE(r0) 1888 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1889 cmp r0,#0 1890 bne common_updateProfile 1891 GET_INST_OPCODE(ip) @ extract opcode from rINST 1892 GOTO_OPCODE(ip) @ jump to next instruction 1893#else 1894 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1895 GET_INST_OPCODE(ip) @ extract opcode from rINST 1896 GOTO_OPCODE(ip) @ jump to next instruction 1897#endif 1898 1899 1900/* ------------------------------ */ 1901 .balign 64 1902.L_OP_UNUSED_3E: /* 0x3e */ 1903/* File: armv5te/OP_UNUSED_3E.S */ 1904/* File: armv5te/unused.S */ 1905 bl common_abort 1906 1907 1908/* ------------------------------ */ 1909 .balign 64 1910.L_OP_UNUSED_3F: /* 0x3f */ 1911/* File: armv5te/OP_UNUSED_3F.S */ 1912/* File: armv5te/unused.S */ 1913 bl common_abort 1914 1915 1916/* ------------------------------ */ 1917 .balign 64 1918.L_OP_UNUSED_40: /* 0x40 */ 1919/* File: armv5te/OP_UNUSED_40.S */ 1920/* File: armv5te/unused.S */ 1921 bl common_abort 1922 1923 1924/* ------------------------------ */ 1925 .balign 64 1926.L_OP_UNUSED_41: /* 0x41 */ 1927/* File: armv5te/OP_UNUSED_41.S */ 1928/* File: armv5te/unused.S */ 1929 bl common_abort 1930 1931 1932/* ------------------------------ */ 1933 .balign 64 1934.L_OP_UNUSED_42: /* 0x42 */ 1935/* File: armv5te/OP_UNUSED_42.S */ 1936/* File: armv5te/unused.S */ 1937 bl common_abort 1938 1939 1940/* ------------------------------ */ 1941 .balign 64 1942.L_OP_UNUSED_43: /* 0x43 */ 1943/* File: armv5te/OP_UNUSED_43.S */ 1944/* File: armv5te/unused.S */ 1945 bl common_abort 1946 1947 1948/* ------------------------------ */ 1949 .balign 64 1950.L_OP_AGET: /* 0x44 */ 1951/* File: armv5te/OP_AGET.S */ 1952 /* 1953 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1954 * 1955 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1956 * instructions. We use a pair of FETCH_Bs instead. 1957 * 1958 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1959 */ 1960 /* op vAA, vBB, vCC */ 1961 FETCH_B(r2, 1, 0) @ r2<- BB 1962 mov r9, rINST, lsr #8 @ r9<- AA 1963 FETCH_B(r3, 1, 1) @ r3<- CC 1964 GET_VREG(r0, r2) @ r0<- vBB (array object) 1965 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1966 cmp r0, #0 @ null array object? 1967 beq common_errNullObject @ yes, bail 1968 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1969 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 1970 cmp r1, r3 @ compare unsigned index, length 1971 bcs common_errArrayIndex @ index >= length, bail 1972 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1973 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 1974 GET_INST_OPCODE(ip) @ extract opcode from rINST 1975 SET_VREG(r2, r9) @ vAA<- r2 1976 GOTO_OPCODE(ip) @ jump to next instruction 1977 1978/* ------------------------------ */ 1979 .balign 64 1980.L_OP_AGET_WIDE: /* 0x45 */ 1981/* File: armv5te/OP_AGET_WIDE.S */ 1982 /* 1983 * Array get, 64 bits. vAA <- vBB[vCC]. 1984 * 1985 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 1986 */ 1987 /* aget-wide vAA, vBB, vCC */ 1988 FETCH(r0, 1) @ r0<- CCBB 1989 mov r9, rINST, lsr #8 @ r9<- AA 1990 and r2, r0, #255 @ r2<- BB 1991 mov r3, r0, lsr #8 @ r3<- CC 1992 GET_VREG(r0, r2) @ r0<- vBB (array object) 1993 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1994 cmp r0, #0 @ null array object? 1995 beq common_errNullObject @ yes, bail 1996 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1997 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 1998 cmp r1, r3 @ compare unsigned index, length 1999 bcc .LOP_AGET_WIDE_finish @ okay, continue below 2000 b common_errArrayIndex @ index >= length, bail 2001 @ May want to swap the order of these two branches depending on how the 2002 @ branch prediction (if any) handles conditional forward branches vs. 2003 @ unconditional forward branches. 2004 2005/* ------------------------------ */ 2006 .balign 64 2007.L_OP_AGET_OBJECT: /* 0x46 */ 2008/* File: armv5te/OP_AGET_OBJECT.S */ 2009/* File: armv5te/OP_AGET.S */ 2010 /* 2011 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2012 * 2013 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2014 * instructions. We use a pair of FETCH_Bs instead. 2015 * 2016 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2017 */ 2018 /* op vAA, vBB, vCC */ 2019 FETCH_B(r2, 1, 0) @ r2<- BB 2020 mov r9, rINST, lsr #8 @ r9<- AA 2021 FETCH_B(r3, 1, 1) @ r3<- CC 2022 GET_VREG(r0, r2) @ r0<- vBB (array object) 2023 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2024 cmp r0, #0 @ null array object? 2025 beq common_errNullObject @ yes, bail 2026 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2027 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2028 cmp r1, r3 @ compare unsigned index, length 2029 bcs common_errArrayIndex @ index >= length, bail 2030 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2031 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2032 GET_INST_OPCODE(ip) @ extract opcode from rINST 2033 SET_VREG(r2, r9) @ vAA<- r2 2034 GOTO_OPCODE(ip) @ jump to next instruction 2035 2036 2037/* ------------------------------ */ 2038 .balign 64 2039.L_OP_AGET_BOOLEAN: /* 0x47 */ 2040/* File: armv5te/OP_AGET_BOOLEAN.S */ 2041/* File: armv5te/OP_AGET.S */ 2042 /* 2043 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2044 * 2045 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2046 * instructions. We use a pair of FETCH_Bs instead. 2047 * 2048 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2049 */ 2050 /* op vAA, vBB, vCC */ 2051 FETCH_B(r2, 1, 0) @ r2<- BB 2052 mov r9, rINST, lsr #8 @ r9<- AA 2053 FETCH_B(r3, 1, 1) @ r3<- CC 2054 GET_VREG(r0, r2) @ r0<- vBB (array object) 2055 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2056 cmp r0, #0 @ null array object? 2057 beq common_errNullObject @ yes, bail 2058 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2059 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2060 cmp r1, r3 @ compare unsigned index, length 2061 bcs common_errArrayIndex @ index >= length, bail 2062 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2063 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2064 GET_INST_OPCODE(ip) @ extract opcode from rINST 2065 SET_VREG(r2, r9) @ vAA<- r2 2066 GOTO_OPCODE(ip) @ jump to next instruction 2067 2068 2069/* ------------------------------ */ 2070 .balign 64 2071.L_OP_AGET_BYTE: /* 0x48 */ 2072/* File: armv5te/OP_AGET_BYTE.S */ 2073/* File: armv5te/OP_AGET.S */ 2074 /* 2075 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2076 * 2077 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2078 * instructions. We use a pair of FETCH_Bs instead. 2079 * 2080 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2081 */ 2082 /* op vAA, vBB, vCC */ 2083 FETCH_B(r2, 1, 0) @ r2<- BB 2084 mov r9, rINST, lsr #8 @ r9<- AA 2085 FETCH_B(r3, 1, 1) @ r3<- CC 2086 GET_VREG(r0, r2) @ r0<- vBB (array object) 2087 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2088 cmp r0, #0 @ null array object? 2089 beq common_errNullObject @ yes, bail 2090 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2091 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2092 cmp r1, r3 @ compare unsigned index, length 2093 bcs common_errArrayIndex @ index >= length, bail 2094 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2095 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2096 GET_INST_OPCODE(ip) @ extract opcode from rINST 2097 SET_VREG(r2, r9) @ vAA<- r2 2098 GOTO_OPCODE(ip) @ jump to next instruction 2099 2100 2101/* ------------------------------ */ 2102 .balign 64 2103.L_OP_AGET_CHAR: /* 0x49 */ 2104/* File: armv5te/OP_AGET_CHAR.S */ 2105/* File: armv5te/OP_AGET.S */ 2106 /* 2107 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2108 * 2109 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2110 * instructions. We use a pair of FETCH_Bs instead. 2111 * 2112 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2113 */ 2114 /* op vAA, vBB, vCC */ 2115 FETCH_B(r2, 1, 0) @ r2<- BB 2116 mov r9, rINST, lsr #8 @ r9<- AA 2117 FETCH_B(r3, 1, 1) @ r3<- CC 2118 GET_VREG(r0, r2) @ r0<- vBB (array object) 2119 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2120 cmp r0, #0 @ null array object? 2121 beq common_errNullObject @ yes, bail 2122 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2123 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2124 cmp r1, r3 @ compare unsigned index, length 2125 bcs common_errArrayIndex @ index >= length, bail 2126 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2127 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2128 GET_INST_OPCODE(ip) @ extract opcode from rINST 2129 SET_VREG(r2, r9) @ vAA<- r2 2130 GOTO_OPCODE(ip) @ jump to next instruction 2131 2132 2133/* ------------------------------ */ 2134 .balign 64 2135.L_OP_AGET_SHORT: /* 0x4a */ 2136/* File: armv5te/OP_AGET_SHORT.S */ 2137/* File: armv5te/OP_AGET.S */ 2138 /* 2139 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2140 * 2141 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2142 * instructions. We use a pair of FETCH_Bs instead. 2143 * 2144 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2145 */ 2146 /* op vAA, vBB, vCC */ 2147 FETCH_B(r2, 1, 0) @ r2<- BB 2148 mov r9, rINST, lsr #8 @ r9<- AA 2149 FETCH_B(r3, 1, 1) @ r3<- CC 2150 GET_VREG(r0, r2) @ r0<- vBB (array object) 2151 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2152 cmp r0, #0 @ null array object? 2153 beq common_errNullObject @ yes, bail 2154 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2155 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2156 cmp r1, r3 @ compare unsigned index, length 2157 bcs common_errArrayIndex @ index >= length, bail 2158 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2159 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2160 GET_INST_OPCODE(ip) @ extract opcode from rINST 2161 SET_VREG(r2, r9) @ vAA<- r2 2162 GOTO_OPCODE(ip) @ jump to next instruction 2163 2164 2165/* ------------------------------ */ 2166 .balign 64 2167.L_OP_APUT: /* 0x4b */ 2168/* File: armv5te/OP_APUT.S */ 2169 /* 2170 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2171 * 2172 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2173 * instructions. We use a pair of FETCH_Bs instead. 2174 * 2175 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2176 */ 2177 /* op vAA, vBB, vCC */ 2178 FETCH_B(r2, 1, 0) @ r2<- BB 2179 mov r9, rINST, lsr #8 @ r9<- AA 2180 FETCH_B(r3, 1, 1) @ r3<- CC 2181 GET_VREG(r0, r2) @ r0<- vBB (array object) 2182 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2183 cmp r0, #0 @ null array object? 2184 beq common_errNullObject @ yes, bail 2185 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2186 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2187 cmp r1, r3 @ compare unsigned index, length 2188 bcs common_errArrayIndex @ index >= length, bail 2189 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2190 GET_VREG(r2, r9) @ r2<- vAA 2191 GET_INST_OPCODE(ip) @ extract opcode from rINST 2192 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2193 GOTO_OPCODE(ip) @ jump to next instruction 2194 2195/* ------------------------------ */ 2196 .balign 64 2197.L_OP_APUT_WIDE: /* 0x4c */ 2198/* File: armv5te/OP_APUT_WIDE.S */ 2199 /* 2200 * Array put, 64 bits. vBB[vCC] <- vAA. 2201 * 2202 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 2203 */ 2204 /* aput-wide vAA, vBB, vCC */ 2205 FETCH(r0, 1) @ r0<- CCBB 2206 mov r9, rINST, lsr #8 @ r9<- AA 2207 and r2, r0, #255 @ r2<- BB 2208 mov r3, r0, lsr #8 @ r3<- CC 2209 GET_VREG(r0, r2) @ r0<- vBB (array object) 2210 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2211 cmp r0, #0 @ null array object? 2212 beq common_errNullObject @ yes, bail 2213 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2214 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2215 cmp r1, r3 @ compare unsigned index, length 2216 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2217 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2218 b common_errArrayIndex @ index >= length, bail 2219 @ May want to swap the order of these two branches depending on how the 2220 @ branch prediction (if any) handles conditional forward branches vs. 2221 @ unconditional forward branches. 2222 2223/* ------------------------------ */ 2224 .balign 64 2225.L_OP_APUT_OBJECT: /* 0x4d */ 2226/* File: armv5te/OP_APUT_OBJECT.S */ 2227 /* 2228 * Store an object into an array. vBB[vCC] <- vAA. 2229 */ 2230 /* op vAA, vBB, vCC */ 2231 FETCH(r0, 1) @ r0<- CCBB 2232 mov r9, rINST, lsr #8 @ r9<- AA 2233 and r2, r0, #255 @ r2<- BB 2234 mov r3, r0, lsr #8 @ r3<- CC 2235 GET_VREG(rINST, r2) @ rINST<- vBB (array object) 2236 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2237 cmp rINST, #0 @ null array object? 2238 GET_VREG(r9, r9) @ r9<- vAA 2239 beq common_errNullObject @ yes, bail 2240 ldr r3, [rINST, #offArrayObject_length] @ r3<- arrayObj->length 2241 add r10, rINST, r1, lsl #2 @ r10<- arrayObj + index*width 2242 cmp r1, r3 @ compare unsigned index, length 2243 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2244 b common_errArrayIndex @ index >= length, bail 2245 2246 2247/* ------------------------------ */ 2248 .balign 64 2249.L_OP_APUT_BOOLEAN: /* 0x4e */ 2250/* File: armv5te/OP_APUT_BOOLEAN.S */ 2251/* File: armv5te/OP_APUT.S */ 2252 /* 2253 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2254 * 2255 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2256 * instructions. We use a pair of FETCH_Bs instead. 2257 * 2258 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2259 */ 2260 /* op vAA, vBB, vCC */ 2261 FETCH_B(r2, 1, 0) @ r2<- BB 2262 mov r9, rINST, lsr #8 @ r9<- AA 2263 FETCH_B(r3, 1, 1) @ r3<- CC 2264 GET_VREG(r0, r2) @ r0<- vBB (array object) 2265 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2266 cmp r0, #0 @ null array object? 2267 beq common_errNullObject @ yes, bail 2268 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2269 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2270 cmp r1, r3 @ compare unsigned index, length 2271 bcs common_errArrayIndex @ index >= length, bail 2272 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2273 GET_VREG(r2, r9) @ r2<- vAA 2274 GET_INST_OPCODE(ip) @ extract opcode from rINST 2275 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2276 GOTO_OPCODE(ip) @ jump to next instruction 2277 2278 2279/* ------------------------------ */ 2280 .balign 64 2281.L_OP_APUT_BYTE: /* 0x4f */ 2282/* File: armv5te/OP_APUT_BYTE.S */ 2283/* File: armv5te/OP_APUT.S */ 2284 /* 2285 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2286 * 2287 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2288 * instructions. We use a pair of FETCH_Bs instead. 2289 * 2290 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2291 */ 2292 /* op vAA, vBB, vCC */ 2293 FETCH_B(r2, 1, 0) @ r2<- BB 2294 mov r9, rINST, lsr #8 @ r9<- AA 2295 FETCH_B(r3, 1, 1) @ r3<- CC 2296 GET_VREG(r0, r2) @ r0<- vBB (array object) 2297 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2298 cmp r0, #0 @ null array object? 2299 beq common_errNullObject @ yes, bail 2300 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2301 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2302 cmp r1, r3 @ compare unsigned index, length 2303 bcs common_errArrayIndex @ index >= length, bail 2304 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2305 GET_VREG(r2, r9) @ r2<- vAA 2306 GET_INST_OPCODE(ip) @ extract opcode from rINST 2307 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2308 GOTO_OPCODE(ip) @ jump to next instruction 2309 2310 2311/* ------------------------------ */ 2312 .balign 64 2313.L_OP_APUT_CHAR: /* 0x50 */ 2314/* File: armv5te/OP_APUT_CHAR.S */ 2315/* File: armv5te/OP_APUT.S */ 2316 /* 2317 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2318 * 2319 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2320 * instructions. We use a pair of FETCH_Bs instead. 2321 * 2322 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2323 */ 2324 /* op vAA, vBB, vCC */ 2325 FETCH_B(r2, 1, 0) @ r2<- BB 2326 mov r9, rINST, lsr #8 @ r9<- AA 2327 FETCH_B(r3, 1, 1) @ r3<- CC 2328 GET_VREG(r0, r2) @ r0<- vBB (array object) 2329 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2330 cmp r0, #0 @ null array object? 2331 beq common_errNullObject @ yes, bail 2332 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2333 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2334 cmp r1, r3 @ compare unsigned index, length 2335 bcs common_errArrayIndex @ index >= length, bail 2336 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2337 GET_VREG(r2, r9) @ r2<- vAA 2338 GET_INST_OPCODE(ip) @ extract opcode from rINST 2339 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2340 GOTO_OPCODE(ip) @ jump to next instruction 2341 2342 2343/* ------------------------------ */ 2344 .balign 64 2345.L_OP_APUT_SHORT: /* 0x51 */ 2346/* File: armv5te/OP_APUT_SHORT.S */ 2347/* File: armv5te/OP_APUT.S */ 2348 /* 2349 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2350 * 2351 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2352 * instructions. We use a pair of FETCH_Bs instead. 2353 * 2354 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2355 */ 2356 /* op vAA, vBB, vCC */ 2357 FETCH_B(r2, 1, 0) @ r2<- BB 2358 mov r9, rINST, lsr #8 @ r9<- AA 2359 FETCH_B(r3, 1, 1) @ r3<- CC 2360 GET_VREG(r0, r2) @ r0<- vBB (array object) 2361 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2362 cmp r0, #0 @ null array object? 2363 beq common_errNullObject @ yes, bail 2364 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2365 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2366 cmp r1, r3 @ compare unsigned index, length 2367 bcs common_errArrayIndex @ index >= length, bail 2368 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2369 GET_VREG(r2, r9) @ r2<- vAA 2370 GET_INST_OPCODE(ip) @ extract opcode from rINST 2371 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2372 GOTO_OPCODE(ip) @ jump to next instruction 2373 2374 2375/* ------------------------------ */ 2376 .balign 64 2377.L_OP_IGET: /* 0x52 */ 2378/* File: armv5te/OP_IGET.S */ 2379 /* 2380 * General 32-bit instance field get. 2381 * 2382 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2383 */ 2384 /* op vA, vB, field@CCCC */ 2385 mov r0, rINST, lsr #12 @ r0<- B 2386 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2387 FETCH(r1, 1) @ r1<- field ref CCCC 2388 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2389 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2390 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2391 cmp r0, #0 @ is resolved entry null? 2392 bne .LOP_IGET_finish @ no, already resolved 23938: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2394 EXPORT_PC() @ resolve() could throw 2395 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2396 bl dvmResolveInstField @ r0<- resolved InstField ptr 2397 cmp r0, #0 2398 bne .LOP_IGET_finish 2399 b common_exceptionThrown 2400 2401/* ------------------------------ */ 2402 .balign 64 2403.L_OP_IGET_WIDE: /* 0x53 */ 2404/* File: armv5te/OP_IGET_WIDE.S */ 2405 /* 2406 * Wide 32-bit instance field get. 2407 */ 2408 /* iget-wide vA, vB, field@CCCC */ 2409 mov r0, rINST, lsr #12 @ r0<- B 2410 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2411 FETCH(r1, 1) @ r1<- field ref CCCC 2412 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2413 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2414 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2415 cmp r0, #0 @ is resolved entry null? 2416 bne .LOP_IGET_WIDE_finish @ no, already resolved 24178: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2418 EXPORT_PC() @ resolve() could throw 2419 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2420 bl dvmResolveInstField @ r0<- resolved InstField ptr 2421 cmp r0, #0 2422 bne .LOP_IGET_WIDE_finish 2423 b common_exceptionThrown 2424 2425/* ------------------------------ */ 2426 .balign 64 2427.L_OP_IGET_OBJECT: /* 0x54 */ 2428/* File: armv5te/OP_IGET_OBJECT.S */ 2429/* File: armv5te/OP_IGET.S */ 2430 /* 2431 * General 32-bit instance field get. 2432 * 2433 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2434 */ 2435 /* op vA, vB, field@CCCC */ 2436 mov r0, rINST, lsr #12 @ r0<- B 2437 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2438 FETCH(r1, 1) @ r1<- field ref CCCC 2439 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2440 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2441 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2442 cmp r0, #0 @ is resolved entry null? 2443 bne .LOP_IGET_OBJECT_finish @ no, already resolved 24448: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2445 EXPORT_PC() @ resolve() could throw 2446 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2447 bl dvmResolveInstField @ r0<- resolved InstField ptr 2448 cmp r0, #0 2449 bne .LOP_IGET_OBJECT_finish 2450 b common_exceptionThrown 2451 2452 2453/* ------------------------------ */ 2454 .balign 64 2455.L_OP_IGET_BOOLEAN: /* 0x55 */ 2456/* File: armv5te/OP_IGET_BOOLEAN.S */ 2457@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2458/* File: armv5te/OP_IGET.S */ 2459 /* 2460 * General 32-bit instance field get. 2461 * 2462 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2463 */ 2464 /* op vA, vB, field@CCCC */ 2465 mov r0, rINST, lsr #12 @ r0<- B 2466 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2467 FETCH(r1, 1) @ r1<- field ref CCCC 2468 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2469 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2470 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2471 cmp r0, #0 @ is resolved entry null? 2472 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 24738: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2474 EXPORT_PC() @ resolve() could throw 2475 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2476 bl dvmResolveInstField @ r0<- resolved InstField ptr 2477 cmp r0, #0 2478 bne .LOP_IGET_BOOLEAN_finish 2479 b common_exceptionThrown 2480 2481 2482/* ------------------------------ */ 2483 .balign 64 2484.L_OP_IGET_BYTE: /* 0x56 */ 2485/* File: armv5te/OP_IGET_BYTE.S */ 2486@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2487/* File: armv5te/OP_IGET.S */ 2488 /* 2489 * General 32-bit instance field get. 2490 * 2491 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2492 */ 2493 /* op vA, vB, field@CCCC */ 2494 mov r0, rINST, lsr #12 @ r0<- B 2495 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2496 FETCH(r1, 1) @ r1<- field ref CCCC 2497 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2498 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2499 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2500 cmp r0, #0 @ is resolved entry null? 2501 bne .LOP_IGET_BYTE_finish @ no, already resolved 25028: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2503 EXPORT_PC() @ resolve() could throw 2504 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2505 bl dvmResolveInstField @ r0<- resolved InstField ptr 2506 cmp r0, #0 2507 bne .LOP_IGET_BYTE_finish 2508 b common_exceptionThrown 2509 2510 2511/* ------------------------------ */ 2512 .balign 64 2513.L_OP_IGET_CHAR: /* 0x57 */ 2514/* File: armv5te/OP_IGET_CHAR.S */ 2515@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2516/* File: armv5te/OP_IGET.S */ 2517 /* 2518 * General 32-bit instance field get. 2519 * 2520 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2521 */ 2522 /* op vA, vB, field@CCCC */ 2523 mov r0, rINST, lsr #12 @ r0<- B 2524 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2525 FETCH(r1, 1) @ r1<- field ref CCCC 2526 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2527 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2528 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2529 cmp r0, #0 @ is resolved entry null? 2530 bne .LOP_IGET_CHAR_finish @ no, already resolved 25318: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2532 EXPORT_PC() @ resolve() could throw 2533 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2534 bl dvmResolveInstField @ r0<- resolved InstField ptr 2535 cmp r0, #0 2536 bne .LOP_IGET_CHAR_finish 2537 b common_exceptionThrown 2538 2539 2540/* ------------------------------ */ 2541 .balign 64 2542.L_OP_IGET_SHORT: /* 0x58 */ 2543/* File: armv5te/OP_IGET_SHORT.S */ 2544@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2545/* File: armv5te/OP_IGET.S */ 2546 /* 2547 * General 32-bit instance field get. 2548 * 2549 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2550 */ 2551 /* op vA, vB, field@CCCC */ 2552 mov r0, rINST, lsr #12 @ r0<- B 2553 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2554 FETCH(r1, 1) @ r1<- field ref CCCC 2555 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2556 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2557 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2558 cmp r0, #0 @ is resolved entry null? 2559 bne .LOP_IGET_SHORT_finish @ no, already resolved 25608: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2561 EXPORT_PC() @ resolve() could throw 2562 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2563 bl dvmResolveInstField @ r0<- resolved InstField ptr 2564 cmp r0, #0 2565 bne .LOP_IGET_SHORT_finish 2566 b common_exceptionThrown 2567 2568 2569/* ------------------------------ */ 2570 .balign 64 2571.L_OP_IPUT: /* 0x59 */ 2572/* File: armv5te/OP_IPUT.S */ 2573 /* 2574 * General 32-bit instance field put. 2575 * 2576 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2577 */ 2578 /* op vA, vB, field@CCCC */ 2579 mov r0, rINST, lsr #12 @ r0<- B 2580 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2581 FETCH(r1, 1) @ r1<- field ref CCCC 2582 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2583 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2584 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2585 cmp r0, #0 @ is resolved entry null? 2586 bne .LOP_IPUT_finish @ no, already resolved 25878: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2588 EXPORT_PC() @ resolve() could throw 2589 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2590 bl dvmResolveInstField @ r0<- resolved InstField ptr 2591 cmp r0, #0 @ success? 2592 bne .LOP_IPUT_finish @ yes, finish up 2593 b common_exceptionThrown 2594 2595/* ------------------------------ */ 2596 .balign 64 2597.L_OP_IPUT_WIDE: /* 0x5a */ 2598/* File: armv5te/OP_IPUT_WIDE.S */ 2599 /* iput-wide vA, vB, field@CCCC */ 2600 mov r0, rINST, lsr #12 @ r0<- B 2601 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2602 FETCH(r1, 1) @ r1<- field ref CCCC 2603 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2604 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2605 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2606 cmp r0, #0 @ is resolved entry null? 2607 bne .LOP_IPUT_WIDE_finish @ no, already resolved 26088: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2609 EXPORT_PC() @ resolve() could throw 2610 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2611 bl dvmResolveInstField @ r0<- resolved InstField ptr 2612 cmp r0, #0 @ success? 2613 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2614 b common_exceptionThrown 2615 2616/* ------------------------------ */ 2617 .balign 64 2618.L_OP_IPUT_OBJECT: /* 0x5b */ 2619/* File: armv5te/OP_IPUT_OBJECT.S */ 2620 /* 2621 * 32-bit instance field put. 2622 * 2623 * for: iput-object, iput-object-volatile 2624 */ 2625 /* op vA, vB, field@CCCC */ 2626 mov r0, rINST, lsr #12 @ r0<- B 2627 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2628 FETCH(r1, 1) @ r1<- field ref CCCC 2629 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2630 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2631 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2632 cmp r0, #0 @ is resolved entry null? 2633 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 26348: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2635 EXPORT_PC() @ resolve() could throw 2636 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2637 bl dvmResolveInstField @ r0<- resolved InstField ptr 2638 cmp r0, #0 @ success? 2639 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2640 b common_exceptionThrown 2641 2642/* ------------------------------ */ 2643 .balign 64 2644.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2645/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2646@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2647/* File: armv5te/OP_IPUT.S */ 2648 /* 2649 * General 32-bit instance field put. 2650 * 2651 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2652 */ 2653 /* op vA, vB, field@CCCC */ 2654 mov r0, rINST, lsr #12 @ r0<- B 2655 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2656 FETCH(r1, 1) @ r1<- field ref CCCC 2657 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2658 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2659 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2660 cmp r0, #0 @ is resolved entry null? 2661 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 26628: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2663 EXPORT_PC() @ resolve() could throw 2664 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2665 bl dvmResolveInstField @ r0<- resolved InstField ptr 2666 cmp r0, #0 @ success? 2667 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2668 b common_exceptionThrown 2669 2670 2671/* ------------------------------ */ 2672 .balign 64 2673.L_OP_IPUT_BYTE: /* 0x5d */ 2674/* File: armv5te/OP_IPUT_BYTE.S */ 2675@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2676/* File: armv5te/OP_IPUT.S */ 2677 /* 2678 * General 32-bit instance field put. 2679 * 2680 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2681 */ 2682 /* op vA, vB, field@CCCC */ 2683 mov r0, rINST, lsr #12 @ r0<- B 2684 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2685 FETCH(r1, 1) @ r1<- field ref CCCC 2686 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2687 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2688 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2689 cmp r0, #0 @ is resolved entry null? 2690 bne .LOP_IPUT_BYTE_finish @ no, already resolved 26918: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2692 EXPORT_PC() @ resolve() could throw 2693 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2694 bl dvmResolveInstField @ r0<- resolved InstField ptr 2695 cmp r0, #0 @ success? 2696 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2697 b common_exceptionThrown 2698 2699 2700/* ------------------------------ */ 2701 .balign 64 2702.L_OP_IPUT_CHAR: /* 0x5e */ 2703/* File: armv5te/OP_IPUT_CHAR.S */ 2704@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2705/* File: armv5te/OP_IPUT.S */ 2706 /* 2707 * General 32-bit instance field put. 2708 * 2709 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2710 */ 2711 /* op vA, vB, field@CCCC */ 2712 mov r0, rINST, lsr #12 @ r0<- B 2713 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2714 FETCH(r1, 1) @ r1<- field ref CCCC 2715 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2716 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2717 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2718 cmp r0, #0 @ is resolved entry null? 2719 bne .LOP_IPUT_CHAR_finish @ no, already resolved 27208: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2721 EXPORT_PC() @ resolve() could throw 2722 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2723 bl dvmResolveInstField @ r0<- resolved InstField ptr 2724 cmp r0, #0 @ success? 2725 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2726 b common_exceptionThrown 2727 2728 2729/* ------------------------------ */ 2730 .balign 64 2731.L_OP_IPUT_SHORT: /* 0x5f */ 2732/* File: armv5te/OP_IPUT_SHORT.S */ 2733@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2734/* File: armv5te/OP_IPUT.S */ 2735 /* 2736 * General 32-bit instance field put. 2737 * 2738 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2739 */ 2740 /* op vA, vB, field@CCCC */ 2741 mov r0, rINST, lsr #12 @ r0<- B 2742 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2743 FETCH(r1, 1) @ r1<- field ref CCCC 2744 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2745 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2746 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2747 cmp r0, #0 @ is resolved entry null? 2748 bne .LOP_IPUT_SHORT_finish @ no, already resolved 27498: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2750 EXPORT_PC() @ resolve() could throw 2751 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2752 bl dvmResolveInstField @ r0<- resolved InstField ptr 2753 cmp r0, #0 @ success? 2754 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2755 b common_exceptionThrown 2756 2757 2758/* ------------------------------ */ 2759 .balign 64 2760.L_OP_SGET: /* 0x60 */ 2761/* File: armv5te/OP_SGET.S */ 2762 /* 2763 * General 32-bit SGET handler. 2764 * 2765 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2766 */ 2767 /* op vAA, field@BBBB */ 2768 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2769 FETCH(r1, 1) @ r1<- field ref BBBB 2770 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2771 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2772 cmp r0, #0 @ is resolved entry null? 2773 beq .LOP_SGET_resolve @ yes, do resolve 2774.LOP_SGET_finish: @ field ptr in r0 2775 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2776 @ no-op @ acquiring load 2777 mov r2, rINST, lsr #8 @ r2<- AA 2778 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2779 SET_VREG(r1, r2) @ fp[AA]<- r1 2780 GET_INST_OPCODE(ip) @ extract opcode from rINST 2781 GOTO_OPCODE(ip) @ jump to next instruction 2782 2783/* ------------------------------ */ 2784 .balign 64 2785.L_OP_SGET_WIDE: /* 0x61 */ 2786/* File: armv5te/OP_SGET_WIDE.S */ 2787 /* 2788 * 64-bit SGET handler. 2789 */ 2790 /* sget-wide vAA, field@BBBB */ 2791 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2792 FETCH(r1, 1) @ r1<- field ref BBBB 2793 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2794 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2795 cmp r0, #0 @ is resolved entry null? 2796 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2797.LOP_SGET_WIDE_finish: 2798 mov r9, rINST, lsr #8 @ r9<- AA 2799 .if 0 2800 add r0, r0, #offStaticField_value @ r0<- pointer to data 2801 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 2802 .else 2803 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 2804 .endif 2805 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2806 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2807 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 2808 GET_INST_OPCODE(ip) @ extract opcode from rINST 2809 GOTO_OPCODE(ip) @ jump to next instruction 2810 2811/* ------------------------------ */ 2812 .balign 64 2813.L_OP_SGET_OBJECT: /* 0x62 */ 2814/* File: armv5te/OP_SGET_OBJECT.S */ 2815/* File: armv5te/OP_SGET.S */ 2816 /* 2817 * General 32-bit SGET handler. 2818 * 2819 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2820 */ 2821 /* op vAA, field@BBBB */ 2822 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2823 FETCH(r1, 1) @ r1<- field ref BBBB 2824 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2825 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2826 cmp r0, #0 @ is resolved entry null? 2827 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2828.LOP_SGET_OBJECT_finish: @ field ptr in r0 2829 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2830 @ no-op @ acquiring load 2831 mov r2, rINST, lsr #8 @ r2<- AA 2832 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2833 SET_VREG(r1, r2) @ fp[AA]<- r1 2834 GET_INST_OPCODE(ip) @ extract opcode from rINST 2835 GOTO_OPCODE(ip) @ jump to next instruction 2836 2837 2838/* ------------------------------ */ 2839 .balign 64 2840.L_OP_SGET_BOOLEAN: /* 0x63 */ 2841/* File: armv5te/OP_SGET_BOOLEAN.S */ 2842/* File: armv5te/OP_SGET.S */ 2843 /* 2844 * General 32-bit SGET handler. 2845 * 2846 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2847 */ 2848 /* op vAA, field@BBBB */ 2849 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2850 FETCH(r1, 1) @ r1<- field ref BBBB 2851 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2852 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2853 cmp r0, #0 @ is resolved entry null? 2854 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2855.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2856 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2857 @ no-op @ acquiring load 2858 mov r2, rINST, lsr #8 @ r2<- AA 2859 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2860 SET_VREG(r1, r2) @ fp[AA]<- r1 2861 GET_INST_OPCODE(ip) @ extract opcode from rINST 2862 GOTO_OPCODE(ip) @ jump to next instruction 2863 2864 2865/* ------------------------------ */ 2866 .balign 64 2867.L_OP_SGET_BYTE: /* 0x64 */ 2868/* File: armv5te/OP_SGET_BYTE.S */ 2869/* File: armv5te/OP_SGET.S */ 2870 /* 2871 * General 32-bit SGET handler. 2872 * 2873 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2874 */ 2875 /* op vAA, field@BBBB */ 2876 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2877 FETCH(r1, 1) @ r1<- field ref BBBB 2878 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2879 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2880 cmp r0, #0 @ is resolved entry null? 2881 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2882.LOP_SGET_BYTE_finish: @ field ptr in r0 2883 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2884 @ no-op @ acquiring load 2885 mov r2, rINST, lsr #8 @ r2<- AA 2886 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2887 SET_VREG(r1, r2) @ fp[AA]<- r1 2888 GET_INST_OPCODE(ip) @ extract opcode from rINST 2889 GOTO_OPCODE(ip) @ jump to next instruction 2890 2891 2892/* ------------------------------ */ 2893 .balign 64 2894.L_OP_SGET_CHAR: /* 0x65 */ 2895/* File: armv5te/OP_SGET_CHAR.S */ 2896/* File: armv5te/OP_SGET.S */ 2897 /* 2898 * General 32-bit SGET handler. 2899 * 2900 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2901 */ 2902 /* op vAA, field@BBBB */ 2903 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2904 FETCH(r1, 1) @ r1<- field ref BBBB 2905 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2906 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2907 cmp r0, #0 @ is resolved entry null? 2908 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2909.LOP_SGET_CHAR_finish: @ field ptr in r0 2910 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2911 @ no-op @ acquiring load 2912 mov r2, rINST, lsr #8 @ r2<- AA 2913 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2914 SET_VREG(r1, r2) @ fp[AA]<- r1 2915 GET_INST_OPCODE(ip) @ extract opcode from rINST 2916 GOTO_OPCODE(ip) @ jump to next instruction 2917 2918 2919/* ------------------------------ */ 2920 .balign 64 2921.L_OP_SGET_SHORT: /* 0x66 */ 2922/* File: armv5te/OP_SGET_SHORT.S */ 2923/* File: armv5te/OP_SGET.S */ 2924 /* 2925 * General 32-bit SGET handler. 2926 * 2927 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2928 */ 2929 /* op vAA, field@BBBB */ 2930 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2931 FETCH(r1, 1) @ r1<- field ref BBBB 2932 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2933 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2934 cmp r0, #0 @ is resolved entry null? 2935 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 2936.LOP_SGET_SHORT_finish: @ field ptr in r0 2937 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2938 @ no-op @ acquiring load 2939 mov r2, rINST, lsr #8 @ r2<- AA 2940 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2941 SET_VREG(r1, r2) @ fp[AA]<- r1 2942 GET_INST_OPCODE(ip) @ extract opcode from rINST 2943 GOTO_OPCODE(ip) @ jump to next instruction 2944 2945 2946/* ------------------------------ */ 2947 .balign 64 2948.L_OP_SPUT: /* 0x67 */ 2949/* File: armv5te/OP_SPUT.S */ 2950 /* 2951 * General 32-bit SPUT handler. 2952 * 2953 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 2954 */ 2955 /* op vAA, field@BBBB */ 2956 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2957 FETCH(r1, 1) @ r1<- field ref BBBB 2958 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2959 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2960 cmp r0, #0 @ is resolved entry null? 2961 beq .LOP_SPUT_resolve @ yes, do resolve 2962.LOP_SPUT_finish: @ field ptr in r0 2963 mov r2, rINST, lsr #8 @ r2<- AA 2964 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2965 GET_VREG(r1, r2) @ r1<- fp[AA] 2966 GET_INST_OPCODE(ip) @ extract opcode from rINST 2967 @ no-op @ releasing store 2968 str r1, [r0, #offStaticField_value] @ field<- vAA 2969 GOTO_OPCODE(ip) @ jump to next instruction 2970 2971/* ------------------------------ */ 2972 .balign 64 2973.L_OP_SPUT_WIDE: /* 0x68 */ 2974/* File: armv5te/OP_SPUT_WIDE.S */ 2975 /* 2976 * 64-bit SPUT handler. 2977 */ 2978 /* sput-wide vAA, field@BBBB */ 2979 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 2980 FETCH(r1, 1) @ r1<- field ref BBBB 2981 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 2982 mov r9, rINST, lsr #8 @ r9<- AA 2983 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 2984 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2985 cmp r2, #0 @ is resolved entry null? 2986 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 2987.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9 2988 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2989 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 2990 GET_INST_OPCODE(r10) @ extract opcode from rINST 2991 .if 0 2992 add r2, r2, #offStaticField_value @ r2<- pointer to data 2993 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 2994 .else 2995 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 2996 .endif 2997 GOTO_OPCODE(r10) @ jump to next instruction 2998 2999/* ------------------------------ */ 3000 .balign 64 3001.L_OP_SPUT_OBJECT: /* 0x69 */ 3002/* File: armv5te/OP_SPUT_OBJECT.S */ 3003 /* 3004 * 32-bit SPUT handler for objects 3005 * 3006 * for: sput-object, sput-object-volatile 3007 */ 3008 /* op vAA, field@BBBB */ 3009 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3010 FETCH(r1, 1) @ r1<- field ref BBBB 3011 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3012 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3013 cmp r0, #0 @ is resolved entry null? 3014 bne .LOP_SPUT_OBJECT_finish @ no, continue 3015 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3016 EXPORT_PC() @ resolve() could throw, so export now 3017 ldr r0, [r9, #offMethod_clazz] @ r0<- method->clazz 3018 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 3019 cmp r0, #0 @ success? 3020 bne .LOP_SPUT_OBJECT_finish @ yes, finish 3021 b common_exceptionThrown @ no, handle exception 3022 3023 3024/* ------------------------------ */ 3025 .balign 64 3026.L_OP_SPUT_BOOLEAN: /* 0x6a */ 3027/* File: armv5te/OP_SPUT_BOOLEAN.S */ 3028/* File: armv5te/OP_SPUT.S */ 3029 /* 3030 * General 32-bit SPUT handler. 3031 * 3032 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3033 */ 3034 /* op vAA, field@BBBB */ 3035 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3036 FETCH(r1, 1) @ r1<- field ref BBBB 3037 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3038 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3039 cmp r0, #0 @ is resolved entry null? 3040 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 3041.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 3042 mov r2, rINST, lsr #8 @ r2<- AA 3043 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3044 GET_VREG(r1, r2) @ r1<- fp[AA] 3045 GET_INST_OPCODE(ip) @ extract opcode from rINST 3046 @ no-op @ releasing store 3047 str r1, [r0, #offStaticField_value] @ field<- vAA 3048 GOTO_OPCODE(ip) @ jump to next instruction 3049 3050 3051/* ------------------------------ */ 3052 .balign 64 3053.L_OP_SPUT_BYTE: /* 0x6b */ 3054/* File: armv5te/OP_SPUT_BYTE.S */ 3055/* File: armv5te/OP_SPUT.S */ 3056 /* 3057 * General 32-bit SPUT handler. 3058 * 3059 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3060 */ 3061 /* op vAA, field@BBBB */ 3062 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3063 FETCH(r1, 1) @ r1<- field ref BBBB 3064 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3065 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3066 cmp r0, #0 @ is resolved entry null? 3067 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 3068.LOP_SPUT_BYTE_finish: @ field ptr in r0 3069 mov r2, rINST, lsr #8 @ r2<- AA 3070 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3071 GET_VREG(r1, r2) @ r1<- fp[AA] 3072 GET_INST_OPCODE(ip) @ extract opcode from rINST 3073 @ no-op @ releasing store 3074 str r1, [r0, #offStaticField_value] @ field<- vAA 3075 GOTO_OPCODE(ip) @ jump to next instruction 3076 3077 3078/* ------------------------------ */ 3079 .balign 64 3080.L_OP_SPUT_CHAR: /* 0x6c */ 3081/* File: armv5te/OP_SPUT_CHAR.S */ 3082/* File: armv5te/OP_SPUT.S */ 3083 /* 3084 * General 32-bit SPUT handler. 3085 * 3086 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3087 */ 3088 /* op vAA, field@BBBB */ 3089 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3090 FETCH(r1, 1) @ r1<- field ref BBBB 3091 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3092 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3093 cmp r0, #0 @ is resolved entry null? 3094 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 3095.LOP_SPUT_CHAR_finish: @ field ptr in r0 3096 mov r2, rINST, lsr #8 @ r2<- AA 3097 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3098 GET_VREG(r1, r2) @ r1<- fp[AA] 3099 GET_INST_OPCODE(ip) @ extract opcode from rINST 3100 @ no-op @ releasing store 3101 str r1, [r0, #offStaticField_value] @ field<- vAA 3102 GOTO_OPCODE(ip) @ jump to next instruction 3103 3104 3105/* ------------------------------ */ 3106 .balign 64 3107.L_OP_SPUT_SHORT: /* 0x6d */ 3108/* File: armv5te/OP_SPUT_SHORT.S */ 3109/* File: armv5te/OP_SPUT.S */ 3110 /* 3111 * General 32-bit SPUT handler. 3112 * 3113 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3114 */ 3115 /* op vAA, field@BBBB */ 3116 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3117 FETCH(r1, 1) @ r1<- field ref BBBB 3118 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3119 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3120 cmp r0, #0 @ is resolved entry null? 3121 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 3122.LOP_SPUT_SHORT_finish: @ field ptr in r0 3123 mov r2, rINST, lsr #8 @ r2<- AA 3124 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3125 GET_VREG(r1, r2) @ r1<- fp[AA] 3126 GET_INST_OPCODE(ip) @ extract opcode from rINST 3127 @ no-op @ releasing store 3128 str r1, [r0, #offStaticField_value] @ field<- vAA 3129 GOTO_OPCODE(ip) @ jump to next instruction 3130 3131 3132/* ------------------------------ */ 3133 .balign 64 3134.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3135/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3136 /* 3137 * Handle a virtual method call. 3138 * 3139 * for: invoke-virtual, invoke-virtual/range 3140 */ 3141 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3142 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3143 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3144 FETCH(r1, 1) @ r1<- BBBB 3145 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3146 FETCH(r10, 2) @ r10<- GFED or CCCC 3147 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3148 .if (!0) 3149 and r10, r10, #15 @ r10<- D (or stays CCCC) 3150 .endif 3151 cmp r0, #0 @ already resolved? 3152 EXPORT_PC() @ must export for invoke 3153 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3154 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3155 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3156 mov r2, #METHOD_VIRTUAL @ resolver method type 3157 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3158 cmp r0, #0 @ got null? 3159 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3160 b common_exceptionThrown @ yes, handle exception 3161 3162/* ------------------------------ */ 3163 .balign 64 3164.L_OP_INVOKE_SUPER: /* 0x6f */ 3165/* File: armv5te/OP_INVOKE_SUPER.S */ 3166 /* 3167 * Handle a "super" method call. 3168 * 3169 * for: invoke-super, invoke-super/range 3170 */ 3171 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3172 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3173 FETCH(r10, 2) @ r10<- GFED or CCCC 3174 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3175 .if (!0) 3176 and r10, r10, #15 @ r10<- D (or stays CCCC) 3177 .endif 3178 FETCH(r1, 1) @ r1<- BBBB 3179 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3180 GET_VREG(r2, r10) @ r2<- "this" ptr 3181 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3182 cmp r2, #0 @ null "this"? 3183 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3184 beq common_errNullObject @ null "this", throw exception 3185 cmp r0, #0 @ already resolved? 3186 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3187 EXPORT_PC() @ must export for invoke 3188 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3189 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3190 3191/* ------------------------------ */ 3192 .balign 64 3193.L_OP_INVOKE_DIRECT: /* 0x70 */ 3194/* File: armv5te/OP_INVOKE_DIRECT.S */ 3195 /* 3196 * Handle a direct method call. 3197 * 3198 * (We could defer the "is 'this' pointer null" test to the common 3199 * method invocation code, and use a flag to indicate that static 3200 * calls don't count. If we do this as part of copying the arguments 3201 * out we could avoiding loading the first arg twice.) 3202 * 3203 * for: invoke-direct, invoke-direct/range 3204 */ 3205 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3206 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3207 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3208 FETCH(r1, 1) @ r1<- BBBB 3209 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3210 FETCH(r10, 2) @ r10<- GFED or CCCC 3211 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3212 .if (!0) 3213 and r10, r10, #15 @ r10<- D (or stays CCCC) 3214 .endif 3215 cmp r0, #0 @ already resolved? 3216 EXPORT_PC() @ must export for invoke 3217 GET_VREG(r2, r10) @ r2<- "this" ptr 3218 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3219.LOP_INVOKE_DIRECT_finish: 3220 cmp r2, #0 @ null "this" ref? 3221 bne common_invokeMethodNoRange @ no, continue on 3222 b common_errNullObject @ yes, throw exception 3223 3224/* ------------------------------ */ 3225 .balign 64 3226.L_OP_INVOKE_STATIC: /* 0x71 */ 3227/* File: armv5te/OP_INVOKE_STATIC.S */ 3228 /* 3229 * Handle a static method call. 3230 * 3231 * for: invoke-static, invoke-static/range 3232 */ 3233 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3234 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3235 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3236 FETCH(r1, 1) @ r1<- BBBB 3237 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3238 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3239 cmp r0, #0 @ already resolved? 3240 EXPORT_PC() @ must export for invoke 3241 bne common_invokeMethodNoRange @ yes, continue on 32420: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3243 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3244 mov r2, #METHOD_STATIC @ resolver method type 3245 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3246 cmp r0, #0 @ got null? 3247 bne common_invokeMethodNoRange @ no, continue 3248 b common_exceptionThrown @ yes, handle exception 3249 3250/* ------------------------------ */ 3251 .balign 64 3252.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3253/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3254 /* 3255 * Handle an interface method call. 3256 * 3257 * for: invoke-interface, invoke-interface/range 3258 */ 3259 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3260 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3261 FETCH(r2, 2) @ r2<- FEDC or CCCC 3262 FETCH(r1, 1) @ r1<- BBBB 3263 .if (!0) 3264 and r2, r2, #15 @ r2<- C (or stays CCCC) 3265 .endif 3266 EXPORT_PC() @ must export for invoke 3267 GET_VREG(r0, r2) @ r0<- first arg ("this") 3268 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3269 cmp r0, #0 @ null obj? 3270 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3271 beq common_errNullObject @ yes, fail 3272 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3273 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3274 cmp r0, #0 @ failed? 3275 beq common_exceptionThrown @ yes, handle exception 3276 b common_invokeMethodNoRange @ jump to common handler 3277 3278/* ------------------------------ */ 3279 .balign 64 3280.L_OP_UNUSED_73: /* 0x73 */ 3281/* File: armv5te/OP_UNUSED_73.S */ 3282/* File: armv5te/unused.S */ 3283 bl common_abort 3284 3285 3286/* ------------------------------ */ 3287 .balign 64 3288.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3289/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3290/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3291 /* 3292 * Handle a virtual method call. 3293 * 3294 * for: invoke-virtual, invoke-virtual/range 3295 */ 3296 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3297 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3298 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3299 FETCH(r1, 1) @ r1<- BBBB 3300 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3301 FETCH(r10, 2) @ r10<- GFED or CCCC 3302 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3303 .if (!1) 3304 and r10, r10, #15 @ r10<- D (or stays CCCC) 3305 .endif 3306 cmp r0, #0 @ already resolved? 3307 EXPORT_PC() @ must export for invoke 3308 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3309 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3310 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3311 mov r2, #METHOD_VIRTUAL @ resolver method type 3312 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3313 cmp r0, #0 @ got null? 3314 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3315 b common_exceptionThrown @ yes, handle exception 3316 3317 3318/* ------------------------------ */ 3319 .balign 64 3320.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3321/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3322/* File: armv5te/OP_INVOKE_SUPER.S */ 3323 /* 3324 * Handle a "super" method call. 3325 * 3326 * for: invoke-super, invoke-super/range 3327 */ 3328 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3329 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3330 FETCH(r10, 2) @ r10<- GFED or CCCC 3331 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3332 .if (!1) 3333 and r10, r10, #15 @ r10<- D (or stays CCCC) 3334 .endif 3335 FETCH(r1, 1) @ r1<- BBBB 3336 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3337 GET_VREG(r2, r10) @ r2<- "this" ptr 3338 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3339 cmp r2, #0 @ null "this"? 3340 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3341 beq common_errNullObject @ null "this", throw exception 3342 cmp r0, #0 @ already resolved? 3343 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3344 EXPORT_PC() @ must export for invoke 3345 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3346 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3347 3348 3349/* ------------------------------ */ 3350 .balign 64 3351.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3352/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3353/* File: armv5te/OP_INVOKE_DIRECT.S */ 3354 /* 3355 * Handle a direct method call. 3356 * 3357 * (We could defer the "is 'this' pointer null" test to the common 3358 * method invocation code, and use a flag to indicate that static 3359 * calls don't count. If we do this as part of copying the arguments 3360 * out we could avoiding loading the first arg twice.) 3361 * 3362 * for: invoke-direct, invoke-direct/range 3363 */ 3364 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3365 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3366 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3367 FETCH(r1, 1) @ r1<- BBBB 3368 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3369 FETCH(r10, 2) @ r10<- GFED or CCCC 3370 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3371 .if (!1) 3372 and r10, r10, #15 @ r10<- D (or stays CCCC) 3373 .endif 3374 cmp r0, #0 @ already resolved? 3375 EXPORT_PC() @ must export for invoke 3376 GET_VREG(r2, r10) @ r2<- "this" ptr 3377 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3378.LOP_INVOKE_DIRECT_RANGE_finish: 3379 cmp r2, #0 @ null "this" ref? 3380 bne common_invokeMethodRange @ no, continue on 3381 b common_errNullObject @ yes, throw exception 3382 3383 3384/* ------------------------------ */ 3385 .balign 64 3386.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3387/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3388/* File: armv5te/OP_INVOKE_STATIC.S */ 3389 /* 3390 * Handle a static method call. 3391 * 3392 * for: invoke-static, invoke-static/range 3393 */ 3394 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3395 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3396 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3397 FETCH(r1, 1) @ r1<- BBBB 3398 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3399 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3400 cmp r0, #0 @ already resolved? 3401 EXPORT_PC() @ must export for invoke 3402 bne common_invokeMethodRange @ yes, continue on 34030: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3404 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3405 mov r2, #METHOD_STATIC @ resolver method type 3406 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3407 cmp r0, #0 @ got null? 3408 bne common_invokeMethodRange @ no, continue 3409 b common_exceptionThrown @ yes, handle exception 3410 3411 3412/* ------------------------------ */ 3413 .balign 64 3414.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3415/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3416/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3417 /* 3418 * Handle an interface method call. 3419 * 3420 * for: invoke-interface, invoke-interface/range 3421 */ 3422 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3423 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3424 FETCH(r2, 2) @ r2<- FEDC or CCCC 3425 FETCH(r1, 1) @ r1<- BBBB 3426 .if (!1) 3427 and r2, r2, #15 @ r2<- C (or stays CCCC) 3428 .endif 3429 EXPORT_PC() @ must export for invoke 3430 GET_VREG(r0, r2) @ r0<- first arg ("this") 3431 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3432 cmp r0, #0 @ null obj? 3433 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3434 beq common_errNullObject @ yes, fail 3435 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3436 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3437 cmp r0, #0 @ failed? 3438 beq common_exceptionThrown @ yes, handle exception 3439 b common_invokeMethodRange @ jump to common handler 3440 3441 3442/* ------------------------------ */ 3443 .balign 64 3444.L_OP_UNUSED_79: /* 0x79 */ 3445/* File: armv5te/OP_UNUSED_79.S */ 3446/* File: armv5te/unused.S */ 3447 bl common_abort 3448 3449 3450/* ------------------------------ */ 3451 .balign 64 3452.L_OP_UNUSED_7A: /* 0x7a */ 3453/* File: armv5te/OP_UNUSED_7A.S */ 3454/* File: armv5te/unused.S */ 3455 bl common_abort 3456 3457 3458/* ------------------------------ */ 3459 .balign 64 3460.L_OP_NEG_INT: /* 0x7b */ 3461/* File: armv5te/OP_NEG_INT.S */ 3462/* File: armv5te/unop.S */ 3463 /* 3464 * Generic 32-bit unary operation. Provide an "instr" line that 3465 * specifies an instruction that performs "result = op r0". 3466 * This could be an ARM instruction or a function call. 3467 * 3468 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3469 * int-to-byte, int-to-char, int-to-short 3470 */ 3471 /* unop vA, vB */ 3472 mov r3, rINST, lsr #12 @ r3<- B 3473 mov r9, rINST, lsr #8 @ r9<- A+ 3474 GET_VREG(r0, r3) @ r0<- vB 3475 and r9, r9, #15 3476 @ optional op; may set condition codes 3477 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3478 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3479 GET_INST_OPCODE(ip) @ extract opcode from rINST 3480 SET_VREG(r0, r9) @ vAA<- r0 3481 GOTO_OPCODE(ip) @ jump to next instruction 3482 /* 9-10 instructions */ 3483 3484 3485/* ------------------------------ */ 3486 .balign 64 3487.L_OP_NOT_INT: /* 0x7c */ 3488/* File: armv5te/OP_NOT_INT.S */ 3489/* File: armv5te/unop.S */ 3490 /* 3491 * Generic 32-bit unary operation. Provide an "instr" line that 3492 * specifies an instruction that performs "result = op r0". 3493 * This could be an ARM instruction or a function call. 3494 * 3495 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3496 * int-to-byte, int-to-char, int-to-short 3497 */ 3498 /* unop vA, vB */ 3499 mov r3, rINST, lsr #12 @ r3<- B 3500 mov r9, rINST, lsr #8 @ r9<- A+ 3501 GET_VREG(r0, r3) @ r0<- vB 3502 and r9, r9, #15 3503 @ optional op; may set condition codes 3504 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3505 mvn r0, r0 @ r0<- op, r0-r3 changed 3506 GET_INST_OPCODE(ip) @ extract opcode from rINST 3507 SET_VREG(r0, r9) @ vAA<- r0 3508 GOTO_OPCODE(ip) @ jump to next instruction 3509 /* 9-10 instructions */ 3510 3511 3512/* ------------------------------ */ 3513 .balign 64 3514.L_OP_NEG_LONG: /* 0x7d */ 3515/* File: armv5te/OP_NEG_LONG.S */ 3516/* File: armv5te/unopWide.S */ 3517 /* 3518 * Generic 64-bit unary operation. Provide an "instr" line that 3519 * specifies an instruction that performs "result = op r0/r1". 3520 * This could be an ARM instruction or a function call. 3521 * 3522 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3523 */ 3524 /* unop vA, vB */ 3525 mov r9, rINST, lsr #8 @ r9<- A+ 3526 mov r3, rINST, lsr #12 @ r3<- B 3527 and r9, r9, #15 3528 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3529 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3530 ldmia r3, {r0-r1} @ r0/r1<- vAA 3531 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3532 rsbs r0, r0, #0 @ optional op; may set condition codes 3533 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3534 GET_INST_OPCODE(ip) @ extract opcode from rINST 3535 stmia r9, {r0-r1} @ vAA<- r0/r1 3536 GOTO_OPCODE(ip) @ jump to next instruction 3537 /* 12-13 instructions */ 3538 3539 3540/* ------------------------------ */ 3541 .balign 64 3542.L_OP_NOT_LONG: /* 0x7e */ 3543/* File: armv5te/OP_NOT_LONG.S */ 3544/* File: armv5te/unopWide.S */ 3545 /* 3546 * Generic 64-bit unary operation. Provide an "instr" line that 3547 * specifies an instruction that performs "result = op r0/r1". 3548 * This could be an ARM instruction or a function call. 3549 * 3550 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3551 */ 3552 /* unop vA, vB */ 3553 mov r9, rINST, lsr #8 @ r9<- A+ 3554 mov r3, rINST, lsr #12 @ r3<- B 3555 and r9, r9, #15 3556 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3557 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3558 ldmia r3, {r0-r1} @ r0/r1<- vAA 3559 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3560 mvn r0, r0 @ optional op; may set condition codes 3561 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3562 GET_INST_OPCODE(ip) @ extract opcode from rINST 3563 stmia r9, {r0-r1} @ vAA<- r0/r1 3564 GOTO_OPCODE(ip) @ jump to next instruction 3565 /* 12-13 instructions */ 3566 3567 3568/* ------------------------------ */ 3569 .balign 64 3570.L_OP_NEG_FLOAT: /* 0x7f */ 3571/* File: armv5te/OP_NEG_FLOAT.S */ 3572/* File: armv5te/unop.S */ 3573 /* 3574 * Generic 32-bit unary operation. Provide an "instr" line that 3575 * specifies an instruction that performs "result = op r0". 3576 * This could be an ARM instruction or a function call. 3577 * 3578 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3579 * int-to-byte, int-to-char, int-to-short 3580 */ 3581 /* unop vA, vB */ 3582 mov r3, rINST, lsr #12 @ r3<- B 3583 mov r9, rINST, lsr #8 @ r9<- A+ 3584 GET_VREG(r0, r3) @ r0<- vB 3585 and r9, r9, #15 3586 @ optional op; may set condition codes 3587 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3588 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3589 GET_INST_OPCODE(ip) @ extract opcode from rINST 3590 SET_VREG(r0, r9) @ vAA<- r0 3591 GOTO_OPCODE(ip) @ jump to next instruction 3592 /* 9-10 instructions */ 3593 3594 3595/* ------------------------------ */ 3596 .balign 64 3597.L_OP_NEG_DOUBLE: /* 0x80 */ 3598/* File: armv5te/OP_NEG_DOUBLE.S */ 3599/* File: armv5te/unopWide.S */ 3600 /* 3601 * Generic 64-bit unary operation. Provide an "instr" line that 3602 * specifies an instruction that performs "result = op r0/r1". 3603 * This could be an ARM instruction or a function call. 3604 * 3605 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3606 */ 3607 /* unop vA, vB */ 3608 mov r9, rINST, lsr #8 @ r9<- A+ 3609 mov r3, rINST, lsr #12 @ r3<- B 3610 and r9, r9, #15 3611 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3612 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3613 ldmia r3, {r0-r1} @ r0/r1<- vAA 3614 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3615 @ optional op; may set condition codes 3616 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3617 GET_INST_OPCODE(ip) @ extract opcode from rINST 3618 stmia r9, {r0-r1} @ vAA<- r0/r1 3619 GOTO_OPCODE(ip) @ jump to next instruction 3620 /* 12-13 instructions */ 3621 3622 3623/* ------------------------------ */ 3624 .balign 64 3625.L_OP_INT_TO_LONG: /* 0x81 */ 3626/* File: armv5te/OP_INT_TO_LONG.S */ 3627/* File: armv5te/unopWider.S */ 3628 /* 3629 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3630 * that specifies an instruction that performs "result = op r0", where 3631 * "result" is a 64-bit quantity in r0/r1. 3632 * 3633 * For: int-to-long, int-to-double, float-to-long, float-to-double 3634 */ 3635 /* unop vA, vB */ 3636 mov r9, rINST, lsr #8 @ r9<- A+ 3637 mov r3, rINST, lsr #12 @ r3<- B 3638 and r9, r9, #15 3639 GET_VREG(r0, r3) @ r0<- vB 3640 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3641 @ optional op; may set condition codes 3642 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3643 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3644 GET_INST_OPCODE(ip) @ extract opcode from rINST 3645 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3646 GOTO_OPCODE(ip) @ jump to next instruction 3647 /* 10-11 instructions */ 3648 3649 3650/* ------------------------------ */ 3651 .balign 64 3652.L_OP_INT_TO_FLOAT: /* 0x82 */ 3653/* File: arm-vfp/OP_INT_TO_FLOAT.S */ 3654/* File: arm-vfp/funop.S */ 3655 /* 3656 * Generic 32-bit unary floating-point operation. Provide an "instr" 3657 * line that specifies an instruction that performs "s1 = op s0". 3658 * 3659 * for: int-to-float, float-to-int 3660 */ 3661 /* unop vA, vB */ 3662 mov r3, rINST, lsr #12 @ r3<- B 3663 mov r9, rINST, lsr #8 @ r9<- A+ 3664 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3665 flds s0, [r3] @ s0<- vB 3666 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3667 and r9, r9, #15 @ r9<- A 3668 fsitos s1, s0 @ s1<- op 3669 GET_INST_OPCODE(ip) @ extract opcode from rINST 3670 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3671 fsts s1, [r9] @ vA<- s1 3672 GOTO_OPCODE(ip) @ jump to next instruction 3673 3674 3675/* ------------------------------ */ 3676 .balign 64 3677.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3678/* File: arm-vfp/OP_INT_TO_DOUBLE.S */ 3679/* File: arm-vfp/funopWider.S */ 3680 /* 3681 * Generic 32bit-to-64bit floating point unary operation. Provide an 3682 * "instr" line that specifies an instruction that performs "d0 = op s0". 3683 * 3684 * For: int-to-double, float-to-double 3685 */ 3686 /* unop vA, vB */ 3687 mov r3, rINST, lsr #12 @ r3<- B 3688 mov r9, rINST, lsr #8 @ r9<- A+ 3689 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3690 flds s0, [r3] @ s0<- vB 3691 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3692 and r9, r9, #15 @ r9<- A 3693 fsitod d0, s0 @ d0<- op 3694 GET_INST_OPCODE(ip) @ extract opcode from rINST 3695 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3696 fstd d0, [r9] @ vA<- d0 3697 GOTO_OPCODE(ip) @ jump to next instruction 3698 3699 3700/* ------------------------------ */ 3701 .balign 64 3702.L_OP_LONG_TO_INT: /* 0x84 */ 3703/* File: armv5te/OP_LONG_TO_INT.S */ 3704/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3705/* File: armv5te/OP_MOVE.S */ 3706 /* for move, move-object, long-to-int */ 3707 /* op vA, vB */ 3708 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3709 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3710 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3711 GET_VREG(r2, r1) @ r2<- fp[B] 3712 and r0, r0, #15 3713 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3714 SET_VREG(r2, r0) @ fp[A]<- r2 3715 GOTO_OPCODE(ip) @ execute next instruction 3716 3717 3718/* ------------------------------ */ 3719 .balign 64 3720.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3721/* File: armv5te/OP_LONG_TO_FLOAT.S */ 3722/* File: armv5te/unopNarrower.S */ 3723 /* 3724 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3725 * that specifies an instruction that performs "result = op r0/r1", where 3726 * "result" is a 32-bit quantity in r0. 3727 * 3728 * For: long-to-float, double-to-int, double-to-float 3729 * 3730 * (This would work for long-to-int, but that instruction is actually 3731 * an exact match for OP_MOVE.) 3732 */ 3733 /* unop vA, vB */ 3734 mov r3, rINST, lsr #12 @ r3<- B 3735 mov r9, rINST, lsr #8 @ r9<- A+ 3736 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3737 and r9, r9, #15 3738 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3739 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3740 @ optional op; may set condition codes 3741 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3742 GET_INST_OPCODE(ip) @ extract opcode from rINST 3743 SET_VREG(r0, r9) @ vA<- r0 3744 GOTO_OPCODE(ip) @ jump to next instruction 3745 /* 10-11 instructions */ 3746 3747 3748/* ------------------------------ */ 3749 .balign 64 3750.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3751/* File: armv5te/OP_LONG_TO_DOUBLE.S */ 3752/* File: armv5te/unopWide.S */ 3753 /* 3754 * Generic 64-bit unary operation. Provide an "instr" line that 3755 * specifies an instruction that performs "result = op r0/r1". 3756 * This could be an ARM instruction or a function call. 3757 * 3758 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3759 */ 3760 /* unop vA, vB */ 3761 mov r9, rINST, lsr #8 @ r9<- A+ 3762 mov r3, rINST, lsr #12 @ r3<- B 3763 and r9, r9, #15 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 /* 12-13 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: armv5te/OP_FLOAT_TO_LONG.S */ 3805@include "armv5te/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3806/* File: armv5te/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 r9, rINST, lsr #8 @ r9<- A+ 3816 mov r3, rINST, lsr #12 @ r3<- B 3817 and r9, r9, #15 3818 GET_VREG(r0, r3) @ r0<- vB 3819 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3820 @ optional op; may set condition codes 3821 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3822 bl f2l_doconv @ r0<- op, r0-r3 changed 3823 GET_INST_OPCODE(ip) @ extract opcode from rINST 3824 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3825 GOTO_OPCODE(ip) @ jump to next instruction 3826 /* 10-11 instructions */ 3827 3828 3829 3830/* ------------------------------ */ 3831 .balign 64 3832.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3833/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */ 3834/* File: arm-vfp/funopWider.S */ 3835 /* 3836 * Generic 32bit-to-64bit floating point unary operation. Provide an 3837 * "instr" line that specifies an instruction that performs "d0 = op s0". 3838 * 3839 * For: int-to-double, float-to-double 3840 */ 3841 /* unop vA, vB */ 3842 mov r3, rINST, lsr #12 @ r3<- B 3843 mov r9, rINST, lsr #8 @ r9<- A+ 3844 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3845 flds s0, [r3] @ s0<- vB 3846 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3847 and r9, r9, #15 @ r9<- A 3848 fcvtds d0, s0 @ d0<- op 3849 GET_INST_OPCODE(ip) @ extract opcode from rINST 3850 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3851 fstd d0, [r9] @ vA<- d0 3852 GOTO_OPCODE(ip) @ jump to next instruction 3853 3854 3855/* ------------------------------ */ 3856 .balign 64 3857.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3858/* File: arm-vfp/OP_DOUBLE_TO_INT.S */ 3859/* File: arm-vfp/funopNarrower.S */ 3860 /* 3861 * Generic 64bit-to-32bit unary floating point operation. Provide an 3862 * "instr" line that specifies an instruction that performs "s0 = op d0". 3863 * 3864 * For: double-to-int, double-to-float 3865 */ 3866 /* unop vA, vB */ 3867 mov r3, rINST, lsr #12 @ r3<- B 3868 mov r9, rINST, lsr #8 @ r9<- A+ 3869 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3870 fldd d0, [r3] @ d0<- vB 3871 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3872 and r9, r9, #15 @ r9<- A 3873 ftosizd s0, d0 @ s0<- op 3874 GET_INST_OPCODE(ip) @ extract opcode from rINST 3875 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3876 fsts s0, [r9] @ vA<- s0 3877 GOTO_OPCODE(ip) @ jump to next instruction 3878 3879 3880/* ------------------------------ */ 3881 .balign 64 3882.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3883/* File: armv5te/OP_DOUBLE_TO_LONG.S */ 3884@include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"} 3885/* File: armv5te/unopWide.S */ 3886 /* 3887 * Generic 64-bit unary operation. Provide an "instr" line that 3888 * specifies an instruction that performs "result = op r0/r1". 3889 * This could be an ARM instruction or a function call. 3890 * 3891 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3892 */ 3893 /* unop vA, vB */ 3894 mov r9, rINST, lsr #8 @ r9<- A+ 3895 mov r3, rINST, lsr #12 @ r3<- B 3896 and r9, r9, #15 3897 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3898 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3899 ldmia r3, {r0-r1} @ r0/r1<- vAA 3900 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3901 @ optional op; may set condition codes 3902 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 3903 GET_INST_OPCODE(ip) @ extract opcode from rINST 3904 stmia r9, {r0-r1} @ vAA<- r0/r1 3905 GOTO_OPCODE(ip) @ jump to next instruction 3906 /* 12-13 instructions */ 3907 3908 3909 3910/* ------------------------------ */ 3911 .balign 64 3912.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3913/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */ 3914/* File: arm-vfp/funopNarrower.S */ 3915 /* 3916 * Generic 64bit-to-32bit unary floating point operation. Provide an 3917 * "instr" line that specifies an instruction that performs "s0 = op d0". 3918 * 3919 * For: double-to-int, double-to-float 3920 */ 3921 /* unop vA, vB */ 3922 mov r3, rINST, lsr #12 @ r3<- B 3923 mov r9, rINST, lsr #8 @ r9<- A+ 3924 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3925 fldd d0, [r3] @ d0<- vB 3926 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3927 and r9, r9, #15 @ r9<- A 3928 fcvtsd s0, d0 @ s0<- op 3929 GET_INST_OPCODE(ip) @ extract opcode from rINST 3930 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3931 fsts s0, [r9] @ vA<- s0 3932 GOTO_OPCODE(ip) @ jump to next instruction 3933 3934 3935/* ------------------------------ */ 3936 .balign 64 3937.L_OP_INT_TO_BYTE: /* 0x8d */ 3938/* File: armv5te/OP_INT_TO_BYTE.S */ 3939/* File: armv5te/unop.S */ 3940 /* 3941 * Generic 32-bit unary operation. Provide an "instr" line that 3942 * specifies an instruction that performs "result = op r0". 3943 * This could be an ARM instruction or a function call. 3944 * 3945 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3946 * int-to-byte, int-to-char, int-to-short 3947 */ 3948 /* unop vA, vB */ 3949 mov r3, rINST, lsr #12 @ r3<- B 3950 mov r9, rINST, lsr #8 @ r9<- A+ 3951 GET_VREG(r0, r3) @ r0<- vB 3952 and r9, r9, #15 3953 mov r0, r0, asl #24 @ optional op; may set condition codes 3954 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3955 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed 3956 GET_INST_OPCODE(ip) @ extract opcode from rINST 3957 SET_VREG(r0, r9) @ vAA<- r0 3958 GOTO_OPCODE(ip) @ jump to next instruction 3959 /* 9-10 instructions */ 3960 3961 3962/* ------------------------------ */ 3963 .balign 64 3964.L_OP_INT_TO_CHAR: /* 0x8e */ 3965/* File: armv5te/OP_INT_TO_CHAR.S */ 3966/* File: armv5te/unop.S */ 3967 /* 3968 * Generic 32-bit unary operation. Provide an "instr" line that 3969 * specifies an instruction that performs "result = op r0". 3970 * This could be an ARM instruction or a function call. 3971 * 3972 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3973 * int-to-byte, int-to-char, int-to-short 3974 */ 3975 /* unop vA, vB */ 3976 mov r3, rINST, lsr #12 @ r3<- B 3977 mov r9, rINST, lsr #8 @ r9<- A+ 3978 GET_VREG(r0, r3) @ r0<- vB 3979 and r9, r9, #15 3980 mov r0, r0, asl #16 @ optional op; may set condition codes 3981 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3982 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed 3983 GET_INST_OPCODE(ip) @ extract opcode from rINST 3984 SET_VREG(r0, r9) @ vAA<- r0 3985 GOTO_OPCODE(ip) @ jump to next instruction 3986 /* 9-10 instructions */ 3987 3988 3989/* ------------------------------ */ 3990 .balign 64 3991.L_OP_INT_TO_SHORT: /* 0x8f */ 3992/* File: armv5te/OP_INT_TO_SHORT.S */ 3993/* File: armv5te/unop.S */ 3994 /* 3995 * Generic 32-bit unary operation. Provide an "instr" line that 3996 * specifies an instruction that performs "result = op r0". 3997 * This could be an ARM instruction or a function call. 3998 * 3999 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4000 * int-to-byte, int-to-char, int-to-short 4001 */ 4002 /* unop vA, vB */ 4003 mov r3, rINST, lsr #12 @ r3<- B 4004 mov r9, rINST, lsr #8 @ r9<- A+ 4005 GET_VREG(r0, r3) @ r0<- vB 4006 and r9, r9, #15 4007 mov r0, r0, asl #16 @ optional op; may set condition codes 4008 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4009 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed 4010 GET_INST_OPCODE(ip) @ extract opcode from rINST 4011 SET_VREG(r0, r9) @ vAA<- r0 4012 GOTO_OPCODE(ip) @ jump to next instruction 4013 /* 9-10 instructions */ 4014 4015 4016/* ------------------------------ */ 4017 .balign 64 4018.L_OP_ADD_INT: /* 0x90 */ 4019/* File: armv5te/OP_ADD_INT.S */ 4020/* File: armv5te/binop.S */ 4021 /* 4022 * Generic 32-bit binary operation. Provide an "instr" line that 4023 * specifies an instruction that performs "result = r0 op r1". 4024 * This could be an ARM instruction or a function call. (If the result 4025 * comes back in a register other than r0, you can override "result".) 4026 * 4027 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4028 * vCC (r1). Useful for integer division and modulus. Note that we 4029 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4030 * handles it correctly. 4031 * 4032 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4033 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4034 * mul-float, div-float, rem-float 4035 */ 4036 /* binop vAA, vBB, vCC */ 4037 FETCH(r0, 1) @ r0<- CCBB 4038 mov r9, rINST, lsr #8 @ r9<- AA 4039 mov r3, r0, lsr #8 @ r3<- CC 4040 and r2, r0, #255 @ r2<- BB 4041 GET_VREG(r1, r3) @ r1<- vCC 4042 GET_VREG(r0, r2) @ r0<- vBB 4043 .if 0 4044 cmp r1, #0 @ is second operand zero? 4045 beq common_errDivideByZero 4046 .endif 4047 4048 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4049 @ optional op; may set condition codes 4050 add r0, r0, r1 @ r0<- op, r0-r3 changed 4051 GET_INST_OPCODE(ip) @ extract opcode from rINST 4052 SET_VREG(r0, r9) @ vAA<- r0 4053 GOTO_OPCODE(ip) @ jump to next instruction 4054 /* 11-14 instructions */ 4055 4056 4057/* ------------------------------ */ 4058 .balign 64 4059.L_OP_SUB_INT: /* 0x91 */ 4060/* File: armv5te/OP_SUB_INT.S */ 4061/* File: armv5te/binop.S */ 4062 /* 4063 * Generic 32-bit binary operation. Provide an "instr" line that 4064 * specifies an instruction that performs "result = r0 op r1". 4065 * This could be an ARM instruction or a function call. (If the result 4066 * comes back in a register other than r0, you can override "result".) 4067 * 4068 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4069 * vCC (r1). Useful for integer division and modulus. Note that we 4070 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4071 * handles it correctly. 4072 * 4073 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4074 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4075 * mul-float, div-float, rem-float 4076 */ 4077 /* binop vAA, vBB, vCC */ 4078 FETCH(r0, 1) @ r0<- CCBB 4079 mov r9, rINST, lsr #8 @ r9<- AA 4080 mov r3, r0, lsr #8 @ r3<- CC 4081 and r2, r0, #255 @ r2<- BB 4082 GET_VREG(r1, r3) @ r1<- vCC 4083 GET_VREG(r0, r2) @ r0<- vBB 4084 .if 0 4085 cmp r1, #0 @ is second operand zero? 4086 beq common_errDivideByZero 4087 .endif 4088 4089 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4090 @ optional op; may set condition codes 4091 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4092 GET_INST_OPCODE(ip) @ extract opcode from rINST 4093 SET_VREG(r0, r9) @ vAA<- r0 4094 GOTO_OPCODE(ip) @ jump to next instruction 4095 /* 11-14 instructions */ 4096 4097 4098/* ------------------------------ */ 4099 .balign 64 4100.L_OP_MUL_INT: /* 0x92 */ 4101/* File: armv5te/OP_MUL_INT.S */ 4102/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4103/* File: armv5te/binop.S */ 4104 /* 4105 * Generic 32-bit binary operation. Provide an "instr" line that 4106 * specifies an instruction that performs "result = r0 op r1". 4107 * This could be an ARM instruction or a function call. (If the result 4108 * comes back in a register other than r0, you can override "result".) 4109 * 4110 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4111 * vCC (r1). Useful for integer division and modulus. Note that we 4112 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4113 * handles it correctly. 4114 * 4115 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4116 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4117 * mul-float, div-float, rem-float 4118 */ 4119 /* binop vAA, vBB, vCC */ 4120 FETCH(r0, 1) @ r0<- CCBB 4121 mov r9, rINST, lsr #8 @ r9<- AA 4122 mov r3, r0, lsr #8 @ r3<- CC 4123 and r2, r0, #255 @ r2<- BB 4124 GET_VREG(r1, r3) @ r1<- vCC 4125 GET_VREG(r0, r2) @ r0<- vBB 4126 .if 0 4127 cmp r1, #0 @ is second operand zero? 4128 beq common_errDivideByZero 4129 .endif 4130 4131 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4132 @ optional op; may set condition codes 4133 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4134 GET_INST_OPCODE(ip) @ extract opcode from rINST 4135 SET_VREG(r0, r9) @ vAA<- r0 4136 GOTO_OPCODE(ip) @ jump to next instruction 4137 /* 11-14 instructions */ 4138 4139 4140/* ------------------------------ */ 4141 .balign 64 4142.L_OP_DIV_INT: /* 0x93 */ 4143/* File: armv5te/OP_DIV_INT.S */ 4144/* File: armv5te/binop.S */ 4145 /* 4146 * Generic 32-bit binary operation. Provide an "instr" line that 4147 * specifies an instruction that performs "result = r0 op r1". 4148 * This could be an ARM instruction or a function call. (If the result 4149 * comes back in a register other than r0, you can override "result".) 4150 * 4151 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4152 * vCC (r1). Useful for integer division and modulus. Note that we 4153 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4154 * handles it correctly. 4155 * 4156 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4157 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4158 * mul-float, div-float, rem-float 4159 */ 4160 /* binop vAA, vBB, vCC */ 4161 FETCH(r0, 1) @ r0<- CCBB 4162 mov r9, rINST, lsr #8 @ r9<- AA 4163 mov r3, r0, lsr #8 @ r3<- CC 4164 and r2, r0, #255 @ r2<- BB 4165 GET_VREG(r1, r3) @ r1<- vCC 4166 GET_VREG(r0, r2) @ r0<- vBB 4167 .if 1 4168 cmp r1, #0 @ is second operand zero? 4169 beq common_errDivideByZero 4170 .endif 4171 4172 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4173 @ optional op; may set condition codes 4174 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4175 GET_INST_OPCODE(ip) @ extract opcode from rINST 4176 SET_VREG(r0, r9) @ vAA<- r0 4177 GOTO_OPCODE(ip) @ jump to next instruction 4178 /* 11-14 instructions */ 4179 4180 4181/* ------------------------------ */ 4182 .balign 64 4183.L_OP_REM_INT: /* 0x94 */ 4184/* File: armv5te/OP_REM_INT.S */ 4185/* idivmod returns quotient in r0 and remainder in r1 */ 4186/* File: armv5te/binop.S */ 4187 /* 4188 * Generic 32-bit binary operation. Provide an "instr" line that 4189 * specifies an instruction that performs "result = r0 op r1". 4190 * This could be an ARM instruction or a function call. (If the result 4191 * comes back in a register other than r0, you can override "result".) 4192 * 4193 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4194 * vCC (r1). Useful for integer division and modulus. Note that we 4195 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4196 * handles it correctly. 4197 * 4198 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4199 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4200 * mul-float, div-float, rem-float 4201 */ 4202 /* binop vAA, vBB, vCC */ 4203 FETCH(r0, 1) @ r0<- CCBB 4204 mov r9, rINST, lsr #8 @ r9<- AA 4205 mov r3, r0, lsr #8 @ r3<- CC 4206 and r2, r0, #255 @ r2<- BB 4207 GET_VREG(r1, r3) @ r1<- vCC 4208 GET_VREG(r0, r2) @ r0<- vBB 4209 .if 1 4210 cmp r1, #0 @ is second operand zero? 4211 beq common_errDivideByZero 4212 .endif 4213 4214 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4215 @ optional op; may set condition codes 4216 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4217 GET_INST_OPCODE(ip) @ extract opcode from rINST 4218 SET_VREG(r1, r9) @ vAA<- r1 4219 GOTO_OPCODE(ip) @ jump to next instruction 4220 /* 11-14 instructions */ 4221 4222 4223/* ------------------------------ */ 4224 .balign 64 4225.L_OP_AND_INT: /* 0x95 */ 4226/* File: armv5te/OP_AND_INT.S */ 4227/* File: armv5te/binop.S */ 4228 /* 4229 * Generic 32-bit binary operation. Provide an "instr" line that 4230 * specifies an instruction that performs "result = r0 op r1". 4231 * This could be an ARM instruction or a function call. (If the result 4232 * comes back in a register other than r0, you can override "result".) 4233 * 4234 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4235 * vCC (r1). Useful for integer division and modulus. Note that we 4236 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4237 * handles it correctly. 4238 * 4239 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4240 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4241 * mul-float, div-float, rem-float 4242 */ 4243 /* binop vAA, vBB, vCC */ 4244 FETCH(r0, 1) @ r0<- CCBB 4245 mov r9, rINST, lsr #8 @ r9<- AA 4246 mov r3, r0, lsr #8 @ r3<- CC 4247 and r2, r0, #255 @ r2<- BB 4248 GET_VREG(r1, r3) @ r1<- vCC 4249 GET_VREG(r0, r2) @ r0<- vBB 4250 .if 0 4251 cmp r1, #0 @ is second operand zero? 4252 beq common_errDivideByZero 4253 .endif 4254 4255 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4256 @ optional op; may set condition codes 4257 and r0, r0, r1 @ r0<- op, r0-r3 changed 4258 GET_INST_OPCODE(ip) @ extract opcode from rINST 4259 SET_VREG(r0, r9) @ vAA<- r0 4260 GOTO_OPCODE(ip) @ jump to next instruction 4261 /* 11-14 instructions */ 4262 4263 4264/* ------------------------------ */ 4265 .balign 64 4266.L_OP_OR_INT: /* 0x96 */ 4267/* File: armv5te/OP_OR_INT.S */ 4268/* File: armv5te/binop.S */ 4269 /* 4270 * Generic 32-bit binary operation. Provide an "instr" line that 4271 * specifies an instruction that performs "result = r0 op r1". 4272 * This could be an ARM instruction or a function call. (If the result 4273 * comes back in a register other than r0, you can override "result".) 4274 * 4275 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4276 * vCC (r1). Useful for integer division and modulus. Note that we 4277 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4278 * handles it correctly. 4279 * 4280 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4281 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4282 * mul-float, div-float, rem-float 4283 */ 4284 /* binop vAA, vBB, vCC */ 4285 FETCH(r0, 1) @ r0<- CCBB 4286 mov r9, rINST, lsr #8 @ r9<- AA 4287 mov r3, r0, lsr #8 @ r3<- CC 4288 and r2, r0, #255 @ r2<- BB 4289 GET_VREG(r1, r3) @ r1<- vCC 4290 GET_VREG(r0, r2) @ r0<- vBB 4291 .if 0 4292 cmp r1, #0 @ is second operand zero? 4293 beq common_errDivideByZero 4294 .endif 4295 4296 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4297 @ optional op; may set condition codes 4298 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4299 GET_INST_OPCODE(ip) @ extract opcode from rINST 4300 SET_VREG(r0, r9) @ vAA<- r0 4301 GOTO_OPCODE(ip) @ jump to next instruction 4302 /* 11-14 instructions */ 4303 4304 4305/* ------------------------------ */ 4306 .balign 64 4307.L_OP_XOR_INT: /* 0x97 */ 4308/* File: armv5te/OP_XOR_INT.S */ 4309/* File: armv5te/binop.S */ 4310 /* 4311 * Generic 32-bit binary operation. Provide an "instr" line that 4312 * specifies an instruction that performs "result = r0 op r1". 4313 * This could be an ARM instruction or a function call. (If the result 4314 * comes back in a register other than r0, you can override "result".) 4315 * 4316 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4317 * vCC (r1). Useful for integer division and modulus. Note that we 4318 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4319 * handles it correctly. 4320 * 4321 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4322 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4323 * mul-float, div-float, rem-float 4324 */ 4325 /* binop vAA, vBB, vCC */ 4326 FETCH(r0, 1) @ r0<- CCBB 4327 mov r9, rINST, lsr #8 @ r9<- AA 4328 mov r3, r0, lsr #8 @ r3<- CC 4329 and r2, r0, #255 @ r2<- BB 4330 GET_VREG(r1, r3) @ r1<- vCC 4331 GET_VREG(r0, r2) @ r0<- vBB 4332 .if 0 4333 cmp r1, #0 @ is second operand zero? 4334 beq common_errDivideByZero 4335 .endif 4336 4337 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4338 @ optional op; may set condition codes 4339 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4340 GET_INST_OPCODE(ip) @ extract opcode from rINST 4341 SET_VREG(r0, r9) @ vAA<- r0 4342 GOTO_OPCODE(ip) @ jump to next instruction 4343 /* 11-14 instructions */ 4344 4345 4346/* ------------------------------ */ 4347 .balign 64 4348.L_OP_SHL_INT: /* 0x98 */ 4349/* File: armv5te/OP_SHL_INT.S */ 4350/* File: armv5te/binop.S */ 4351 /* 4352 * Generic 32-bit binary operation. Provide an "instr" line that 4353 * specifies an instruction that performs "result = r0 op r1". 4354 * This could be an ARM instruction or a function call. (If the result 4355 * comes back in a register other than r0, you can override "result".) 4356 * 4357 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4358 * vCC (r1). Useful for integer division and modulus. Note that we 4359 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4360 * handles it correctly. 4361 * 4362 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4363 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4364 * mul-float, div-float, rem-float 4365 */ 4366 /* binop vAA, vBB, vCC */ 4367 FETCH(r0, 1) @ r0<- CCBB 4368 mov r9, rINST, lsr #8 @ r9<- AA 4369 mov r3, r0, lsr #8 @ r3<- CC 4370 and r2, r0, #255 @ r2<- BB 4371 GET_VREG(r1, r3) @ r1<- vCC 4372 GET_VREG(r0, r2) @ r0<- vBB 4373 .if 0 4374 cmp r1, #0 @ is second operand zero? 4375 beq common_errDivideByZero 4376 .endif 4377 4378 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4379 and r1, r1, #31 @ optional op; may set condition codes 4380 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4381 GET_INST_OPCODE(ip) @ extract opcode from rINST 4382 SET_VREG(r0, r9) @ vAA<- r0 4383 GOTO_OPCODE(ip) @ jump to next instruction 4384 /* 11-14 instructions */ 4385 4386 4387/* ------------------------------ */ 4388 .balign 64 4389.L_OP_SHR_INT: /* 0x99 */ 4390/* File: armv5te/OP_SHR_INT.S */ 4391/* File: armv5te/binop.S */ 4392 /* 4393 * Generic 32-bit binary operation. Provide an "instr" line that 4394 * specifies an instruction that performs "result = r0 op r1". 4395 * This could be an ARM instruction or a function call. (If the result 4396 * comes back in a register other than r0, you can override "result".) 4397 * 4398 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4399 * vCC (r1). Useful for integer division and modulus. Note that we 4400 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4401 * handles it correctly. 4402 * 4403 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4404 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4405 * mul-float, div-float, rem-float 4406 */ 4407 /* binop vAA, vBB, vCC */ 4408 FETCH(r0, 1) @ r0<- CCBB 4409 mov r9, rINST, lsr #8 @ r9<- AA 4410 mov r3, r0, lsr #8 @ r3<- CC 4411 and r2, r0, #255 @ r2<- BB 4412 GET_VREG(r1, r3) @ r1<- vCC 4413 GET_VREG(r0, r2) @ r0<- vBB 4414 .if 0 4415 cmp r1, #0 @ is second operand zero? 4416 beq common_errDivideByZero 4417 .endif 4418 4419 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4420 and r1, r1, #31 @ optional op; may set condition codes 4421 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4422 GET_INST_OPCODE(ip) @ extract opcode from rINST 4423 SET_VREG(r0, r9) @ vAA<- r0 4424 GOTO_OPCODE(ip) @ jump to next instruction 4425 /* 11-14 instructions */ 4426 4427 4428/* ------------------------------ */ 4429 .balign 64 4430.L_OP_USHR_INT: /* 0x9a */ 4431/* File: armv5te/OP_USHR_INT.S */ 4432/* File: armv5te/binop.S */ 4433 /* 4434 * Generic 32-bit binary operation. Provide an "instr" line that 4435 * specifies an instruction that performs "result = r0 op r1". 4436 * This could be an ARM instruction or a function call. (If the result 4437 * comes back in a register other than r0, you can override "result".) 4438 * 4439 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4440 * vCC (r1). Useful for integer division and modulus. Note that we 4441 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4442 * handles it correctly. 4443 * 4444 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4445 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4446 * mul-float, div-float, rem-float 4447 */ 4448 /* binop vAA, vBB, vCC */ 4449 FETCH(r0, 1) @ r0<- CCBB 4450 mov r9, rINST, lsr #8 @ r9<- AA 4451 mov r3, r0, lsr #8 @ r3<- CC 4452 and r2, r0, #255 @ r2<- BB 4453 GET_VREG(r1, r3) @ r1<- vCC 4454 GET_VREG(r0, r2) @ r0<- vBB 4455 .if 0 4456 cmp r1, #0 @ is second operand zero? 4457 beq common_errDivideByZero 4458 .endif 4459 4460 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4461 and r1, r1, #31 @ optional op; may set condition codes 4462 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4463 GET_INST_OPCODE(ip) @ extract opcode from rINST 4464 SET_VREG(r0, r9) @ vAA<- r0 4465 GOTO_OPCODE(ip) @ jump to next instruction 4466 /* 11-14 instructions */ 4467 4468 4469/* ------------------------------ */ 4470 .balign 64 4471.L_OP_ADD_LONG: /* 0x9b */ 4472/* File: armv5te/OP_ADD_LONG.S */ 4473/* File: armv5te/binopWide.S */ 4474 /* 4475 * Generic 64-bit binary operation. Provide an "instr" line that 4476 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4477 * This could be an ARM instruction or a function call. (If the result 4478 * comes back in a register other than r0, you can override "result".) 4479 * 4480 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4481 * vCC (r1). Useful for integer division and modulus. 4482 * 4483 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4484 * xor-long, add-double, sub-double, mul-double, div-double, 4485 * rem-double 4486 * 4487 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4488 */ 4489 /* binop vAA, vBB, vCC */ 4490 FETCH(r0, 1) @ r0<- CCBB 4491 mov r9, rINST, lsr #8 @ r9<- AA 4492 and r2, r0, #255 @ r2<- BB 4493 mov r3, r0, lsr #8 @ r3<- CC 4494 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4495 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4496 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4497 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4498 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4499 .if 0 4500 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4501 beq common_errDivideByZero 4502 .endif 4503 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4504 4505 adds r0, r0, r2 @ optional op; may set condition codes 4506 adc r1, r1, r3 @ result<- op, r0-r3 changed 4507 GET_INST_OPCODE(ip) @ extract opcode from rINST 4508 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4509 GOTO_OPCODE(ip) @ jump to next instruction 4510 /* 14-17 instructions */ 4511 4512 4513/* ------------------------------ */ 4514 .balign 64 4515.L_OP_SUB_LONG: /* 0x9c */ 4516/* File: armv5te/OP_SUB_LONG.S */ 4517/* File: armv5te/binopWide.S */ 4518 /* 4519 * Generic 64-bit binary operation. Provide an "instr" line that 4520 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4521 * This could be an ARM instruction or a function call. (If the result 4522 * comes back in a register other than r0, you can override "result".) 4523 * 4524 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4525 * vCC (r1). Useful for integer division and modulus. 4526 * 4527 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4528 * xor-long, add-double, sub-double, mul-double, div-double, 4529 * rem-double 4530 * 4531 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4532 */ 4533 /* binop vAA, vBB, vCC */ 4534 FETCH(r0, 1) @ r0<- CCBB 4535 mov r9, rINST, lsr #8 @ r9<- AA 4536 and r2, r0, #255 @ r2<- BB 4537 mov r3, r0, lsr #8 @ r3<- CC 4538 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4539 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4540 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4541 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4542 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4543 .if 0 4544 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4545 beq common_errDivideByZero 4546 .endif 4547 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4548 4549 subs r0, r0, r2 @ optional op; may set condition codes 4550 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4551 GET_INST_OPCODE(ip) @ extract opcode from rINST 4552 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4553 GOTO_OPCODE(ip) @ jump to next instruction 4554 /* 14-17 instructions */ 4555 4556 4557/* ------------------------------ */ 4558 .balign 64 4559.L_OP_MUL_LONG: /* 0x9d */ 4560/* File: armv5te/OP_MUL_LONG.S */ 4561 /* 4562 * Signed 64-bit integer multiply. 4563 * 4564 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4565 * WX 4566 * x YZ 4567 * -------- 4568 * ZW ZX 4569 * YW YX 4570 * 4571 * The low word of the result holds ZX, the high word holds 4572 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4573 * it doesn't fit in the low 64 bits. 4574 * 4575 * Unlike most ARM math operations, multiply instructions have 4576 * restrictions on using the same register more than once (Rd and Rm 4577 * cannot be the same). 4578 */ 4579 /* mul-long vAA, vBB, vCC */ 4580 FETCH(r0, 1) @ r0<- CCBB 4581 and r2, r0, #255 @ r2<- BB 4582 mov r3, r0, lsr #8 @ r3<- CC 4583 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4584 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4585 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4586 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4587 mul ip, r2, r1 @ ip<- ZxW 4588 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4589 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4590 mov r0, rINST, lsr #8 @ r0<- AA 4591 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4592 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4593 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4594 b .LOP_MUL_LONG_finish 4595 4596/* ------------------------------ */ 4597 .balign 64 4598.L_OP_DIV_LONG: /* 0x9e */ 4599/* File: armv5te/OP_DIV_LONG.S */ 4600/* File: armv5te/binopWide.S */ 4601 /* 4602 * Generic 64-bit binary operation. Provide an "instr" line that 4603 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4604 * This could be an ARM instruction or a function call. (If the result 4605 * comes back in a register other than r0, you can override "result".) 4606 * 4607 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4608 * vCC (r1). Useful for integer division and modulus. 4609 * 4610 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4611 * xor-long, add-double, sub-double, mul-double, div-double, 4612 * rem-double 4613 * 4614 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4615 */ 4616 /* binop vAA, vBB, vCC */ 4617 FETCH(r0, 1) @ r0<- CCBB 4618 mov r9, rINST, lsr #8 @ r9<- AA 4619 and r2, r0, #255 @ r2<- BB 4620 mov r3, r0, lsr #8 @ r3<- CC 4621 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4622 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4623 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4624 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4625 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4626 .if 1 4627 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4628 beq common_errDivideByZero 4629 .endif 4630 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4631 4632 @ optional op; may set condition codes 4633 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4634 GET_INST_OPCODE(ip) @ extract opcode from rINST 4635 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4636 GOTO_OPCODE(ip) @ jump to next instruction 4637 /* 14-17 instructions */ 4638 4639 4640/* ------------------------------ */ 4641 .balign 64 4642.L_OP_REM_LONG: /* 0x9f */ 4643/* File: armv5te/OP_REM_LONG.S */ 4644/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4645/* File: armv5te/binopWide.S */ 4646 /* 4647 * Generic 64-bit binary operation. Provide an "instr" line that 4648 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4649 * This could be an ARM instruction or a function call. (If the result 4650 * comes back in a register other than r0, you can override "result".) 4651 * 4652 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4653 * vCC (r1). Useful for integer division and modulus. 4654 * 4655 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4656 * xor-long, add-double, sub-double, mul-double, div-double, 4657 * rem-double 4658 * 4659 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4660 */ 4661 /* binop vAA, vBB, vCC */ 4662 FETCH(r0, 1) @ r0<- CCBB 4663 mov r9, rINST, lsr #8 @ r9<- AA 4664 and r2, r0, #255 @ r2<- BB 4665 mov r3, r0, lsr #8 @ r3<- CC 4666 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4667 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4668 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4669 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4670 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4671 .if 1 4672 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4673 beq common_errDivideByZero 4674 .endif 4675 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4676 4677 @ optional op; may set condition codes 4678 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4679 GET_INST_OPCODE(ip) @ extract opcode from rINST 4680 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4681 GOTO_OPCODE(ip) @ jump to next instruction 4682 /* 14-17 instructions */ 4683 4684 4685/* ------------------------------ */ 4686 .balign 64 4687.L_OP_AND_LONG: /* 0xa0 */ 4688/* File: armv5te/OP_AND_LONG.S */ 4689/* File: armv5te/binopWide.S */ 4690 /* 4691 * Generic 64-bit binary operation. Provide an "instr" line that 4692 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4693 * This could be an ARM instruction or a function call. (If the result 4694 * comes back in a register other than r0, you can override "result".) 4695 * 4696 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4697 * vCC (r1). Useful for integer division and modulus. 4698 * 4699 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4700 * xor-long, add-double, sub-double, mul-double, div-double, 4701 * rem-double 4702 * 4703 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4704 */ 4705 /* binop vAA, vBB, vCC */ 4706 FETCH(r0, 1) @ r0<- CCBB 4707 mov r9, rINST, lsr #8 @ r9<- AA 4708 and r2, r0, #255 @ r2<- BB 4709 mov r3, r0, lsr #8 @ r3<- CC 4710 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4711 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4712 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4713 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4714 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4715 .if 0 4716 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4717 beq common_errDivideByZero 4718 .endif 4719 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4720 4721 and r0, r0, r2 @ optional op; may set condition codes 4722 and r1, r1, r3 @ result<- op, r0-r3 changed 4723 GET_INST_OPCODE(ip) @ extract opcode from rINST 4724 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4725 GOTO_OPCODE(ip) @ jump to next instruction 4726 /* 14-17 instructions */ 4727 4728 4729/* ------------------------------ */ 4730 .balign 64 4731.L_OP_OR_LONG: /* 0xa1 */ 4732/* File: armv5te/OP_OR_LONG.S */ 4733/* File: armv5te/binopWide.S */ 4734 /* 4735 * Generic 64-bit binary operation. Provide an "instr" line that 4736 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4737 * This could be an ARM instruction or a function call. (If the result 4738 * comes back in a register other than r0, you can override "result".) 4739 * 4740 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4741 * vCC (r1). Useful for integer division and modulus. 4742 * 4743 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4744 * xor-long, add-double, sub-double, mul-double, div-double, 4745 * rem-double 4746 * 4747 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4748 */ 4749 /* binop vAA, vBB, vCC */ 4750 FETCH(r0, 1) @ r0<- CCBB 4751 mov r9, rINST, lsr #8 @ r9<- AA 4752 and r2, r0, #255 @ r2<- BB 4753 mov r3, r0, lsr #8 @ r3<- CC 4754 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4755 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4756 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4757 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4758 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4759 .if 0 4760 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4761 beq common_errDivideByZero 4762 .endif 4763 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4764 4765 orr r0, r0, r2 @ optional op; may set condition codes 4766 orr r1, r1, r3 @ result<- op, r0-r3 changed 4767 GET_INST_OPCODE(ip) @ extract opcode from rINST 4768 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4769 GOTO_OPCODE(ip) @ jump to next instruction 4770 /* 14-17 instructions */ 4771 4772 4773/* ------------------------------ */ 4774 .balign 64 4775.L_OP_XOR_LONG: /* 0xa2 */ 4776/* File: armv5te/OP_XOR_LONG.S */ 4777/* File: armv5te/binopWide.S */ 4778 /* 4779 * Generic 64-bit binary operation. Provide an "instr" line that 4780 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4781 * This could be an ARM instruction or a function call. (If the result 4782 * comes back in a register other than r0, you can override "result".) 4783 * 4784 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4785 * vCC (r1). Useful for integer division and modulus. 4786 * 4787 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4788 * xor-long, add-double, sub-double, mul-double, div-double, 4789 * rem-double 4790 * 4791 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4792 */ 4793 /* binop vAA, vBB, vCC */ 4794 FETCH(r0, 1) @ r0<- CCBB 4795 mov r9, rINST, lsr #8 @ r9<- AA 4796 and r2, r0, #255 @ r2<- BB 4797 mov r3, r0, lsr #8 @ r3<- CC 4798 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4799 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4800 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4801 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4802 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4803 .if 0 4804 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4805 beq common_errDivideByZero 4806 .endif 4807 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4808 4809 eor r0, r0, r2 @ optional op; may set condition codes 4810 eor r1, r1, r3 @ result<- op, r0-r3 changed 4811 GET_INST_OPCODE(ip) @ extract opcode from rINST 4812 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4813 GOTO_OPCODE(ip) @ jump to next instruction 4814 /* 14-17 instructions */ 4815 4816 4817/* ------------------------------ */ 4818 .balign 64 4819.L_OP_SHL_LONG: /* 0xa3 */ 4820/* File: armv5te/OP_SHL_LONG.S */ 4821 /* 4822 * Long integer shift. This is different from the generic 32/64-bit 4823 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4824 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4825 * 6 bits of the shift distance. 4826 */ 4827 /* shl-long vAA, vBB, vCC */ 4828 FETCH(r0, 1) @ r0<- CCBB 4829 mov r9, rINST, lsr #8 @ r9<- AA 4830 and r3, r0, #255 @ r3<- BB 4831 mov r0, r0, lsr #8 @ r0<- CC 4832 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4833 GET_VREG(r2, r0) @ r2<- vCC 4834 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4835 and r2, r2, #63 @ r2<- r2 & 0x3f 4836 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4837 4838 mov r1, r1, asl r2 @ r1<- r1 << r2 4839 rsb r3, r2, #32 @ r3<- 32 - r2 4840 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 4841 subs ip, r2, #32 @ ip<- r2 - 32 4842 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 4843 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4844 b .LOP_SHL_LONG_finish 4845 4846/* ------------------------------ */ 4847 .balign 64 4848.L_OP_SHR_LONG: /* 0xa4 */ 4849/* File: armv5te/OP_SHR_LONG.S */ 4850 /* 4851 * Long integer shift. This is different from the generic 32/64-bit 4852 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4853 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4854 * 6 bits of the shift distance. 4855 */ 4856 /* shr-long vAA, vBB, vCC */ 4857 FETCH(r0, 1) @ r0<- CCBB 4858 mov r9, rINST, lsr #8 @ r9<- AA 4859 and r3, r0, #255 @ r3<- BB 4860 mov r0, r0, lsr #8 @ r0<- CC 4861 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4862 GET_VREG(r2, r0) @ r2<- vCC 4863 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4864 and r2, r2, #63 @ r0<- r0 & 0x3f 4865 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4866 4867 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4868 rsb r3, r2, #32 @ r3<- 32 - r2 4869 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4870 subs ip, r2, #32 @ ip<- r2 - 32 4871 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 4872 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4873 b .LOP_SHR_LONG_finish 4874 4875/* ------------------------------ */ 4876 .balign 64 4877.L_OP_USHR_LONG: /* 0xa5 */ 4878/* File: armv5te/OP_USHR_LONG.S */ 4879 /* 4880 * Long integer shift. This is different from the generic 32/64-bit 4881 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4882 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4883 * 6 bits of the shift distance. 4884 */ 4885 /* ushr-long vAA, vBB, vCC */ 4886 FETCH(r0, 1) @ r0<- CCBB 4887 mov r9, rINST, lsr #8 @ r9<- AA 4888 and r3, r0, #255 @ r3<- BB 4889 mov r0, r0, lsr #8 @ r0<- CC 4890 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4891 GET_VREG(r2, r0) @ r2<- vCC 4892 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4893 and r2, r2, #63 @ r0<- r0 & 0x3f 4894 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4895 4896 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4897 rsb r3, r2, #32 @ r3<- 32 - r2 4898 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4899 subs ip, r2, #32 @ ip<- r2 - 32 4900 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 4901 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4902 b .LOP_USHR_LONG_finish 4903 4904/* ------------------------------ */ 4905 .balign 64 4906.L_OP_ADD_FLOAT: /* 0xa6 */ 4907/* File: arm-vfp/OP_ADD_FLOAT.S */ 4908/* File: arm-vfp/fbinop.S */ 4909 /* 4910 * Generic 32-bit floating-point operation. Provide an "instr" line that 4911 * specifies an instruction that performs "s2 = s0 op s1". Because we 4912 * use the "softfp" ABI, this must be an instruction, not a function call. 4913 * 4914 * For: add-float, sub-float, mul-float, div-float 4915 */ 4916 /* floatop vAA, vBB, vCC */ 4917 FETCH(r0, 1) @ r0<- CCBB 4918 mov r9, rINST, lsr #8 @ r9<- AA 4919 mov r3, r0, lsr #8 @ r3<- CC 4920 and r2, r0, #255 @ r2<- BB 4921 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4922 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4923 flds s1, [r3] @ s1<- vCC 4924 flds s0, [r2] @ s0<- vBB 4925 4926 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4927 fadds s2, s0, s1 @ s2<- op 4928 GET_INST_OPCODE(ip) @ extract opcode from rINST 4929 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4930 fsts s2, [r9] @ vAA<- s2 4931 GOTO_OPCODE(ip) @ jump to next instruction 4932 4933 4934/* ------------------------------ */ 4935 .balign 64 4936.L_OP_SUB_FLOAT: /* 0xa7 */ 4937/* File: arm-vfp/OP_SUB_FLOAT.S */ 4938/* File: arm-vfp/fbinop.S */ 4939 /* 4940 * Generic 32-bit floating-point operation. Provide an "instr" line that 4941 * specifies an instruction that performs "s2 = s0 op s1". Because we 4942 * use the "softfp" ABI, this must be an instruction, not a function call. 4943 * 4944 * For: add-float, sub-float, mul-float, div-float 4945 */ 4946 /* floatop vAA, vBB, vCC */ 4947 FETCH(r0, 1) @ r0<- CCBB 4948 mov r9, rINST, lsr #8 @ r9<- AA 4949 mov r3, r0, lsr #8 @ r3<- CC 4950 and r2, r0, #255 @ r2<- BB 4951 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4952 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4953 flds s1, [r3] @ s1<- vCC 4954 flds s0, [r2] @ s0<- vBB 4955 4956 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4957 fsubs s2, s0, s1 @ s2<- op 4958 GET_INST_OPCODE(ip) @ extract opcode from rINST 4959 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4960 fsts s2, [r9] @ vAA<- s2 4961 GOTO_OPCODE(ip) @ jump to next instruction 4962 4963 4964/* ------------------------------ */ 4965 .balign 64 4966.L_OP_MUL_FLOAT: /* 0xa8 */ 4967/* File: arm-vfp/OP_MUL_FLOAT.S */ 4968/* File: arm-vfp/fbinop.S */ 4969 /* 4970 * Generic 32-bit floating-point operation. Provide an "instr" line that 4971 * specifies an instruction that performs "s2 = s0 op s1". Because we 4972 * use the "softfp" ABI, this must be an instruction, not a function call. 4973 * 4974 * For: add-float, sub-float, mul-float, div-float 4975 */ 4976 /* floatop vAA, vBB, vCC */ 4977 FETCH(r0, 1) @ r0<- CCBB 4978 mov r9, rINST, lsr #8 @ r9<- AA 4979 mov r3, r0, lsr #8 @ r3<- CC 4980 and r2, r0, #255 @ r2<- BB 4981 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4982 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4983 flds s1, [r3] @ s1<- vCC 4984 flds s0, [r2] @ s0<- vBB 4985 4986 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4987 fmuls s2, s0, s1 @ s2<- op 4988 GET_INST_OPCODE(ip) @ extract opcode from rINST 4989 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4990 fsts s2, [r9] @ vAA<- s2 4991 GOTO_OPCODE(ip) @ jump to next instruction 4992 4993 4994/* ------------------------------ */ 4995 .balign 64 4996.L_OP_DIV_FLOAT: /* 0xa9 */ 4997/* File: arm-vfp/OP_DIV_FLOAT.S */ 4998/* File: arm-vfp/fbinop.S */ 4999 /* 5000 * Generic 32-bit floating-point operation. Provide an "instr" line that 5001 * specifies an instruction that performs "s2 = s0 op s1". Because we 5002 * use the "softfp" ABI, this must be an instruction, not a function call. 5003 * 5004 * For: add-float, sub-float, mul-float, div-float 5005 */ 5006 /* floatop vAA, vBB, vCC */ 5007 FETCH(r0, 1) @ r0<- CCBB 5008 mov r9, rINST, lsr #8 @ r9<- AA 5009 mov r3, r0, lsr #8 @ r3<- CC 5010 and r2, r0, #255 @ r2<- BB 5011 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5012 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5013 flds s1, [r3] @ s1<- vCC 5014 flds s0, [r2] @ s0<- vBB 5015 5016 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5017 fdivs s2, s0, s1 @ s2<- op 5018 GET_INST_OPCODE(ip) @ extract opcode from rINST 5019 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5020 fsts s2, [r9] @ vAA<- s2 5021 GOTO_OPCODE(ip) @ jump to next instruction 5022 5023 5024/* ------------------------------ */ 5025 .balign 64 5026.L_OP_REM_FLOAT: /* 0xaa */ 5027/* File: armv5te/OP_REM_FLOAT.S */ 5028/* EABI doesn't define a float remainder function, but libm does */ 5029/* File: armv5te/binop.S */ 5030 /* 5031 * Generic 32-bit binary operation. Provide an "instr" line that 5032 * specifies an instruction that performs "result = r0 op r1". 5033 * This could be an ARM instruction or a function call. (If the result 5034 * comes back in a register other than r0, you can override "result".) 5035 * 5036 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5037 * vCC (r1). Useful for integer division and modulus. Note that we 5038 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5039 * handles it correctly. 5040 * 5041 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5042 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5043 * mul-float, div-float, rem-float 5044 */ 5045 /* binop vAA, vBB, vCC */ 5046 FETCH(r0, 1) @ r0<- CCBB 5047 mov r9, rINST, lsr #8 @ r9<- AA 5048 mov r3, r0, lsr #8 @ r3<- CC 5049 and r2, r0, #255 @ r2<- BB 5050 GET_VREG(r1, r3) @ r1<- vCC 5051 GET_VREG(r0, r2) @ r0<- vBB 5052 .if 0 5053 cmp r1, #0 @ is second operand zero? 5054 beq common_errDivideByZero 5055 .endif 5056 5057 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5058 @ optional op; may set condition codes 5059 bl fmodf @ r0<- op, r0-r3 changed 5060 GET_INST_OPCODE(ip) @ extract opcode from rINST 5061 SET_VREG(r0, r9) @ vAA<- r0 5062 GOTO_OPCODE(ip) @ jump to next instruction 5063 /* 11-14 instructions */ 5064 5065 5066/* ------------------------------ */ 5067 .balign 64 5068.L_OP_ADD_DOUBLE: /* 0xab */ 5069/* File: arm-vfp/OP_ADD_DOUBLE.S */ 5070/* File: arm-vfp/fbinopWide.S */ 5071 /* 5072 * Generic 64-bit double-precision floating point binary operation. 5073 * Provide an "instr" line that specifies an instruction that performs 5074 * "d2 = d0 op d1". 5075 * 5076 * for: add-double, sub-double, mul-double, div-double 5077 */ 5078 /* doubleop vAA, vBB, vCC */ 5079 FETCH(r0, 1) @ r0<- CCBB 5080 mov r9, rINST, lsr #8 @ r9<- AA 5081 mov r3, r0, lsr #8 @ r3<- CC 5082 and r2, r0, #255 @ r2<- BB 5083 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5084 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5085 fldd d1, [r3] @ d1<- vCC 5086 fldd d0, [r2] @ d0<- vBB 5087 5088 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5089 faddd d2, d0, d1 @ s2<- op 5090 GET_INST_OPCODE(ip) @ extract opcode from rINST 5091 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5092 fstd d2, [r9] @ vAA<- d2 5093 GOTO_OPCODE(ip) @ jump to next instruction 5094 5095 5096/* ------------------------------ */ 5097 .balign 64 5098.L_OP_SUB_DOUBLE: /* 0xac */ 5099/* File: arm-vfp/OP_SUB_DOUBLE.S */ 5100/* File: arm-vfp/fbinopWide.S */ 5101 /* 5102 * Generic 64-bit double-precision floating point binary operation. 5103 * Provide an "instr" line that specifies an instruction that performs 5104 * "d2 = d0 op d1". 5105 * 5106 * for: add-double, sub-double, mul-double, div-double 5107 */ 5108 /* doubleop vAA, vBB, vCC */ 5109 FETCH(r0, 1) @ r0<- CCBB 5110 mov r9, rINST, lsr #8 @ r9<- AA 5111 mov r3, r0, lsr #8 @ r3<- CC 5112 and r2, r0, #255 @ r2<- BB 5113 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5114 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5115 fldd d1, [r3] @ d1<- vCC 5116 fldd d0, [r2] @ d0<- vBB 5117 5118 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5119 fsubd d2, d0, d1 @ s2<- op 5120 GET_INST_OPCODE(ip) @ extract opcode from rINST 5121 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5122 fstd d2, [r9] @ vAA<- d2 5123 GOTO_OPCODE(ip) @ jump to next instruction 5124 5125 5126/* ------------------------------ */ 5127 .balign 64 5128.L_OP_MUL_DOUBLE: /* 0xad */ 5129/* File: arm-vfp/OP_MUL_DOUBLE.S */ 5130/* File: arm-vfp/fbinopWide.S */ 5131 /* 5132 * Generic 64-bit double-precision floating point binary operation. 5133 * Provide an "instr" line that specifies an instruction that performs 5134 * "d2 = d0 op d1". 5135 * 5136 * for: add-double, sub-double, mul-double, div-double 5137 */ 5138 /* doubleop vAA, vBB, vCC */ 5139 FETCH(r0, 1) @ r0<- CCBB 5140 mov r9, rINST, lsr #8 @ r9<- AA 5141 mov r3, r0, lsr #8 @ r3<- CC 5142 and r2, r0, #255 @ r2<- BB 5143 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5144 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5145 fldd d1, [r3] @ d1<- vCC 5146 fldd d0, [r2] @ d0<- vBB 5147 5148 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5149 fmuld d2, d0, d1 @ s2<- op 5150 GET_INST_OPCODE(ip) @ extract opcode from rINST 5151 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5152 fstd d2, [r9] @ vAA<- d2 5153 GOTO_OPCODE(ip) @ jump to next instruction 5154 5155 5156/* ------------------------------ */ 5157 .balign 64 5158.L_OP_DIV_DOUBLE: /* 0xae */ 5159/* File: arm-vfp/OP_DIV_DOUBLE.S */ 5160/* File: arm-vfp/fbinopWide.S */ 5161 /* 5162 * Generic 64-bit double-precision floating point binary operation. 5163 * Provide an "instr" line that specifies an instruction that performs 5164 * "d2 = d0 op d1". 5165 * 5166 * for: add-double, sub-double, mul-double, div-double 5167 */ 5168 /* doubleop vAA, vBB, vCC */ 5169 FETCH(r0, 1) @ r0<- CCBB 5170 mov r9, rINST, lsr #8 @ r9<- AA 5171 mov r3, r0, lsr #8 @ r3<- CC 5172 and r2, r0, #255 @ r2<- BB 5173 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5174 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5175 fldd d1, [r3] @ d1<- vCC 5176 fldd d0, [r2] @ d0<- vBB 5177 5178 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5179 fdivd d2, d0, d1 @ s2<- op 5180 GET_INST_OPCODE(ip) @ extract opcode from rINST 5181 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5182 fstd d2, [r9] @ vAA<- d2 5183 GOTO_OPCODE(ip) @ jump to next instruction 5184 5185 5186/* ------------------------------ */ 5187 .balign 64 5188.L_OP_REM_DOUBLE: /* 0xaf */ 5189/* File: armv5te/OP_REM_DOUBLE.S */ 5190/* EABI doesn't define a double remainder function, but libm does */ 5191/* File: armv5te/binopWide.S */ 5192 /* 5193 * Generic 64-bit binary operation. Provide an "instr" line that 5194 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5195 * This could be an ARM instruction or a function call. (If the result 5196 * comes back in a register other than r0, you can override "result".) 5197 * 5198 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5199 * vCC (r1). Useful for integer division and modulus. 5200 * 5201 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5202 * xor-long, add-double, sub-double, mul-double, div-double, 5203 * rem-double 5204 * 5205 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5206 */ 5207 /* binop vAA, vBB, vCC */ 5208 FETCH(r0, 1) @ r0<- CCBB 5209 mov r9, rINST, lsr #8 @ r9<- AA 5210 and r2, r0, #255 @ r2<- BB 5211 mov r3, r0, lsr #8 @ r3<- CC 5212 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5213 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5214 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5215 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5216 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5217 .if 0 5218 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5219 beq common_errDivideByZero 5220 .endif 5221 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5222 5223 @ optional op; may set condition codes 5224 bl fmod @ result<- op, r0-r3 changed 5225 GET_INST_OPCODE(ip) @ extract opcode from rINST 5226 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5227 GOTO_OPCODE(ip) @ jump to next instruction 5228 /* 14-17 instructions */ 5229 5230 5231/* ------------------------------ */ 5232 .balign 64 5233.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5234/* File: armv5te/OP_ADD_INT_2ADDR.S */ 5235/* File: armv5te/binop2addr.S */ 5236 /* 5237 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5238 * that specifies an instruction that performs "result = r0 op r1". 5239 * This could be an ARM instruction or a function call. (If the result 5240 * comes back in a register other than r0, you can override "result".) 5241 * 5242 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5243 * vCC (r1). Useful for integer division and modulus. 5244 * 5245 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5246 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5247 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5248 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5249 */ 5250 /* binop/2addr vA, vB */ 5251 mov r9, rINST, lsr #8 @ r9<- A+ 5252 mov r3, rINST, lsr #12 @ r3<- B 5253 and r9, r9, #15 5254 GET_VREG(r1, r3) @ r1<- vB 5255 GET_VREG(r0, r9) @ r0<- vA 5256 .if 0 5257 cmp r1, #0 @ is second operand zero? 5258 beq common_errDivideByZero 5259 .endif 5260 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5261 5262 @ optional op; may set condition codes 5263 add r0, r0, r1 @ r0<- op, r0-r3 changed 5264 GET_INST_OPCODE(ip) @ extract opcode from rINST 5265 SET_VREG(r0, r9) @ vAA<- r0 5266 GOTO_OPCODE(ip) @ jump to next instruction 5267 /* 10-13 instructions */ 5268 5269 5270/* ------------------------------ */ 5271 .balign 64 5272.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5273/* File: armv5te/OP_SUB_INT_2ADDR.S */ 5274/* File: armv5te/binop2addr.S */ 5275 /* 5276 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5277 * that specifies an instruction that performs "result = r0 op r1". 5278 * This could be an ARM instruction or a function call. (If the result 5279 * comes back in a register other than r0, you can override "result".) 5280 * 5281 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5282 * vCC (r1). Useful for integer division and modulus. 5283 * 5284 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5285 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5286 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5287 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5288 */ 5289 /* binop/2addr vA, vB */ 5290 mov r9, rINST, lsr #8 @ r9<- A+ 5291 mov r3, rINST, lsr #12 @ r3<- B 5292 and r9, r9, #15 5293 GET_VREG(r1, r3) @ r1<- vB 5294 GET_VREG(r0, r9) @ r0<- vA 5295 .if 0 5296 cmp r1, #0 @ is second operand zero? 5297 beq common_errDivideByZero 5298 .endif 5299 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5300 5301 @ optional op; may set condition codes 5302 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5303 GET_INST_OPCODE(ip) @ extract opcode from rINST 5304 SET_VREG(r0, r9) @ vAA<- r0 5305 GOTO_OPCODE(ip) @ jump to next instruction 5306 /* 10-13 instructions */ 5307 5308 5309/* ------------------------------ */ 5310 .balign 64 5311.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5312/* File: armv5te/OP_MUL_INT_2ADDR.S */ 5313/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5314/* File: armv5te/binop2addr.S */ 5315 /* 5316 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5317 * that specifies an instruction that performs "result = r0 op r1". 5318 * This could be an ARM instruction or a function call. (If the result 5319 * comes back in a register other than r0, you can override "result".) 5320 * 5321 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5322 * vCC (r1). Useful for integer division and modulus. 5323 * 5324 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5325 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5326 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5327 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5328 */ 5329 /* binop/2addr vA, vB */ 5330 mov r9, rINST, lsr #8 @ r9<- A+ 5331 mov r3, rINST, lsr #12 @ r3<- B 5332 and r9, r9, #15 5333 GET_VREG(r1, r3) @ r1<- vB 5334 GET_VREG(r0, r9) @ r0<- vA 5335 .if 0 5336 cmp r1, #0 @ is second operand zero? 5337 beq common_errDivideByZero 5338 .endif 5339 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5340 5341 @ optional op; may set condition codes 5342 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5343 GET_INST_OPCODE(ip) @ extract opcode from rINST 5344 SET_VREG(r0, r9) @ vAA<- r0 5345 GOTO_OPCODE(ip) @ jump to next instruction 5346 /* 10-13 instructions */ 5347 5348 5349/* ------------------------------ */ 5350 .balign 64 5351.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5352/* File: armv5te/OP_DIV_INT_2ADDR.S */ 5353/* File: armv5te/binop2addr.S */ 5354 /* 5355 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5356 * that specifies an instruction that performs "result = r0 op r1". 5357 * This could be an ARM instruction or a function call. (If the result 5358 * comes back in a register other than r0, you can override "result".) 5359 * 5360 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5361 * vCC (r1). Useful for integer division and modulus. 5362 * 5363 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5364 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5365 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5366 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5367 */ 5368 /* binop/2addr vA, vB */ 5369 mov r9, rINST, lsr #8 @ r9<- A+ 5370 mov r3, rINST, lsr #12 @ r3<- B 5371 and r9, r9, #15 5372 GET_VREG(r1, r3) @ r1<- vB 5373 GET_VREG(r0, r9) @ r0<- vA 5374 .if 1 5375 cmp r1, #0 @ is second operand zero? 5376 beq common_errDivideByZero 5377 .endif 5378 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5379 5380 @ optional op; may set condition codes 5381 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5382 GET_INST_OPCODE(ip) @ extract opcode from rINST 5383 SET_VREG(r0, r9) @ vAA<- r0 5384 GOTO_OPCODE(ip) @ jump to next instruction 5385 /* 10-13 instructions */ 5386 5387 5388/* ------------------------------ */ 5389 .balign 64 5390.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5391/* File: armv5te/OP_REM_INT_2ADDR.S */ 5392/* idivmod returns quotient in r0 and remainder in r1 */ 5393/* File: armv5te/binop2addr.S */ 5394 /* 5395 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5396 * that specifies an instruction that performs "result = r0 op r1". 5397 * This could be an ARM instruction or a function call. (If the result 5398 * comes back in a register other than r0, you can override "result".) 5399 * 5400 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5401 * vCC (r1). Useful for integer division and modulus. 5402 * 5403 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5404 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5405 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5406 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5407 */ 5408 /* binop/2addr vA, vB */ 5409 mov r9, rINST, lsr #8 @ r9<- A+ 5410 mov r3, rINST, lsr #12 @ r3<- B 5411 and r9, r9, #15 5412 GET_VREG(r1, r3) @ r1<- vB 5413 GET_VREG(r0, r9) @ r0<- vA 5414 .if 1 5415 cmp r1, #0 @ is second operand zero? 5416 beq common_errDivideByZero 5417 .endif 5418 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5419 5420 @ optional op; may set condition codes 5421 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5422 GET_INST_OPCODE(ip) @ extract opcode from rINST 5423 SET_VREG(r1, r9) @ vAA<- r1 5424 GOTO_OPCODE(ip) @ jump to next instruction 5425 /* 10-13 instructions */ 5426 5427 5428/* ------------------------------ */ 5429 .balign 64 5430.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5431/* File: armv5te/OP_AND_INT_2ADDR.S */ 5432/* File: armv5te/binop2addr.S */ 5433 /* 5434 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5435 * that specifies an instruction that performs "result = r0 op r1". 5436 * This could be an ARM instruction or a function call. (If the result 5437 * comes back in a register other than r0, you can override "result".) 5438 * 5439 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5440 * vCC (r1). Useful for integer division and modulus. 5441 * 5442 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5443 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5444 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5445 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5446 */ 5447 /* binop/2addr vA, vB */ 5448 mov r9, rINST, lsr #8 @ r9<- A+ 5449 mov r3, rINST, lsr #12 @ r3<- B 5450 and r9, r9, #15 5451 GET_VREG(r1, r3) @ r1<- vB 5452 GET_VREG(r0, r9) @ r0<- vA 5453 .if 0 5454 cmp r1, #0 @ is second operand zero? 5455 beq common_errDivideByZero 5456 .endif 5457 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5458 5459 @ optional op; may set condition codes 5460 and r0, r0, r1 @ r0<- op, r0-r3 changed 5461 GET_INST_OPCODE(ip) @ extract opcode from rINST 5462 SET_VREG(r0, r9) @ vAA<- r0 5463 GOTO_OPCODE(ip) @ jump to next instruction 5464 /* 10-13 instructions */ 5465 5466 5467/* ------------------------------ */ 5468 .balign 64 5469.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5470/* File: armv5te/OP_OR_INT_2ADDR.S */ 5471/* File: armv5te/binop2addr.S */ 5472 /* 5473 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5474 * that specifies an instruction that performs "result = r0 op r1". 5475 * This could be an ARM instruction or a function call. (If the result 5476 * comes back in a register other than r0, you can override "result".) 5477 * 5478 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5479 * vCC (r1). Useful for integer division and modulus. 5480 * 5481 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5482 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5483 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5484 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5485 */ 5486 /* binop/2addr vA, vB */ 5487 mov r9, rINST, lsr #8 @ r9<- A+ 5488 mov r3, rINST, lsr #12 @ r3<- B 5489 and r9, r9, #15 5490 GET_VREG(r1, r3) @ r1<- vB 5491 GET_VREG(r0, r9) @ r0<- vA 5492 .if 0 5493 cmp r1, #0 @ is second operand zero? 5494 beq common_errDivideByZero 5495 .endif 5496 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5497 5498 @ optional op; may set condition codes 5499 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5500 GET_INST_OPCODE(ip) @ extract opcode from rINST 5501 SET_VREG(r0, r9) @ vAA<- r0 5502 GOTO_OPCODE(ip) @ jump to next instruction 5503 /* 10-13 instructions */ 5504 5505 5506/* ------------------------------ */ 5507 .balign 64 5508.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5509/* File: armv5te/OP_XOR_INT_2ADDR.S */ 5510/* File: armv5te/binop2addr.S */ 5511 /* 5512 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5513 * that specifies an instruction that performs "result = r0 op r1". 5514 * This could be an ARM instruction or a function call. (If the result 5515 * comes back in a register other than r0, you can override "result".) 5516 * 5517 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5518 * vCC (r1). Useful for integer division and modulus. 5519 * 5520 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5521 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5522 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5523 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5524 */ 5525 /* binop/2addr vA, vB */ 5526 mov r9, rINST, lsr #8 @ r9<- A+ 5527 mov r3, rINST, lsr #12 @ r3<- B 5528 and r9, r9, #15 5529 GET_VREG(r1, r3) @ r1<- vB 5530 GET_VREG(r0, r9) @ r0<- vA 5531 .if 0 5532 cmp r1, #0 @ is second operand zero? 5533 beq common_errDivideByZero 5534 .endif 5535 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5536 5537 @ optional op; may set condition codes 5538 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5539 GET_INST_OPCODE(ip) @ extract opcode from rINST 5540 SET_VREG(r0, r9) @ vAA<- r0 5541 GOTO_OPCODE(ip) @ jump to next instruction 5542 /* 10-13 instructions */ 5543 5544 5545/* ------------------------------ */ 5546 .balign 64 5547.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5548/* File: armv5te/OP_SHL_INT_2ADDR.S */ 5549/* File: armv5te/binop2addr.S */ 5550 /* 5551 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5552 * that specifies an instruction that performs "result = r0 op r1". 5553 * This could be an ARM instruction or a function call. (If the result 5554 * comes back in a register other than r0, you can override "result".) 5555 * 5556 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5557 * vCC (r1). Useful for integer division and modulus. 5558 * 5559 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5560 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5561 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5562 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5563 */ 5564 /* binop/2addr vA, vB */ 5565 mov r9, rINST, lsr #8 @ r9<- A+ 5566 mov r3, rINST, lsr #12 @ r3<- B 5567 and r9, r9, #15 5568 GET_VREG(r1, r3) @ r1<- vB 5569 GET_VREG(r0, r9) @ r0<- vA 5570 .if 0 5571 cmp r1, #0 @ is second operand zero? 5572 beq common_errDivideByZero 5573 .endif 5574 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5575 5576 and r1, r1, #31 @ optional op; may set condition codes 5577 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5578 GET_INST_OPCODE(ip) @ extract opcode from rINST 5579 SET_VREG(r0, r9) @ vAA<- r0 5580 GOTO_OPCODE(ip) @ jump to next instruction 5581 /* 10-13 instructions */ 5582 5583 5584/* ------------------------------ */ 5585 .balign 64 5586.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5587/* File: armv5te/OP_SHR_INT_2ADDR.S */ 5588/* File: armv5te/binop2addr.S */ 5589 /* 5590 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5591 * that specifies an instruction that performs "result = r0 op r1". 5592 * This could be an ARM instruction or a function call. (If the result 5593 * comes back in a register other than r0, you can override "result".) 5594 * 5595 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5596 * vCC (r1). Useful for integer division and modulus. 5597 * 5598 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5599 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5600 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5601 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5602 */ 5603 /* binop/2addr vA, vB */ 5604 mov r9, rINST, lsr #8 @ r9<- A+ 5605 mov r3, rINST, lsr #12 @ r3<- B 5606 and r9, r9, #15 5607 GET_VREG(r1, r3) @ r1<- vB 5608 GET_VREG(r0, r9) @ r0<- vA 5609 .if 0 5610 cmp r1, #0 @ is second operand zero? 5611 beq common_errDivideByZero 5612 .endif 5613 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5614 5615 and r1, r1, #31 @ optional op; may set condition codes 5616 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5617 GET_INST_OPCODE(ip) @ extract opcode from rINST 5618 SET_VREG(r0, r9) @ vAA<- r0 5619 GOTO_OPCODE(ip) @ jump to next instruction 5620 /* 10-13 instructions */ 5621 5622 5623/* ------------------------------ */ 5624 .balign 64 5625.L_OP_USHR_INT_2ADDR: /* 0xba */ 5626/* File: armv5te/OP_USHR_INT_2ADDR.S */ 5627/* File: armv5te/binop2addr.S */ 5628 /* 5629 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5630 * that specifies an instruction that performs "result = r0 op r1". 5631 * This could be an ARM instruction or a function call. (If the result 5632 * comes back in a register other than r0, you can override "result".) 5633 * 5634 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5635 * vCC (r1). Useful for integer division and modulus. 5636 * 5637 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5638 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5639 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5640 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5641 */ 5642 /* binop/2addr vA, vB */ 5643 mov r9, rINST, lsr #8 @ r9<- A+ 5644 mov r3, rINST, lsr #12 @ r3<- B 5645 and r9, r9, #15 5646 GET_VREG(r1, r3) @ r1<- vB 5647 GET_VREG(r0, r9) @ r0<- vA 5648 .if 0 5649 cmp r1, #0 @ is second operand zero? 5650 beq common_errDivideByZero 5651 .endif 5652 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5653 5654 and r1, r1, #31 @ optional op; may set condition codes 5655 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5656 GET_INST_OPCODE(ip) @ extract opcode from rINST 5657 SET_VREG(r0, r9) @ vAA<- r0 5658 GOTO_OPCODE(ip) @ jump to next instruction 5659 /* 10-13 instructions */ 5660 5661 5662/* ------------------------------ */ 5663 .balign 64 5664.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5665/* File: armv5te/OP_ADD_LONG_2ADDR.S */ 5666/* File: armv5te/binopWide2addr.S */ 5667 /* 5668 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5669 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5670 * This could be an ARM instruction or a function call. (If the result 5671 * comes back in a register other than r0, you can override "result".) 5672 * 5673 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5674 * vCC (r1). Useful for integer division and modulus. 5675 * 5676 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5677 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5678 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5679 * rem-double/2addr 5680 */ 5681 /* binop/2addr vA, vB */ 5682 mov r9, rINST, lsr #8 @ r9<- A+ 5683 mov r1, rINST, lsr #12 @ r1<- B 5684 and r9, r9, #15 5685 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5686 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5687 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5688 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5689 .if 0 5690 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5691 beq common_errDivideByZero 5692 .endif 5693 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5694 5695 adds r0, r0, r2 @ optional op; may set condition codes 5696 adc r1, r1, r3 @ result<- op, r0-r3 changed 5697 GET_INST_OPCODE(ip) @ extract opcode from rINST 5698 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5699 GOTO_OPCODE(ip) @ jump to next instruction 5700 /* 12-15 instructions */ 5701 5702 5703/* ------------------------------ */ 5704 .balign 64 5705.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5706/* File: armv5te/OP_SUB_LONG_2ADDR.S */ 5707/* File: armv5te/binopWide2addr.S */ 5708 /* 5709 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5710 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5711 * This could be an ARM instruction or a function call. (If the result 5712 * comes back in a register other than r0, you can override "result".) 5713 * 5714 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5715 * vCC (r1). Useful for integer division and modulus. 5716 * 5717 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5718 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5719 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5720 * rem-double/2addr 5721 */ 5722 /* binop/2addr vA, vB */ 5723 mov r9, rINST, lsr #8 @ r9<- A+ 5724 mov r1, rINST, lsr #12 @ r1<- B 5725 and r9, r9, #15 5726 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5727 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5728 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5729 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5730 .if 0 5731 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5732 beq common_errDivideByZero 5733 .endif 5734 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5735 5736 subs r0, r0, r2 @ optional op; may set condition codes 5737 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5738 GET_INST_OPCODE(ip) @ extract opcode from rINST 5739 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5740 GOTO_OPCODE(ip) @ jump to next instruction 5741 /* 12-15 instructions */ 5742 5743 5744/* ------------------------------ */ 5745 .balign 64 5746.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 5747/* File: armv5te/OP_MUL_LONG_2ADDR.S */ 5748 /* 5749 * Signed 64-bit integer multiply, "/2addr" version. 5750 * 5751 * See OP_MUL_LONG for an explanation. 5752 * 5753 * We get a little tight on registers, so to avoid looking up &fp[A] 5754 * again we stuff it into rINST. 5755 */ 5756 /* mul-long/2addr vA, vB */ 5757 mov r9, rINST, lsr #8 @ r9<- A+ 5758 mov r1, rINST, lsr #12 @ r1<- B 5759 and r9, r9, #15 5760 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5761 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 5762 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5763 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 5764 mul ip, r2, r1 @ ip<- ZxW 5765 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 5766 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 5767 mov r0, rINST @ r0<- &fp[A] (free up rINST) 5768 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5769 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 5770 GET_INST_OPCODE(ip) @ extract opcode from rINST 5771 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 5772 GOTO_OPCODE(ip) @ jump to next instruction 5773 5774/* ------------------------------ */ 5775 .balign 64 5776.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 5777/* File: armv5te/OP_DIV_LONG_2ADDR.S */ 5778/* File: armv5te/binopWide2addr.S */ 5779 /* 5780 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5781 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5782 * This could be an ARM instruction or a function call. (If the result 5783 * comes back in a register other than r0, you can override "result".) 5784 * 5785 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5786 * vCC (r1). Useful for integer division and modulus. 5787 * 5788 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5789 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5790 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5791 * rem-double/2addr 5792 */ 5793 /* binop/2addr vA, vB */ 5794 mov r9, rINST, lsr #8 @ r9<- A+ 5795 mov r1, rINST, lsr #12 @ r1<- B 5796 and r9, r9, #15 5797 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5798 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5799 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5800 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5801 .if 1 5802 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5803 beq common_errDivideByZero 5804 .endif 5805 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5806 5807 @ optional op; may set condition codes 5808 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5809 GET_INST_OPCODE(ip) @ extract opcode from rINST 5810 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5811 GOTO_OPCODE(ip) @ jump to next instruction 5812 /* 12-15 instructions */ 5813 5814 5815/* ------------------------------ */ 5816 .balign 64 5817.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5818/* File: armv5te/OP_REM_LONG_2ADDR.S */ 5819/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 5820/* File: armv5te/binopWide2addr.S */ 5821 /* 5822 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5823 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5824 * This could be an ARM instruction or a function call. (If the result 5825 * comes back in a register other than r0, you can override "result".) 5826 * 5827 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5828 * vCC (r1). Useful for integer division and modulus. 5829 * 5830 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5831 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5832 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5833 * rem-double/2addr 5834 */ 5835 /* binop/2addr vA, vB */ 5836 mov r9, rINST, lsr #8 @ r9<- A+ 5837 mov r1, rINST, lsr #12 @ r1<- B 5838 and r9, r9, #15 5839 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5840 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5841 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5842 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5843 .if 1 5844 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5845 beq common_errDivideByZero 5846 .endif 5847 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5848 5849 @ optional op; may set condition codes 5850 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5851 GET_INST_OPCODE(ip) @ extract opcode from rINST 5852 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 5853 GOTO_OPCODE(ip) @ jump to next instruction 5854 /* 12-15 instructions */ 5855 5856 5857/* ------------------------------ */ 5858 .balign 64 5859.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 5860/* File: armv5te/OP_AND_LONG_2ADDR.S */ 5861/* File: armv5te/binopWide2addr.S */ 5862 /* 5863 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5864 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5865 * This could be an ARM instruction or a function call. (If the result 5866 * comes back in a register other than r0, you can override "result".) 5867 * 5868 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5869 * vCC (r1). Useful for integer division and modulus. 5870 * 5871 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5872 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5873 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5874 * rem-double/2addr 5875 */ 5876 /* binop/2addr vA, vB */ 5877 mov r9, rINST, lsr #8 @ r9<- A+ 5878 mov r1, rINST, lsr #12 @ r1<- B 5879 and r9, r9, #15 5880 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5881 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5882 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5883 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5884 .if 0 5885 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5886 beq common_errDivideByZero 5887 .endif 5888 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5889 5890 and r0, r0, r2 @ optional op; may set condition codes 5891 and r1, r1, r3 @ result<- op, r0-r3 changed 5892 GET_INST_OPCODE(ip) @ extract opcode from rINST 5893 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5894 GOTO_OPCODE(ip) @ jump to next instruction 5895 /* 12-15 instructions */ 5896 5897 5898/* ------------------------------ */ 5899 .balign 64 5900.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 5901/* File: armv5te/OP_OR_LONG_2ADDR.S */ 5902/* File: armv5te/binopWide2addr.S */ 5903 /* 5904 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5905 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5906 * This could be an ARM instruction or a function call. (If the result 5907 * comes back in a register other than r0, you can override "result".) 5908 * 5909 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5910 * vCC (r1). Useful for integer division and modulus. 5911 * 5912 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5913 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5914 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5915 * rem-double/2addr 5916 */ 5917 /* binop/2addr vA, vB */ 5918 mov r9, rINST, lsr #8 @ r9<- A+ 5919 mov r1, rINST, lsr #12 @ r1<- B 5920 and r9, r9, #15 5921 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5922 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5923 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5924 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5925 .if 0 5926 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5927 beq common_errDivideByZero 5928 .endif 5929 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5930 5931 orr r0, r0, r2 @ optional op; may set condition codes 5932 orr r1, r1, r3 @ result<- op, r0-r3 changed 5933 GET_INST_OPCODE(ip) @ extract opcode from rINST 5934 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5935 GOTO_OPCODE(ip) @ jump to next instruction 5936 /* 12-15 instructions */ 5937 5938 5939/* ------------------------------ */ 5940 .balign 64 5941.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 5942/* File: armv5te/OP_XOR_LONG_2ADDR.S */ 5943/* File: armv5te/binopWide2addr.S */ 5944 /* 5945 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5946 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5947 * This could be an ARM instruction or a function call. (If the result 5948 * comes back in a register other than r0, you can override "result".) 5949 * 5950 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5951 * vCC (r1). Useful for integer division and modulus. 5952 * 5953 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5954 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5955 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5956 * rem-double/2addr 5957 */ 5958 /* binop/2addr vA, vB */ 5959 mov r9, rINST, lsr #8 @ r9<- A+ 5960 mov r1, rINST, lsr #12 @ r1<- B 5961 and r9, r9, #15 5962 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5963 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5964 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5965 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5966 .if 0 5967 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5968 beq common_errDivideByZero 5969 .endif 5970 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5971 5972 eor r0, r0, r2 @ optional op; may set condition codes 5973 eor r1, r1, r3 @ result<- op, r0-r3 changed 5974 GET_INST_OPCODE(ip) @ extract opcode from rINST 5975 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5976 GOTO_OPCODE(ip) @ jump to next instruction 5977 /* 12-15 instructions */ 5978 5979 5980/* ------------------------------ */ 5981 .balign 64 5982.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 5983/* File: armv5te/OP_SHL_LONG_2ADDR.S */ 5984 /* 5985 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 5986 * 32-bit shift distance. 5987 */ 5988 /* shl-long/2addr vA, vB */ 5989 mov r9, rINST, lsr #8 @ r9<- A+ 5990 mov r3, rINST, lsr #12 @ r3<- B 5991 and r9, r9, #15 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 r1, r1, asl r2 @ r1<- r1 << r2 5998 rsb r3, r2, #32 @ r3<- 32 - r2 5999 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 6000 subs ip, r2, #32 @ ip<- r2 - 32 6001 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6002 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 6003 mov r0, r0, asl r2 @ r0<- r0 << r2 6004 b .LOP_SHL_LONG_2ADDR_finish 6005 6006/* ------------------------------ */ 6007 .balign 64 6008.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 6009/* File: armv5te/OP_SHR_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 /* shr-long/2addr vA, vB */ 6015 mov r9, rINST, lsr #8 @ r9<- A+ 6016 mov r3, rINST, lsr #12 @ r3<- B 6017 and r9, r9, #15 6018 GET_VREG(r2, r3) @ r2<- vB 6019 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6020 and r2, r2, #63 @ r2<- r2 & 0x3f 6021 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6022 6023 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6024 rsb r3, r2, #32 @ r3<- 32 - r2 6025 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6026 subs ip, r2, #32 @ ip<- r2 - 32 6027 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6028 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6029 mov r1, r1, asr r2 @ r1<- r1 >> r2 6030 b .LOP_SHR_LONG_2ADDR_finish 6031 6032/* ------------------------------ */ 6033 .balign 64 6034.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6035/* File: armv5te/OP_USHR_LONG_2ADDR.S */ 6036 /* 6037 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6038 * 32-bit shift distance. 6039 */ 6040 /* ushr-long/2addr vA, vB */ 6041 mov r9, rINST, lsr #8 @ r9<- A+ 6042 mov r3, rINST, lsr #12 @ r3<- B 6043 and r9, r9, #15 6044 GET_VREG(r2, r3) @ r2<- vB 6045 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6046 and r2, r2, #63 @ r2<- r2 & 0x3f 6047 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6048 6049 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6050 rsb r3, r2, #32 @ r3<- 32 - r2 6051 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6052 subs ip, r2, #32 @ ip<- r2 - 32 6053 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6054 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6055 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6056 b .LOP_USHR_LONG_2ADDR_finish 6057 6058/* ------------------------------ */ 6059 .balign 64 6060.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6061/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */ 6062/* File: arm-vfp/fbinop2addr.S */ 6063 /* 6064 * Generic 32-bit floating point "/2addr" binary operation. Provide 6065 * an "instr" line that specifies an instruction that performs 6066 * "s2 = s0 op s1". 6067 * 6068 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6069 */ 6070 /* binop/2addr vA, vB */ 6071 mov r3, rINST, lsr #12 @ r3<- B 6072 mov r9, rINST, lsr #8 @ r9<- A+ 6073 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6074 and r9, r9, #15 @ r9<- A 6075 flds s1, [r3] @ s1<- vB 6076 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6077 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6078 flds s0, [r9] @ s0<- vA 6079 6080 fadds s2, s0, s1 @ s2<- op 6081 GET_INST_OPCODE(ip) @ extract opcode from rINST 6082 fsts s2, [r9] @ vAA<- s2 6083 GOTO_OPCODE(ip) @ jump to next instruction 6084 6085 6086/* ------------------------------ */ 6087 .balign 64 6088.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6089/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */ 6090/* File: arm-vfp/fbinop2addr.S */ 6091 /* 6092 * Generic 32-bit floating point "/2addr" binary operation. Provide 6093 * an "instr" line that specifies an instruction that performs 6094 * "s2 = s0 op s1". 6095 * 6096 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6097 */ 6098 /* binop/2addr vA, vB */ 6099 mov r3, rINST, lsr #12 @ r3<- B 6100 mov r9, rINST, lsr #8 @ r9<- A+ 6101 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6102 and r9, r9, #15 @ r9<- A 6103 flds s1, [r3] @ s1<- vB 6104 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6105 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6106 flds s0, [r9] @ s0<- vA 6107 6108 fsubs s2, s0, s1 @ s2<- op 6109 GET_INST_OPCODE(ip) @ extract opcode from rINST 6110 fsts s2, [r9] @ vAA<- s2 6111 GOTO_OPCODE(ip) @ jump to next instruction 6112 6113 6114/* ------------------------------ */ 6115 .balign 64 6116.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6117/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */ 6118/* File: arm-vfp/fbinop2addr.S */ 6119 /* 6120 * Generic 32-bit floating point "/2addr" binary operation. Provide 6121 * an "instr" line that specifies an instruction that performs 6122 * "s2 = s0 op s1". 6123 * 6124 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6125 */ 6126 /* binop/2addr vA, vB */ 6127 mov r3, rINST, lsr #12 @ r3<- B 6128 mov r9, rINST, lsr #8 @ r9<- A+ 6129 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6130 and r9, r9, #15 @ r9<- A 6131 flds s1, [r3] @ s1<- vB 6132 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6133 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6134 flds s0, [r9] @ s0<- vA 6135 6136 fmuls s2, s0, s1 @ s2<- op 6137 GET_INST_OPCODE(ip) @ extract opcode from rINST 6138 fsts s2, [r9] @ vAA<- s2 6139 GOTO_OPCODE(ip) @ jump to next instruction 6140 6141 6142/* ------------------------------ */ 6143 .balign 64 6144.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6145/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */ 6146/* File: arm-vfp/fbinop2addr.S */ 6147 /* 6148 * Generic 32-bit floating point "/2addr" binary operation. Provide 6149 * an "instr" line that specifies an instruction that performs 6150 * "s2 = s0 op s1". 6151 * 6152 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6153 */ 6154 /* binop/2addr vA, vB */ 6155 mov r3, rINST, lsr #12 @ r3<- B 6156 mov r9, rINST, lsr #8 @ r9<- A+ 6157 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6158 and r9, r9, #15 @ r9<- A 6159 flds s1, [r3] @ s1<- vB 6160 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6161 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6162 flds s0, [r9] @ s0<- vA 6163 6164 fdivs s2, s0, s1 @ s2<- op 6165 GET_INST_OPCODE(ip) @ extract opcode from rINST 6166 fsts s2, [r9] @ vAA<- s2 6167 GOTO_OPCODE(ip) @ jump to next instruction 6168 6169 6170/* ------------------------------ */ 6171 .balign 64 6172.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6173/* File: armv5te/OP_REM_FLOAT_2ADDR.S */ 6174/* EABI doesn't define a float remainder function, but libm does */ 6175/* File: armv5te/binop2addr.S */ 6176 /* 6177 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6178 * that specifies an instruction that performs "result = r0 op r1". 6179 * This could be an ARM instruction or a function call. (If the result 6180 * comes back in a register other than r0, you can override "result".) 6181 * 6182 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6183 * vCC (r1). Useful for integer division and modulus. 6184 * 6185 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6186 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6187 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6188 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6189 */ 6190 /* binop/2addr vA, vB */ 6191 mov r9, rINST, lsr #8 @ r9<- A+ 6192 mov r3, rINST, lsr #12 @ r3<- B 6193 and r9, r9, #15 6194 GET_VREG(r1, r3) @ r1<- vB 6195 GET_VREG(r0, r9) @ r0<- vA 6196 .if 0 6197 cmp r1, #0 @ is second operand zero? 6198 beq common_errDivideByZero 6199 .endif 6200 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6201 6202 @ optional op; may set condition codes 6203 bl fmodf @ r0<- op, r0-r3 changed 6204 GET_INST_OPCODE(ip) @ extract opcode from rINST 6205 SET_VREG(r0, r9) @ vAA<- r0 6206 GOTO_OPCODE(ip) @ jump to next instruction 6207 /* 10-13 instructions */ 6208 6209 6210/* ------------------------------ */ 6211 .balign 64 6212.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6213/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */ 6214/* File: arm-vfp/fbinopWide2addr.S */ 6215 /* 6216 * Generic 64-bit floating point "/2addr" binary operation. Provide 6217 * an "instr" line that specifies an instruction that performs 6218 * "d2 = d0 op d1". 6219 * 6220 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6221 * div-double/2addr 6222 */ 6223 /* binop/2addr vA, vB */ 6224 mov r3, rINST, lsr #12 @ r3<- B 6225 mov r9, rINST, lsr #8 @ r9<- A+ 6226 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6227 and r9, r9, #15 @ r9<- A 6228 fldd d1, [r3] @ d1<- vB 6229 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6230 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6231 fldd d0, [r9] @ d0<- vA 6232 6233 faddd d2, d0, d1 @ d2<- op 6234 GET_INST_OPCODE(ip) @ extract opcode from rINST 6235 fstd d2, [r9] @ vAA<- d2 6236 GOTO_OPCODE(ip) @ jump to next instruction 6237 6238 6239/* ------------------------------ */ 6240 .balign 64 6241.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6242/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */ 6243/* File: arm-vfp/fbinopWide2addr.S */ 6244 /* 6245 * Generic 64-bit floating point "/2addr" binary operation. Provide 6246 * an "instr" line that specifies an instruction that performs 6247 * "d2 = d0 op d1". 6248 * 6249 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6250 * div-double/2addr 6251 */ 6252 /* binop/2addr vA, vB */ 6253 mov r3, rINST, lsr #12 @ r3<- B 6254 mov r9, rINST, lsr #8 @ r9<- A+ 6255 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6256 and r9, r9, #15 @ r9<- A 6257 fldd d1, [r3] @ d1<- vB 6258 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6259 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6260 fldd d0, [r9] @ d0<- vA 6261 6262 fsubd d2, d0, d1 @ d2<- op 6263 GET_INST_OPCODE(ip) @ extract opcode from rINST 6264 fstd d2, [r9] @ vAA<- d2 6265 GOTO_OPCODE(ip) @ jump to next instruction 6266 6267 6268/* ------------------------------ */ 6269 .balign 64 6270.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6271/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */ 6272/* File: arm-vfp/fbinopWide2addr.S */ 6273 /* 6274 * Generic 64-bit floating point "/2addr" binary operation. Provide 6275 * an "instr" line that specifies an instruction that performs 6276 * "d2 = d0 op d1". 6277 * 6278 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6279 * div-double/2addr 6280 */ 6281 /* binop/2addr vA, vB */ 6282 mov r3, rINST, lsr #12 @ r3<- B 6283 mov r9, rINST, lsr #8 @ r9<- A+ 6284 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6285 and r9, r9, #15 @ r9<- A 6286 fldd d1, [r3] @ d1<- vB 6287 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6288 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6289 fldd d0, [r9] @ d0<- vA 6290 6291 fmuld d2, d0, d1 @ d2<- op 6292 GET_INST_OPCODE(ip) @ extract opcode from rINST 6293 fstd d2, [r9] @ vAA<- d2 6294 GOTO_OPCODE(ip) @ jump to next instruction 6295 6296 6297/* ------------------------------ */ 6298 .balign 64 6299.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6300/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */ 6301/* File: arm-vfp/fbinopWide2addr.S */ 6302 /* 6303 * Generic 64-bit floating point "/2addr" binary operation. Provide 6304 * an "instr" line that specifies an instruction that performs 6305 * "d2 = d0 op d1". 6306 * 6307 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6308 * div-double/2addr 6309 */ 6310 /* binop/2addr vA, vB */ 6311 mov r3, rINST, lsr #12 @ r3<- B 6312 mov r9, rINST, lsr #8 @ r9<- A+ 6313 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6314 and r9, r9, #15 @ r9<- A 6315 fldd d1, [r3] @ d1<- vB 6316 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6317 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6318 fldd d0, [r9] @ d0<- vA 6319 6320 fdivd d2, d0, d1 @ d2<- op 6321 GET_INST_OPCODE(ip) @ extract opcode from rINST 6322 fstd d2, [r9] @ vAA<- d2 6323 GOTO_OPCODE(ip) @ jump to next instruction 6324 6325 6326/* ------------------------------ */ 6327 .balign 64 6328.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6329/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */ 6330/* EABI doesn't define a double remainder function, but libm does */ 6331/* File: armv5te/binopWide2addr.S */ 6332 /* 6333 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6334 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6335 * This could be an ARM instruction or a function call. (If the result 6336 * comes back in a register other than r0, you can override "result".) 6337 * 6338 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6339 * vCC (r1). Useful for integer division and modulus. 6340 * 6341 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6342 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6343 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6344 * rem-double/2addr 6345 */ 6346 /* binop/2addr vA, vB */ 6347 mov r9, rINST, lsr #8 @ r9<- A+ 6348 mov r1, rINST, lsr #12 @ r1<- B 6349 and r9, r9, #15 6350 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6351 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6352 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6353 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6354 .if 0 6355 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6356 beq common_errDivideByZero 6357 .endif 6358 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6359 6360 @ optional op; may set condition codes 6361 bl fmod @ result<- op, r0-r3 changed 6362 GET_INST_OPCODE(ip) @ extract opcode from rINST 6363 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6364 GOTO_OPCODE(ip) @ jump to next instruction 6365 /* 12-15 instructions */ 6366 6367 6368/* ------------------------------ */ 6369 .balign 64 6370.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6371/* File: armv5te/OP_ADD_INT_LIT16.S */ 6372/* File: armv5te/binopLit16.S */ 6373 /* 6374 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6375 * that specifies an instruction that performs "result = r0 op r1". 6376 * This could be an ARM instruction or a function call. (If the result 6377 * comes back in a register other than r0, you can override "result".) 6378 * 6379 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6380 * vCC (r1). Useful for integer division and modulus. 6381 * 6382 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6383 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6384 */ 6385 /* binop/lit16 vA, vB, #+CCCC */ 6386 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6387 mov r2, rINST, lsr #12 @ r2<- B 6388 mov r9, rINST, lsr #8 @ r9<- A+ 6389 GET_VREG(r0, r2) @ r0<- vB 6390 and r9, r9, #15 6391 .if 0 6392 cmp r1, #0 @ is second operand zero? 6393 beq common_errDivideByZero 6394 .endif 6395 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6396 6397 add r0, r0, r1 @ r0<- op, r0-r3 changed 6398 GET_INST_OPCODE(ip) @ extract opcode from rINST 6399 SET_VREG(r0, r9) @ vAA<- r0 6400 GOTO_OPCODE(ip) @ jump to next instruction 6401 /* 10-13 instructions */ 6402 6403 6404/* ------------------------------ */ 6405 .balign 64 6406.L_OP_RSUB_INT: /* 0xd1 */ 6407/* File: armv5te/OP_RSUB_INT.S */ 6408/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6409/* File: armv5te/binopLit16.S */ 6410 /* 6411 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6412 * that specifies an instruction that performs "result = r0 op r1". 6413 * This could be an ARM instruction or a function call. (If the result 6414 * comes back in a register other than r0, you can override "result".) 6415 * 6416 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6417 * vCC (r1). Useful for integer division and modulus. 6418 * 6419 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6420 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6421 */ 6422 /* binop/lit16 vA, vB, #+CCCC */ 6423 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6424 mov r2, rINST, lsr #12 @ r2<- B 6425 mov r9, rINST, lsr #8 @ r9<- A+ 6426 GET_VREG(r0, r2) @ r0<- vB 6427 and r9, r9, #15 6428 .if 0 6429 cmp r1, #0 @ is second operand zero? 6430 beq common_errDivideByZero 6431 .endif 6432 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6433 6434 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6435 GET_INST_OPCODE(ip) @ extract opcode from rINST 6436 SET_VREG(r0, r9) @ vAA<- r0 6437 GOTO_OPCODE(ip) @ jump to next instruction 6438 /* 10-13 instructions */ 6439 6440 6441/* ------------------------------ */ 6442 .balign 64 6443.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6444/* File: armv5te/OP_MUL_INT_LIT16.S */ 6445/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6446/* File: armv5te/binopLit16.S */ 6447 /* 6448 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6449 * that specifies an instruction that performs "result = r0 op r1". 6450 * This could be an ARM instruction or a function call. (If the result 6451 * comes back in a register other than r0, you can override "result".) 6452 * 6453 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6454 * vCC (r1). Useful for integer division and modulus. 6455 * 6456 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6457 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6458 */ 6459 /* binop/lit16 vA, vB, #+CCCC */ 6460 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6461 mov r2, rINST, lsr #12 @ r2<- B 6462 mov r9, rINST, lsr #8 @ r9<- A+ 6463 GET_VREG(r0, r2) @ r0<- vB 6464 and r9, r9, #15 6465 .if 0 6466 cmp r1, #0 @ is second operand zero? 6467 beq common_errDivideByZero 6468 .endif 6469 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6470 6471 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6472 GET_INST_OPCODE(ip) @ extract opcode from rINST 6473 SET_VREG(r0, r9) @ vAA<- r0 6474 GOTO_OPCODE(ip) @ jump to next instruction 6475 /* 10-13 instructions */ 6476 6477 6478/* ------------------------------ */ 6479 .balign 64 6480.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6481/* File: armv5te/OP_DIV_INT_LIT16.S */ 6482/* File: armv5te/binopLit16.S */ 6483 /* 6484 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6485 * that specifies an instruction that performs "result = r0 op r1". 6486 * This could be an ARM instruction or a function call. (If the result 6487 * comes back in a register other than r0, you can override "result".) 6488 * 6489 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6490 * vCC (r1). Useful for integer division and modulus. 6491 * 6492 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6493 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6494 */ 6495 /* binop/lit16 vA, vB, #+CCCC */ 6496 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6497 mov r2, rINST, lsr #12 @ r2<- B 6498 mov r9, rINST, lsr #8 @ r9<- A+ 6499 GET_VREG(r0, r2) @ r0<- vB 6500 and r9, r9, #15 6501 .if 1 6502 cmp r1, #0 @ is second operand zero? 6503 beq common_errDivideByZero 6504 .endif 6505 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6506 6507 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6508 GET_INST_OPCODE(ip) @ extract opcode from rINST 6509 SET_VREG(r0, r9) @ vAA<- r0 6510 GOTO_OPCODE(ip) @ jump to next instruction 6511 /* 10-13 instructions */ 6512 6513 6514/* ------------------------------ */ 6515 .balign 64 6516.L_OP_REM_INT_LIT16: /* 0xd4 */ 6517/* File: armv5te/OP_REM_INT_LIT16.S */ 6518/* idivmod returns quotient in r0 and remainder in r1 */ 6519/* File: armv5te/binopLit16.S */ 6520 /* 6521 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6522 * that specifies an instruction that performs "result = r0 op r1". 6523 * This could be an ARM instruction or a function call. (If the result 6524 * comes back in a register other than r0, you can override "result".) 6525 * 6526 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6527 * vCC (r1). Useful for integer division and modulus. 6528 * 6529 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6530 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6531 */ 6532 /* binop/lit16 vA, vB, #+CCCC */ 6533 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6534 mov r2, rINST, lsr #12 @ r2<- B 6535 mov r9, rINST, lsr #8 @ r9<- A+ 6536 GET_VREG(r0, r2) @ r0<- vB 6537 and r9, r9, #15 6538 .if 1 6539 cmp r1, #0 @ is second operand zero? 6540 beq common_errDivideByZero 6541 .endif 6542 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6543 6544 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6545 GET_INST_OPCODE(ip) @ extract opcode from rINST 6546 SET_VREG(r1, r9) @ vAA<- r1 6547 GOTO_OPCODE(ip) @ jump to next instruction 6548 /* 10-13 instructions */ 6549 6550 6551/* ------------------------------ */ 6552 .balign 64 6553.L_OP_AND_INT_LIT16: /* 0xd5 */ 6554/* File: armv5te/OP_AND_INT_LIT16.S */ 6555/* File: armv5te/binopLit16.S */ 6556 /* 6557 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6558 * that specifies an instruction that performs "result = r0 op r1". 6559 * This could be an ARM instruction or a function call. (If the result 6560 * comes back in a register other than r0, you can override "result".) 6561 * 6562 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6563 * vCC (r1). Useful for integer division and modulus. 6564 * 6565 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6566 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6567 */ 6568 /* binop/lit16 vA, vB, #+CCCC */ 6569 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6570 mov r2, rINST, lsr #12 @ r2<- B 6571 mov r9, rINST, lsr #8 @ r9<- A+ 6572 GET_VREG(r0, r2) @ r0<- vB 6573 and r9, r9, #15 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 and 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_OR_INT_LIT16: /* 0xd6 */ 6590/* File: armv5te/OP_OR_INT_LIT16.S */ 6591/* File: armv5te/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 mov r9, rINST, lsr #8 @ r9<- A+ 6608 GET_VREG(r0, r2) @ r0<- vB 6609 and r9, r9, #15 6610 .if 0 6611 cmp r1, #0 @ is second operand zero? 6612 beq common_errDivideByZero 6613 .endif 6614 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6615 6616 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6617 GET_INST_OPCODE(ip) @ extract opcode from rINST 6618 SET_VREG(r0, r9) @ vAA<- r0 6619 GOTO_OPCODE(ip) @ jump to next instruction 6620 /* 10-13 instructions */ 6621 6622 6623/* ------------------------------ */ 6624 .balign 64 6625.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6626/* File: armv5te/OP_XOR_INT_LIT16.S */ 6627/* File: armv5te/binopLit16.S */ 6628 /* 6629 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6630 * that specifies an instruction that performs "result = r0 op r1". 6631 * This could be an ARM instruction or a function call. (If the result 6632 * comes back in a register other than r0, you can override "result".) 6633 * 6634 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6635 * vCC (r1). Useful for integer division and modulus. 6636 * 6637 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6638 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6639 */ 6640 /* binop/lit16 vA, vB, #+CCCC */ 6641 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6642 mov r2, rINST, lsr #12 @ r2<- B 6643 mov r9, rINST, lsr #8 @ r9<- A+ 6644 GET_VREG(r0, r2) @ r0<- vB 6645 and r9, r9, #15 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 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6653 GET_INST_OPCODE(ip) @ extract opcode from rINST 6654 SET_VREG(r0, r9) @ vAA<- r0 6655 GOTO_OPCODE(ip) @ jump to next instruction 6656 /* 10-13 instructions */ 6657 6658 6659/* ------------------------------ */ 6660 .balign 64 6661.L_OP_ADD_INT_LIT8: /* 0xd8 */ 6662/* File: armv5te/OP_ADD_INT_LIT8.S */ 6663/* File: armv5te/binopLit8.S */ 6664 /* 6665 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6666 * that specifies an instruction that performs "result = r0 op r1". 6667 * This could be an ARM instruction or a function call. (If the result 6668 * comes back in a register other than r0, you can override "result".) 6669 * 6670 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6671 * vCC (r1). Useful for integer division and modulus. 6672 * 6673 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6674 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6675 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6676 */ 6677 /* binop/lit8 vAA, vBB, #+CC */ 6678 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6679 mov r9, rINST, lsr #8 @ r9<- AA 6680 and r2, r3, #255 @ r2<- BB 6681 GET_VREG(r0, r2) @ r0<- vBB 6682 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6683 .if 0 6684 @cmp r1, #0 @ is second operand zero? 6685 beq common_errDivideByZero 6686 .endif 6687 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6688 6689 @ optional op; may set condition codes 6690 add r0, r0, r1 @ r0<- op, r0-r3 changed 6691 GET_INST_OPCODE(ip) @ extract opcode from rINST 6692 SET_VREG(r0, r9) @ vAA<- r0 6693 GOTO_OPCODE(ip) @ jump to next instruction 6694 /* 10-12 instructions */ 6695 6696 6697/* ------------------------------ */ 6698 .balign 64 6699.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 6700/* File: armv5te/OP_RSUB_INT_LIT8.S */ 6701/* File: armv5te/binopLit8.S */ 6702 /* 6703 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6704 * that specifies an instruction that performs "result = r0 op r1". 6705 * This could be an ARM instruction or a function call. (If the result 6706 * comes back in a register other than r0, you can override "result".) 6707 * 6708 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6709 * vCC (r1). Useful for integer division and modulus. 6710 * 6711 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6712 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6713 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6714 */ 6715 /* binop/lit8 vAA, vBB, #+CC */ 6716 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6717 mov r9, rINST, lsr #8 @ r9<- AA 6718 and r2, r3, #255 @ r2<- BB 6719 GET_VREG(r0, r2) @ r0<- vBB 6720 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6721 .if 0 6722 @cmp r1, #0 @ is second operand zero? 6723 beq common_errDivideByZero 6724 .endif 6725 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6726 6727 @ optional op; may set condition codes 6728 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6729 GET_INST_OPCODE(ip) @ extract opcode from rINST 6730 SET_VREG(r0, r9) @ vAA<- r0 6731 GOTO_OPCODE(ip) @ jump to next instruction 6732 /* 10-12 instructions */ 6733 6734 6735/* ------------------------------ */ 6736 .balign 64 6737.L_OP_MUL_INT_LIT8: /* 0xda */ 6738/* File: armv5te/OP_MUL_INT_LIT8.S */ 6739/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6740/* File: armv5te/binopLit8.S */ 6741 /* 6742 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6743 * that specifies an instruction that performs "result = r0 op r1". 6744 * This could be an ARM instruction or a function call. (If the result 6745 * comes back in a register other than r0, you can override "result".) 6746 * 6747 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6748 * vCC (r1). Useful for integer division and modulus. 6749 * 6750 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6751 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6752 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6753 */ 6754 /* binop/lit8 vAA, vBB, #+CC */ 6755 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6756 mov r9, rINST, lsr #8 @ r9<- AA 6757 and r2, r3, #255 @ r2<- BB 6758 GET_VREG(r0, r2) @ r0<- vBB 6759 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6760 .if 0 6761 @cmp r1, #0 @ is second operand zero? 6762 beq common_errDivideByZero 6763 .endif 6764 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6765 6766 @ optional op; may set condition codes 6767 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6768 GET_INST_OPCODE(ip) @ extract opcode from rINST 6769 SET_VREG(r0, r9) @ vAA<- r0 6770 GOTO_OPCODE(ip) @ jump to next instruction 6771 /* 10-12 instructions */ 6772 6773 6774/* ------------------------------ */ 6775 .balign 64 6776.L_OP_DIV_INT_LIT8: /* 0xdb */ 6777/* File: armv5te/OP_DIV_INT_LIT8.S */ 6778/* File: armv5te/binopLit8.S */ 6779 /* 6780 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6781 * that specifies an instruction that performs "result = r0 op r1". 6782 * This could be an ARM instruction or a function call. (If the result 6783 * comes back in a register other than r0, you can override "result".) 6784 * 6785 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6786 * vCC (r1). Useful for integer division and modulus. 6787 * 6788 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6789 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6790 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6791 */ 6792 /* binop/lit8 vAA, vBB, #+CC */ 6793 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6794 mov r9, rINST, lsr #8 @ r9<- AA 6795 and r2, r3, #255 @ r2<- BB 6796 GET_VREG(r0, r2) @ r0<- vBB 6797 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6798 .if 1 6799 @cmp r1, #0 @ is second operand zero? 6800 beq common_errDivideByZero 6801 .endif 6802 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6803 6804 @ optional op; may set condition codes 6805 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6806 GET_INST_OPCODE(ip) @ extract opcode from rINST 6807 SET_VREG(r0, r9) @ vAA<- r0 6808 GOTO_OPCODE(ip) @ jump to next instruction 6809 /* 10-12 instructions */ 6810 6811 6812/* ------------------------------ */ 6813 .balign 64 6814.L_OP_REM_INT_LIT8: /* 0xdc */ 6815/* File: armv5te/OP_REM_INT_LIT8.S */ 6816/* idivmod returns quotient in r0 and remainder in r1 */ 6817/* File: armv5te/binopLit8.S */ 6818 /* 6819 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6820 * that specifies an instruction that performs "result = r0 op r1". 6821 * This could be an ARM instruction or a function call. (If the result 6822 * comes back in a register other than r0, you can override "result".) 6823 * 6824 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6825 * vCC (r1). Useful for integer division and modulus. 6826 * 6827 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6828 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6829 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6830 */ 6831 /* binop/lit8 vAA, vBB, #+CC */ 6832 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6833 mov r9, rINST, lsr #8 @ r9<- AA 6834 and r2, r3, #255 @ r2<- BB 6835 GET_VREG(r0, r2) @ r0<- vBB 6836 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6837 .if 1 6838 @cmp r1, #0 @ is second operand zero? 6839 beq common_errDivideByZero 6840 .endif 6841 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6842 6843 @ optional op; may set condition codes 6844 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6845 GET_INST_OPCODE(ip) @ extract opcode from rINST 6846 SET_VREG(r1, r9) @ vAA<- r1 6847 GOTO_OPCODE(ip) @ jump to next instruction 6848 /* 10-12 instructions */ 6849 6850 6851/* ------------------------------ */ 6852 .balign 64 6853.L_OP_AND_INT_LIT8: /* 0xdd */ 6854/* File: armv5te/OP_AND_INT_LIT8.S */ 6855/* File: armv5te/binopLit8.S */ 6856 /* 6857 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6858 * that specifies an instruction that performs "result = r0 op r1". 6859 * This could be an ARM instruction or a function call. (If the result 6860 * comes back in a register other than r0, you can override "result".) 6861 * 6862 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6863 * vCC (r1). Useful for integer division and modulus. 6864 * 6865 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6866 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6867 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6868 */ 6869 /* binop/lit8 vAA, vBB, #+CC */ 6870 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6871 mov r9, rINST, lsr #8 @ r9<- AA 6872 and r2, r3, #255 @ r2<- BB 6873 GET_VREG(r0, r2) @ r0<- vBB 6874 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6875 .if 0 6876 @cmp r1, #0 @ is second operand zero? 6877 beq common_errDivideByZero 6878 .endif 6879 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6880 6881 @ optional op; may set condition codes 6882 and r0, r0, r1 @ r0<- op, r0-r3 changed 6883 GET_INST_OPCODE(ip) @ extract opcode from rINST 6884 SET_VREG(r0, r9) @ vAA<- r0 6885 GOTO_OPCODE(ip) @ jump to next instruction 6886 /* 10-12 instructions */ 6887 6888 6889/* ------------------------------ */ 6890 .balign 64 6891.L_OP_OR_INT_LIT8: /* 0xde */ 6892/* File: armv5te/OP_OR_INT_LIT8.S */ 6893/* File: armv5te/binopLit8.S */ 6894 /* 6895 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6896 * that specifies an instruction that performs "result = r0 op r1". 6897 * This could be an ARM instruction or a function call. (If the result 6898 * comes back in a register other than r0, you can override "result".) 6899 * 6900 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6901 * vCC (r1). Useful for integer division and modulus. 6902 * 6903 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6904 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6905 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6906 */ 6907 /* binop/lit8 vAA, vBB, #+CC */ 6908 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6909 mov r9, rINST, lsr #8 @ r9<- AA 6910 and r2, r3, #255 @ r2<- BB 6911 GET_VREG(r0, r2) @ r0<- vBB 6912 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6913 .if 0 6914 @cmp r1, #0 @ is second operand zero? 6915 beq common_errDivideByZero 6916 .endif 6917 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6918 6919 @ optional op; may set condition codes 6920 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6921 GET_INST_OPCODE(ip) @ extract opcode from rINST 6922 SET_VREG(r0, r9) @ vAA<- r0 6923 GOTO_OPCODE(ip) @ jump to next instruction 6924 /* 10-12 instructions */ 6925 6926 6927/* ------------------------------ */ 6928 .balign 64 6929.L_OP_XOR_INT_LIT8: /* 0xdf */ 6930/* File: armv5te/OP_XOR_INT_LIT8.S */ 6931/* File: armv5te/binopLit8.S */ 6932 /* 6933 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6934 * that specifies an instruction that performs "result = r0 op r1". 6935 * This could be an ARM instruction or a function call. (If the result 6936 * comes back in a register other than r0, you can override "result".) 6937 * 6938 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6939 * vCC (r1). Useful for integer division and modulus. 6940 * 6941 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6942 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6943 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6944 */ 6945 /* binop/lit8 vAA, vBB, #+CC */ 6946 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6947 mov r9, rINST, lsr #8 @ r9<- AA 6948 and r2, r3, #255 @ r2<- BB 6949 GET_VREG(r0, r2) @ r0<- vBB 6950 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6951 .if 0 6952 @cmp r1, #0 @ is second operand zero? 6953 beq common_errDivideByZero 6954 .endif 6955 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6956 6957 @ optional op; may set condition codes 6958 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6959 GET_INST_OPCODE(ip) @ extract opcode from rINST 6960 SET_VREG(r0, r9) @ vAA<- r0 6961 GOTO_OPCODE(ip) @ jump to next instruction 6962 /* 10-12 instructions */ 6963 6964 6965/* ------------------------------ */ 6966 .balign 64 6967.L_OP_SHL_INT_LIT8: /* 0xe0 */ 6968/* File: armv5te/OP_SHL_INT_LIT8.S */ 6969/* File: armv5te/binopLit8.S */ 6970 /* 6971 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6972 * that specifies an instruction that performs "result = r0 op r1". 6973 * This could be an ARM instruction or a function call. (If the result 6974 * comes back in a register other than r0, you can override "result".) 6975 * 6976 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6977 * vCC (r1). Useful for integer division and modulus. 6978 * 6979 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6980 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6981 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6982 */ 6983 /* binop/lit8 vAA, vBB, #+CC */ 6984 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6985 mov r9, rINST, lsr #8 @ r9<- AA 6986 and r2, r3, #255 @ r2<- BB 6987 GET_VREG(r0, r2) @ r0<- vBB 6988 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6989 .if 0 6990 @cmp r1, #0 @ is second operand zero? 6991 beq common_errDivideByZero 6992 .endif 6993 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6994 6995 and r1, r1, #31 @ optional op; may set condition codes 6996 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 6997 GET_INST_OPCODE(ip) @ extract opcode from rINST 6998 SET_VREG(r0, r9) @ vAA<- r0 6999 GOTO_OPCODE(ip) @ jump to next instruction 7000 /* 10-12 instructions */ 7001 7002 7003/* ------------------------------ */ 7004 .balign 64 7005.L_OP_SHR_INT_LIT8: /* 0xe1 */ 7006/* File: armv5te/OP_SHR_INT_LIT8.S */ 7007/* File: armv5te/binopLit8.S */ 7008 /* 7009 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7010 * that specifies an instruction that performs "result = r0 op r1". 7011 * This could be an ARM instruction or a function call. (If the result 7012 * comes back in a register other than r0, you can override "result".) 7013 * 7014 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7015 * vCC (r1). Useful for integer division and modulus. 7016 * 7017 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7018 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7019 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7020 */ 7021 /* binop/lit8 vAA, vBB, #+CC */ 7022 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7023 mov r9, rINST, lsr #8 @ r9<- AA 7024 and r2, r3, #255 @ r2<- BB 7025 GET_VREG(r0, r2) @ r0<- vBB 7026 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7027 .if 0 7028 @cmp r1, #0 @ is second operand zero? 7029 beq common_errDivideByZero 7030 .endif 7031 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7032 7033 and r1, r1, #31 @ optional op; may set condition codes 7034 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7035 GET_INST_OPCODE(ip) @ extract opcode from rINST 7036 SET_VREG(r0, r9) @ vAA<- r0 7037 GOTO_OPCODE(ip) @ jump to next instruction 7038 /* 10-12 instructions */ 7039 7040 7041/* ------------------------------ */ 7042 .balign 64 7043.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7044/* File: armv5te/OP_USHR_INT_LIT8.S */ 7045/* File: armv5te/binopLit8.S */ 7046 /* 7047 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7048 * that specifies an instruction that performs "result = r0 op r1". 7049 * This could be an ARM instruction or a function call. (If the result 7050 * comes back in a register other than r0, you can override "result".) 7051 * 7052 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7053 * vCC (r1). Useful for integer division and modulus. 7054 * 7055 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7056 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7057 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7058 */ 7059 /* binop/lit8 vAA, vBB, #+CC */ 7060 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7061 mov r9, rINST, lsr #8 @ r9<- AA 7062 and r2, r3, #255 @ r2<- BB 7063 GET_VREG(r0, r2) @ r0<- vBB 7064 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7065 .if 0 7066 @cmp r1, #0 @ is second operand zero? 7067 beq common_errDivideByZero 7068 .endif 7069 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7070 7071 and r1, r1, #31 @ optional op; may set condition codes 7072 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7073 GET_INST_OPCODE(ip) @ extract opcode from rINST 7074 SET_VREG(r0, r9) @ vAA<- r0 7075 GOTO_OPCODE(ip) @ jump to next instruction 7076 /* 10-12 instructions */ 7077 7078 7079/* ------------------------------ */ 7080 .balign 64 7081.L_OP_IGET_VOLATILE: /* 0xe3 */ 7082/* File: armv5te/OP_IGET_VOLATILE.S */ 7083/* File: armv5te/OP_IGET.S */ 7084 /* 7085 * General 32-bit instance field get. 7086 * 7087 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7088 */ 7089 /* op vA, vB, field@CCCC */ 7090 mov r0, rINST, lsr #12 @ r0<- B 7091 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7092 FETCH(r1, 1) @ r1<- field ref CCCC 7093 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7094 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7095 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7096 cmp r0, #0 @ is resolved entry null? 7097 bne .LOP_IGET_VOLATILE_finish @ no, already resolved 70988: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7099 EXPORT_PC() @ resolve() could throw 7100 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7101 bl dvmResolveInstField @ r0<- resolved InstField ptr 7102 cmp r0, #0 7103 bne .LOP_IGET_VOLATILE_finish 7104 b common_exceptionThrown 7105 7106 7107/* ------------------------------ */ 7108 .balign 64 7109.L_OP_IPUT_VOLATILE: /* 0xe4 */ 7110/* File: armv5te/OP_IPUT_VOLATILE.S */ 7111/* File: armv5te/OP_IPUT.S */ 7112 /* 7113 * General 32-bit instance field put. 7114 * 7115 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 7116 */ 7117 /* op vA, vB, field@CCCC */ 7118 mov r0, rINST, lsr #12 @ r0<- B 7119 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7120 FETCH(r1, 1) @ r1<- field ref CCCC 7121 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7122 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7123 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7124 cmp r0, #0 @ is resolved entry null? 7125 bne .LOP_IPUT_VOLATILE_finish @ no, already resolved 71268: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7127 EXPORT_PC() @ resolve() could throw 7128 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7129 bl dvmResolveInstField @ r0<- resolved InstField ptr 7130 cmp r0, #0 @ success? 7131 bne .LOP_IPUT_VOLATILE_finish @ yes, finish up 7132 b common_exceptionThrown 7133 7134 7135/* ------------------------------ */ 7136 .balign 64 7137.L_OP_SGET_VOLATILE: /* 0xe5 */ 7138/* File: armv5te/OP_SGET_VOLATILE.S */ 7139/* File: armv5te/OP_SGET.S */ 7140 /* 7141 * General 32-bit SGET handler. 7142 * 7143 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7144 */ 7145 /* op vAA, field@BBBB */ 7146 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7147 FETCH(r1, 1) @ r1<- field ref BBBB 7148 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7149 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7150 cmp r0, #0 @ is resolved entry null? 7151 beq .LOP_SGET_VOLATILE_resolve @ yes, do resolve 7152.LOP_SGET_VOLATILE_finish: @ field ptr in r0 7153 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7154 SMP_DMB @ acquiring load 7155 mov r2, rINST, lsr #8 @ r2<- AA 7156 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7157 SET_VREG(r1, r2) @ fp[AA]<- r1 7158 GET_INST_OPCODE(ip) @ extract opcode from rINST 7159 GOTO_OPCODE(ip) @ jump to next instruction 7160 7161 7162/* ------------------------------ */ 7163 .balign 64 7164.L_OP_SPUT_VOLATILE: /* 0xe6 */ 7165/* File: armv5te/OP_SPUT_VOLATILE.S */ 7166/* File: armv5te/OP_SPUT.S */ 7167 /* 7168 * General 32-bit SPUT handler. 7169 * 7170 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 7171 */ 7172 /* op vAA, field@BBBB */ 7173 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7174 FETCH(r1, 1) @ r1<- field ref BBBB 7175 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7176 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7177 cmp r0, #0 @ is resolved entry null? 7178 beq .LOP_SPUT_VOLATILE_resolve @ yes, do resolve 7179.LOP_SPUT_VOLATILE_finish: @ field ptr in r0 7180 mov r2, rINST, lsr #8 @ r2<- AA 7181 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7182 GET_VREG(r1, r2) @ r1<- fp[AA] 7183 GET_INST_OPCODE(ip) @ extract opcode from rINST 7184 SMP_DMB @ releasing store 7185 str r1, [r0, #offStaticField_value] @ field<- vAA 7186 GOTO_OPCODE(ip) @ jump to next instruction 7187 7188 7189/* ------------------------------ */ 7190 .balign 64 7191.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ 7192/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */ 7193/* File: armv5te/OP_IGET.S */ 7194 /* 7195 * General 32-bit instance field get. 7196 * 7197 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7198 */ 7199 /* op vA, vB, field@CCCC */ 7200 mov r0, rINST, lsr #12 @ r0<- B 7201 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7202 FETCH(r1, 1) @ r1<- field ref CCCC 7203 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7204 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7205 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7206 cmp r0, #0 @ is resolved entry null? 7207 bne .LOP_IGET_OBJECT_VOLATILE_finish @ no, already resolved 72088: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7209 EXPORT_PC() @ resolve() could throw 7210 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7211 bl dvmResolveInstField @ r0<- resolved InstField ptr 7212 cmp r0, #0 7213 bne .LOP_IGET_OBJECT_VOLATILE_finish 7214 b common_exceptionThrown 7215 7216 7217/* ------------------------------ */ 7218 .balign 64 7219.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */ 7220/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */ 7221/* File: armv5te/OP_IGET_WIDE.S */ 7222 /* 7223 * Wide 32-bit instance field get. 7224 */ 7225 /* iget-wide vA, vB, field@CCCC */ 7226 mov r0, rINST, lsr #12 @ r0<- B 7227 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7228 FETCH(r1, 1) @ r1<- field ref CCCC 7229 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7230 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7231 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7232 cmp r0, #0 @ is resolved entry null? 7233 bne .LOP_IGET_WIDE_VOLATILE_finish @ no, already resolved 72348: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7235 EXPORT_PC() @ resolve() could throw 7236 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7237 bl dvmResolveInstField @ r0<- resolved InstField ptr 7238 cmp r0, #0 7239 bne .LOP_IGET_WIDE_VOLATILE_finish 7240 b common_exceptionThrown 7241 7242 7243/* ------------------------------ */ 7244 .balign 64 7245.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */ 7246/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */ 7247/* File: armv5te/OP_IPUT_WIDE.S */ 7248 /* iput-wide vA, vB, field@CCCC */ 7249 mov r0, rINST, lsr #12 @ r0<- B 7250 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7251 FETCH(r1, 1) @ r1<- field ref CCCC 7252 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7253 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7254 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7255 cmp r0, #0 @ is resolved entry null? 7256 bne .LOP_IPUT_WIDE_VOLATILE_finish @ no, already resolved 72578: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7258 EXPORT_PC() @ resolve() could throw 7259 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7260 bl dvmResolveInstField @ r0<- resolved InstField ptr 7261 cmp r0, #0 @ success? 7262 bne .LOP_IPUT_WIDE_VOLATILE_finish @ yes, finish up 7263 b common_exceptionThrown 7264 7265 7266/* ------------------------------ */ 7267 .balign 64 7268.L_OP_SGET_WIDE_VOLATILE: /* 0xea */ 7269/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */ 7270/* File: armv5te/OP_SGET_WIDE.S */ 7271 /* 7272 * 64-bit SGET handler. 7273 */ 7274 /* sget-wide vAA, field@BBBB */ 7275 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7276 FETCH(r1, 1) @ r1<- field ref BBBB 7277 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7278 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7279 cmp r0, #0 @ is resolved entry null? 7280 beq .LOP_SGET_WIDE_VOLATILE_resolve @ yes, do resolve 7281.LOP_SGET_WIDE_VOLATILE_finish: 7282 mov r9, rINST, lsr #8 @ r9<- AA 7283 .if 1 7284 add r0, r0, #offStaticField_value @ r0<- pointer to data 7285 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 7286 .else 7287 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 7288 .endif 7289 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7290 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7291 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 7292 GET_INST_OPCODE(ip) @ extract opcode from rINST 7293 GOTO_OPCODE(ip) @ jump to next instruction 7294 7295 7296/* ------------------------------ */ 7297 .balign 64 7298.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */ 7299/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */ 7300/* File: armv5te/OP_SPUT_WIDE.S */ 7301 /* 7302 * 64-bit SPUT handler. 7303 */ 7304 /* sput-wide vAA, field@BBBB */ 7305 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 7306 FETCH(r1, 1) @ r1<- field ref BBBB 7307 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 7308 mov r9, rINST, lsr #8 @ r9<- AA 7309 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 7310 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7311 cmp r2, #0 @ is resolved entry null? 7312 beq .LOP_SPUT_WIDE_VOLATILE_resolve @ yes, do resolve 7313.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9 7314 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7315 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 7316 GET_INST_OPCODE(r10) @ extract opcode from rINST 7317 .if 1 7318 add r2, r2, #offStaticField_value @ r2<- pointer to data 7319 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 7320 .else 7321 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 7322 .endif 7323 GOTO_OPCODE(r10) @ jump to next instruction 7324 7325 7326/* ------------------------------ */ 7327 .balign 64 7328.L_OP_BREAKPOINT: /* 0xec */ 7329/* File: armv5te/OP_BREAKPOINT.S */ 7330/* File: armv5te/unused.S */ 7331 bl common_abort 7332 7333 7334/* ------------------------------ */ 7335 .balign 64 7336.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7337/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7338 /* 7339 * Handle a throw-verification-error instruction. This throws an 7340 * exception for an error discovered during verification. The 7341 * exception is indicated by AA, with some detail provided by BBBB. 7342 */ 7343 /* op AA, ref@BBBB */ 7344 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7345 FETCH(r2, 1) @ r2<- BBBB 7346 EXPORT_PC() @ export the PC 7347 mov r1, rINST, lsr #8 @ r1<- AA 7348 bl dvmThrowVerificationError @ always throws 7349 b common_exceptionThrown @ handle exception 7350 7351/* ------------------------------ */ 7352 .balign 64 7353.L_OP_EXECUTE_INLINE: /* 0xee */ 7354/* File: armv5te/OP_EXECUTE_INLINE.S */ 7355 /* 7356 * Execute a "native inline" instruction. 7357 * 7358 * We need to call an InlineOp4Func: 7359 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7360 * 7361 * The first four args are in r0-r3, pointer to return value storage 7362 * is on the stack. The function's return value is a flag that tells 7363 * us if an exception was thrown. 7364 */ 7365 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7366 FETCH(r10, 1) @ r10<- BBBB 7367 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7368 EXPORT_PC() @ can throw 7369 sub sp, sp, #8 @ make room for arg, +64 bit align 7370 mov r0, rINST, lsr #12 @ r0<- B 7371 str r1, [sp] @ push &glue->retval 7372 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7373 add sp, sp, #8 @ pop stack 7374 cmp r0, #0 @ test boolean result of inline 7375 beq common_exceptionThrown @ returned false, handle exception 7376 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7377 GET_INST_OPCODE(ip) @ extract opcode from rINST 7378 GOTO_OPCODE(ip) @ jump to next instruction 7379 7380/* ------------------------------ */ 7381 .balign 64 7382.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ 7383/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */ 7384 /* 7385 * Execute a "native inline" instruction, using "/range" semantics. 7386 * Same idea as execute-inline, but we get the args differently. 7387 * 7388 * We need to call an InlineOp4Func: 7389 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7390 * 7391 * The first four args are in r0-r3, pointer to return value storage 7392 * is on the stack. The function's return value is a flag that tells 7393 * us if an exception was thrown. 7394 */ 7395 /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */ 7396 FETCH(r10, 1) @ r10<- BBBB 7397 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7398 EXPORT_PC() @ can throw 7399 sub sp, sp, #8 @ make room for arg, +64 bit align 7400 mov r0, rINST, lsr #8 @ r0<- AA 7401 str r1, [sp] @ push &glue->retval 7402 bl .LOP_EXECUTE_INLINE_RANGE_continue @ make call; will return after 7403 add sp, sp, #8 @ pop stack 7404 cmp r0, #0 @ test boolean result of inline 7405 beq common_exceptionThrown @ returned false, handle exception 7406 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7407 GET_INST_OPCODE(ip) @ extract opcode from rINST 7408 GOTO_OPCODE(ip) @ jump to next instruction 7409 7410/* ------------------------------ */ 7411 .balign 64 7412.L_OP_INVOKE_OBJECT_INIT: /* 0xf0 */ 7413/* File: armv5te/OP_INVOKE_OBJECT_INIT.S */ 7414 /* 7415 * invoke-object-init is a no-op in a "standard" interpreter. 7416 */ 7417 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7418 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7419 GOTO_OPCODE(ip) @ execute it 7420 7421/* ------------------------------ */ 7422 .balign 64 7423.L_OP_RETURN_VOID_BARRIER: /* 0xf1 */ 7424/* File: armv5te/OP_RETURN_VOID_BARRIER.S */ 7425 SMP_DMB_ST 7426 b common_returnFromMethod 7427 7428/* ------------------------------ */ 7429 .balign 64 7430.L_OP_IGET_QUICK: /* 0xf2 */ 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 .balign 64 7449.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7450/* File: armv5te/OP_IGET_WIDE_QUICK.S */ 7451 /* iget-wide-quick vA, vB, offset@CCCC */ 7452 mov r2, rINST, lsr #12 @ r2<- B 7453 GET_VREG(r3, r2) @ r3<- object we're operating on 7454 FETCH(ip, 1) @ ip<- field byte offset 7455 cmp r3, #0 @ check object for null 7456 mov r2, rINST, lsr #8 @ r2<- A(+) 7457 beq common_errNullObject @ object was null 7458 ldrd r0, [r3, ip] @ r0<- obj.field (64 bits, aligned) 7459 and r2, r2, #15 7460 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7461 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7462 GET_INST_OPCODE(ip) @ extract opcode from rINST 7463 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7464 GOTO_OPCODE(ip) @ jump to next instruction 7465 7466/* ------------------------------ */ 7467 .balign 64 7468.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7469/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7470/* File: armv5te/OP_IGET_QUICK.S */ 7471 /* For: iget-quick, iget-object-quick */ 7472 /* op vA, vB, offset@CCCC */ 7473 mov r2, rINST, lsr #12 @ r2<- B 7474 GET_VREG(r3, r2) @ r3<- object we're operating on 7475 FETCH(r1, 1) @ r1<- field byte offset 7476 cmp r3, #0 @ check object for null 7477 mov r2, rINST, lsr #8 @ r2<- A(+) 7478 beq common_errNullObject @ object was null 7479 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7480 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7481 and r2, r2, #15 7482 GET_INST_OPCODE(ip) @ extract opcode from rINST 7483 SET_VREG(r0, r2) @ fp[A]<- r0 7484 GOTO_OPCODE(ip) @ jump to next instruction 7485 7486 7487/* ------------------------------ */ 7488 .balign 64 7489.L_OP_IPUT_QUICK: /* 0xf5 */ 7490/* File: armv5te/OP_IPUT_QUICK.S */ 7491 /* For: iput-quick */ 7492 /* op vA, vB, offset@CCCC */ 7493 mov r2, rINST, lsr #12 @ r2<- B 7494 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7495 FETCH(r1, 1) @ r1<- field byte offset 7496 cmp r3, #0 @ check object for null 7497 mov r2, rINST, lsr #8 @ r2<- A(+) 7498 beq common_errNullObject @ object was null 7499 and r2, r2, #15 7500 GET_VREG(r0, r2) @ r0<- fp[A] 7501 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7502 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 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_IPUT_WIDE_QUICK: /* 0xf6 */ 7509/* File: armv5te/OP_IPUT_WIDE_QUICK.S */ 7510 /* iput-wide-quick vA, vB, offset@CCCC */ 7511 mov r0, rINST, lsr #8 @ r0<- A(+) 7512 mov r1, rINST, lsr #12 @ r1<- B 7513 and r0, r0, #15 7514 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7515 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7516 cmp r2, #0 @ check object for null 7517 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7518 beq common_errNullObject @ object was null 7519 FETCH(r3, 1) @ r3<- field byte offset 7520 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7521 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7522 GET_INST_OPCODE(ip) @ extract opcode from rINST 7523 GOTO_OPCODE(ip) @ jump to next instruction 7524 7525/* ------------------------------ */ 7526 .balign 64 7527.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7528/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7529 /* For: iput-object-quick */ 7530 /* op vA, vB, offset@CCCC */ 7531 mov r2, rINST, lsr #12 @ r2<- B 7532 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7533 FETCH(r1, 1) @ r1<- field byte offset 7534 cmp r3, #0 @ check object for null 7535 mov r2, rINST, lsr #8 @ r2<- A(+) 7536 beq common_errNullObject @ object was null 7537 and r2, r2, #15 7538 GET_VREG(r0, r2) @ r0<- fp[A] 7539 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 7540 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7541 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7542 cmp r0, #0 7543 strneb r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head 7544 GET_INST_OPCODE(ip) @ extract opcode from rINST 7545 GOTO_OPCODE(ip) @ jump to next instruction 7546 7547/* ------------------------------ */ 7548 .balign 64 7549.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7550/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7551 /* 7552 * Handle an optimized virtual method call. 7553 * 7554 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7555 */ 7556 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7557 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7558 FETCH(r3, 2) @ r3<- FEDC or CCCC 7559 FETCH(r1, 1) @ r1<- BBBB 7560 .if (!0) 7561 and r3, r3, #15 @ r3<- C (or stays CCCC) 7562 .endif 7563 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7564 cmp r2, #0 @ is "this" null? 7565 beq common_errNullObject @ null "this", throw exception 7566 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7567 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7568 EXPORT_PC() @ invoke must export 7569 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7570 bl common_invokeMethodNoRange @ continue on 7571 7572/* ------------------------------ */ 7573 .balign 64 7574.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7575/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7576/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7577 /* 7578 * Handle an optimized virtual method call. 7579 * 7580 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7581 */ 7582 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7583 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7584 FETCH(r3, 2) @ r3<- FEDC or CCCC 7585 FETCH(r1, 1) @ r1<- BBBB 7586 .if (!1) 7587 and r3, r3, #15 @ r3<- C (or stays CCCC) 7588 .endif 7589 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7590 cmp r2, #0 @ is "this" null? 7591 beq common_errNullObject @ null "this", throw exception 7592 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7593 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7594 EXPORT_PC() @ invoke must export 7595 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7596 bl common_invokeMethodRange @ continue on 7597 7598 7599/* ------------------------------ */ 7600 .balign 64 7601.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7602/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7603 /* 7604 * Handle an optimized "super" method call. 7605 * 7606 * for: [opt] invoke-super-quick, invoke-super-quick/range 7607 */ 7608 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7609 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7610 FETCH(r10, 2) @ r10<- GFED or CCCC 7611 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7612 .if (!0) 7613 and r10, r10, #15 @ r10<- D (or stays CCCC) 7614 .endif 7615 FETCH(r1, 1) @ r1<- BBBB 7616 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7617 EXPORT_PC() @ must export for invoke 7618 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7619 GET_VREG(r3, r10) @ r3<- "this" 7620 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7621 cmp r3, #0 @ null "this" ref? 7622 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7623 beq common_errNullObject @ "this" is null, throw exception 7624 bl common_invokeMethodNoRange @ continue on 7625 7626/* ------------------------------ */ 7627 .balign 64 7628.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7629/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7630/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7631 /* 7632 * Handle an optimized "super" method call. 7633 * 7634 * for: [opt] invoke-super-quick, invoke-super-quick/range 7635 */ 7636 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7637 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7638 FETCH(r10, 2) @ r10<- GFED or CCCC 7639 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7640 .if (!1) 7641 and r10, r10, #15 @ r10<- D (or stays CCCC) 7642 .endif 7643 FETCH(r1, 1) @ r1<- BBBB 7644 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7645 EXPORT_PC() @ must export for invoke 7646 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7647 GET_VREG(r3, r10) @ r3<- "this" 7648 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7649 cmp r3, #0 @ null "this" ref? 7650 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7651 beq common_errNullObject @ "this" is null, throw exception 7652 bl common_invokeMethodRange @ continue on 7653 7654 7655/* ------------------------------ */ 7656 .balign 64 7657.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ 7658/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */ 7659/* File: armv5te/OP_IPUT_OBJECT.S */ 7660 /* 7661 * 32-bit instance field put. 7662 * 7663 * for: iput-object, iput-object-volatile 7664 */ 7665 /* op vA, vB, field@CCCC */ 7666 mov r0, rINST, lsr #12 @ r0<- B 7667 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7668 FETCH(r1, 1) @ r1<- field ref CCCC 7669 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7670 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7671 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7672 cmp r0, #0 @ is resolved entry null? 7673 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ no, already resolved 76748: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7675 EXPORT_PC() @ resolve() could throw 7676 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7677 bl dvmResolveInstField @ r0<- resolved InstField ptr 7678 cmp r0, #0 @ success? 7679 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ yes, finish up 7680 b common_exceptionThrown 7681 7682 7683/* ------------------------------ */ 7684 .balign 64 7685.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ 7686/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */ 7687/* File: armv5te/OP_SGET.S */ 7688 /* 7689 * General 32-bit SGET handler. 7690 * 7691 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7692 */ 7693 /* op vAA, field@BBBB */ 7694 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7695 FETCH(r1, 1) @ r1<- field ref BBBB 7696 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7697 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7698 cmp r0, #0 @ is resolved entry null? 7699 beq .LOP_SGET_OBJECT_VOLATILE_resolve @ yes, do resolve 7700.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0 7701 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7702 SMP_DMB @ acquiring load 7703 mov r2, rINST, lsr #8 @ r2<- AA 7704 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7705 SET_VREG(r1, r2) @ fp[AA]<- r1 7706 GET_INST_OPCODE(ip) @ extract opcode from rINST 7707 GOTO_OPCODE(ip) @ jump to next instruction 7708 7709 7710/* ------------------------------ */ 7711 .balign 64 7712.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ 7713/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */ 7714/* File: armv5te/OP_SPUT_OBJECT.S */ 7715 /* 7716 * 32-bit SPUT handler for objects 7717 * 7718 * for: sput-object, sput-object-volatile 7719 */ 7720 /* op vAA, field@BBBB */ 7721 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7722 FETCH(r1, 1) @ r1<- field ref BBBB 7723 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7724 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7725 cmp r0, #0 @ is resolved entry null? 7726 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ no, continue 7727 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 7728 EXPORT_PC() @ resolve() could throw, so export now 7729 ldr r0, [r9, #offMethod_clazz] @ r0<- method->clazz 7730 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 7731 cmp r0, #0 @ success? 7732 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish 7733 b common_exceptionThrown @ no, handle exception 7734 7735 7736 7737/* ------------------------------ */ 7738 .balign 64 7739.L_OP_DISPATCH_FF: /* 0xff */ 7740/* File: armv5te/OP_DISPATCH_FF.S */ 7741 mov ip, rINST, lsr #8 @ r9<- extended opcode 7742 add ip, ip, #256 @ add offset for extended opcodes 7743 GOTO_OPCODE(ip) @ go to proper extended handler 7744 7745 7746/* ------------------------------ */ 7747 .balign 64 7748.L_OP_CONST_CLASS_JUMBO: /* 0x100 */ 7749/* File: armv5te/OP_CONST_CLASS_JUMBO.S */ 7750 /* const-class/jumbo vBBBB, Class@AAAAAAAA */ 7751 FETCH(r0, 1) @ r0<- aaaa (lo) 7752 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 7753 FETCH(r1, 2) @ r1<- AAAA (hi) 7754 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 7755 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 7756 FETCH(r9, 3) @ r9<- BBBB 7757 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[AAAAaaaa] 7758 cmp r0, #0 @ not yet resolved? 7759 beq .LOP_CONST_CLASS_JUMBO_resolve 7760 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 7761 GET_INST_OPCODE(ip) @ extract opcode from rINST 7762 SET_VREG(r0, r9) @ vBBBB<- r0 7763 GOTO_OPCODE(ip) @ jump to next instruction 7764 7765/* ------------------------------ */ 7766 .balign 64 7767.L_OP_CHECK_CAST_JUMBO: /* 0x101 */ 7768/* File: armv5te/OP_CHECK_CAST_JUMBO.S */ 7769 /* 7770 * Check to see if a cast from one class to another is allowed. 7771 */ 7772 /* check-cast/jumbo vBBBB, class@AAAAAAAA */ 7773 FETCH(r0, 1) @ r0<- aaaa (lo) 7774 FETCH(r2, 2) @ r2<- AAAA (hi) 7775 FETCH(r3, 3) @ r3<- BBBB 7776 orr r2, r0, r2, lsl #16 @ r2<- AAAAaaaa 7777 GET_VREG(r9, r3) @ r9<- object 7778 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 7779 cmp r9, #0 @ is object null? 7780 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 7781 beq .LOP_CHECK_CAST_JUMBO_okay @ null obj, cast always succeeds 7782 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 7783 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7784 cmp r1, #0 @ have we resolved this before? 7785 beq .LOP_CHECK_CAST_JUMBO_resolve @ not resolved, do it now 7786.LOP_CHECK_CAST_JUMBO_resolved: 7787 cmp r0, r1 @ same class (trivial success)? 7788 bne .LOP_CHECK_CAST_JUMBO_fullcheck @ no, do full check 7789 b .LOP_CHECK_CAST_JUMBO_okay @ yes, finish up 7790 7791/* ------------------------------ */ 7792 .balign 64 7793.L_OP_INSTANCE_OF_JUMBO: /* 0x102 */ 7794/* File: armv5te/OP_INSTANCE_OF_JUMBO.S */ 7795 /* 7796 * Check to see if an object reference is an instance of a class. 7797 * 7798 * Most common situation is a non-null object, being compared against 7799 * an already-resolved class. 7800 * 7801 * TODO: convert most of this into a common subroutine, shared with 7802 * OP_INSTANCE_OF.S. 7803 */ 7804 /* instance-of/jumbo vBBBB, vCCCC, class@AAAAAAAA */ 7805 FETCH(r3, 4) @ r3<- vCCCC 7806 FETCH(r9, 3) @ r9<- vBBBB 7807 GET_VREG(r0, r3) @ r0<- vCCCC (object) 7808 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 7809 cmp r0, #0 @ is object null? 7810 beq .LOP_INSTANCE_OF_JUMBO_store @ null obj, not an instance, store r0 7811 FETCH(r1, 1) @ r1<- aaaa (lo) 7812 FETCH(r3, 2) @ r3<- AAAA (hi) 7813 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 7814 orr r3, r1, r3, lsl #16 @ r3<- AAAAaaaa 7815 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 7816 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7817 cmp r1, #0 @ have we resolved this before? 7818 beq .LOP_INSTANCE_OF_JUMBO_resolve @ not resolved, do it now 7819 b .LOP_INSTANCE_OF_JUMBO_resolved @ resolved, continue 7820 7821/* ------------------------------ */ 7822 .balign 64 7823.L_OP_NEW_INSTANCE_JUMBO: /* 0x103 */ 7824/* File: armv5te/OP_NEW_INSTANCE_JUMBO.S */ 7825 /* 7826 * Create a new instance of a class. 7827 */ 7828 /* new-instance/jumbo vBBBB, class@AAAAAAAA */ 7829 FETCH(r0, 1) @ r0<- aaaa (lo) 7830 FETCH(r1, 2) @ r1<- AAAA (hi) 7831 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 7832 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 7833 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 7834 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 7835 EXPORT_PC() @ req'd for init, resolve, alloc 7836 cmp r0, #0 @ already resolved? 7837 beq .LOP_NEW_INSTANCE_JUMBO_resolve @ no, resolve it now 7838.LOP_NEW_INSTANCE_JUMBO_resolved: @ r0=class 7839 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 7840 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 7841 bne .LOP_NEW_INSTANCE_JUMBO_needinit @ no, init class now 7842.LOP_NEW_INSTANCE_JUMBO_initialized: @ r0=class 7843 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 7844 bl dvmAllocObject @ r0<- new object 7845 b .LOP_NEW_INSTANCE_JUMBO_finish @ continue 7846 7847/* ------------------------------ */ 7848 .balign 64 7849.L_OP_NEW_ARRAY_JUMBO: /* 0x104 */ 7850/* File: armv5te/OP_NEW_ARRAY_JUMBO.S */ 7851 /* 7852 * Allocate an array of objects, specified with the array class 7853 * and a count. 7854 * 7855 * The verifier guarantees that this is an array class, so we don't 7856 * check for it here. 7857 */ 7858 /* new-array/jumbo vBBBB, vCCCC, class@AAAAAAAA */ 7859 FETCH(r2, 1) @ r2<- aaaa (lo) 7860 FETCH(r3, 2) @ r3<- AAAA (hi) 7861 FETCH(r0, 4) @ r0<- vCCCC 7862 orr r2, r2, r3, lsl #16 @ r2<- AAAAaaaa 7863 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 7864 GET_VREG(r1, r0) @ r1<- vCCCC (array length) 7865 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 7866 cmp r1, #0 @ check length 7867 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 7868 bmi common_errNegativeArraySize @ negative length, bail 7869 cmp r0, #0 @ already resolved? 7870 EXPORT_PC() @ req'd for resolve, alloc 7871 bne .LOP_NEW_ARRAY_JUMBO_finish @ resolved, continue 7872 b .LOP_NEW_ARRAY_JUMBO_resolve @ do resolve now 7873 7874/* ------------------------------ */ 7875 .balign 64 7876.L_OP_FILLED_NEW_ARRAY_JUMBO: /* 0x105 */ 7877/* File: armv5te/OP_FILLED_NEW_ARRAY_JUMBO.S */ 7878 /* 7879 * Create a new array with elements filled from registers. 7880 * 7881 * TODO: convert most of this into a common subroutine, shared with 7882 * OP_FILLED_NEW_ARRAY.S. 7883 */ 7884 /* filled-new-array/jumbo {vCCCC..v(CCCC+BBBB-1)}, type@AAAAAAAA */ 7885 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 7886 FETCH(r0, 1) @ r0<- aaaa (lo) 7887 FETCH(r1, 2) @ r1<- AAAA (hi) 7888 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 7889 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 7890 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 7891 EXPORT_PC() @ need for resolve and alloc 7892 cmp r0, #0 @ already resolved? 7893 bne .LOP_FILLED_NEW_ARRAY_JUMBO_continue @ yes, continue on 78948: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7895 mov r2, #0 @ r2<- false 7896 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7897 bl dvmResolveClass @ r0<- call(clazz, ref) 7898 cmp r0, #0 @ got null? 7899 beq common_exceptionThrown @ yes, handle exception 7900 b .LOP_FILLED_NEW_ARRAY_JUMBO_continue 7901 7902/* ------------------------------ */ 7903 .balign 64 7904.L_OP_IGET_JUMBO: /* 0x106 */ 7905/* File: armv5te/OP_IGET_JUMBO.S */ 7906 /* 7907 * Jumbo 32-bit instance field get. 7908 * 7909 * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo, 7910 * iget-char/jumbo, iget-short/jumbo 7911 */ 7912 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 7913 FETCH(r1, 1) @ r1<- aaaa (lo) 7914 FETCH(r2, 2) @ r2<- AAAA (hi) 7915 FETCH(r0, 4) @ r0<- CCCC 7916 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7917 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 7918 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7919 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 7920 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7921 cmp r0, #0 @ is resolved entry null? 7922 bne .LOP_IGET_JUMBO_finish @ no, already resolved 79238: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7924 EXPORT_PC() @ resolve() could throw 7925 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7926 bl dvmResolveInstField @ r0<- resolved InstField ptr 7927 b .LOP_IGET_JUMBO_resolved @ resolved, continue 7928 7929/* ------------------------------ */ 7930 .balign 64 7931.L_OP_IGET_WIDE_JUMBO: /* 0x107 */ 7932/* File: armv5te/OP_IGET_WIDE_JUMBO.S */ 7933 /* 7934 * Jumbo 64-bit instance field get. 7935 */ 7936 /* iget-wide/jumbo vBBBB, vCCCC, field@AAAAAAAA */ 7937 FETCH(r1, 1) @ r1<- aaaa (lo) 7938 FETCH(r2, 2) @ r2<- AAAA (hi) 7939 FETCH(r0, 4) @ r0<- CCCC 7940 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7941 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 7942 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7943 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 7944 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7945 cmp r0, #0 @ is resolved entry null? 7946 bne .LOP_IGET_WIDE_JUMBO_finish @ no, already resolved 79478: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7948 EXPORT_PC() @ resolve() could throw 7949 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7950 bl dvmResolveInstField @ r0<- resolved InstField ptr 7951 b .LOP_IGET_WIDE_JUMBO_resolved @ resolved, continue 7952 7953/* ------------------------------ */ 7954 .balign 64 7955.L_OP_IGET_OBJECT_JUMBO: /* 0x108 */ 7956/* File: armv5te/OP_IGET_OBJECT_JUMBO.S */ 7957/* File: armv5te/OP_IGET_JUMBO.S */ 7958 /* 7959 * Jumbo 32-bit instance field get. 7960 * 7961 * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo, 7962 * iget-char/jumbo, iget-short/jumbo 7963 */ 7964 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 7965 FETCH(r1, 1) @ r1<- aaaa (lo) 7966 FETCH(r2, 2) @ r2<- AAAA (hi) 7967 FETCH(r0, 4) @ r0<- CCCC 7968 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7969 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 7970 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7971 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 7972 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7973 cmp r0, #0 @ is resolved entry null? 7974 bne .LOP_IGET_OBJECT_JUMBO_finish @ no, already resolved 79758: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7976 EXPORT_PC() @ resolve() could throw 7977 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7978 bl dvmResolveInstField @ r0<- resolved InstField ptr 7979 b .LOP_IGET_OBJECT_JUMBO_resolved @ resolved, continue 7980 7981 7982/* ------------------------------ */ 7983 .balign 64 7984.L_OP_IGET_BOOLEAN_JUMBO: /* 0x109 */ 7985/* File: armv5te/OP_IGET_BOOLEAN_JUMBO.S */ 7986@include "armv5te/OP_IGET_JUMBO.S" { "load":"ldrb", "sqnum":"1" } 7987/* File: armv5te/OP_IGET_JUMBO.S */ 7988 /* 7989 * Jumbo 32-bit instance field get. 7990 * 7991 * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo, 7992 * iget-char/jumbo, iget-short/jumbo 7993 */ 7994 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 7995 FETCH(r1, 1) @ r1<- aaaa (lo) 7996 FETCH(r2, 2) @ r2<- AAAA (hi) 7997 FETCH(r0, 4) @ r0<- CCCC 7998 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7999 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8000 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8001 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8002 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8003 cmp r0, #0 @ is resolved entry null? 8004 bne .LOP_IGET_BOOLEAN_JUMBO_finish @ no, already resolved 80058: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8006 EXPORT_PC() @ resolve() could throw 8007 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8008 bl dvmResolveInstField @ r0<- resolved InstField ptr 8009 b .LOP_IGET_BOOLEAN_JUMBO_resolved @ resolved, continue 8010 8011 8012/* ------------------------------ */ 8013 .balign 64 8014.L_OP_IGET_BYTE_JUMBO: /* 0x10a */ 8015/* File: armv5te/OP_IGET_BYTE_JUMBO.S */ 8016@include "armv5te/OP_IGET_JUMBO.S" { "load":"ldrsb", "sqnum":"2" } 8017/* File: armv5te/OP_IGET_JUMBO.S */ 8018 /* 8019 * Jumbo 32-bit instance field get. 8020 * 8021 * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo, 8022 * iget-char/jumbo, iget-short/jumbo 8023 */ 8024 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8025 FETCH(r1, 1) @ r1<- aaaa (lo) 8026 FETCH(r2, 2) @ r2<- AAAA (hi) 8027 FETCH(r0, 4) @ r0<- CCCC 8028 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8029 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8030 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8031 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8032 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8033 cmp r0, #0 @ is resolved entry null? 8034 bne .LOP_IGET_BYTE_JUMBO_finish @ no, already resolved 80358: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8036 EXPORT_PC() @ resolve() could throw 8037 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8038 bl dvmResolveInstField @ r0<- resolved InstField ptr 8039 b .LOP_IGET_BYTE_JUMBO_resolved @ resolved, continue 8040 8041 8042/* ------------------------------ */ 8043 .balign 64 8044.L_OP_IGET_CHAR_JUMBO: /* 0x10b */ 8045/* File: armv5te/OP_IGET_CHAR_JUMBO.S */ 8046@include "armv5te/OP_IGET_JUMBO.S" { "load":"ldrh", "sqnum":"3" } 8047/* File: armv5te/OP_IGET_JUMBO.S */ 8048 /* 8049 * Jumbo 32-bit instance field get. 8050 * 8051 * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo, 8052 * iget-char/jumbo, iget-short/jumbo 8053 */ 8054 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8055 FETCH(r1, 1) @ r1<- aaaa (lo) 8056 FETCH(r2, 2) @ r2<- AAAA (hi) 8057 FETCH(r0, 4) @ r0<- CCCC 8058 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8059 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8060 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8061 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8062 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8063 cmp r0, #0 @ is resolved entry null? 8064 bne .LOP_IGET_CHAR_JUMBO_finish @ no, already resolved 80658: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8066 EXPORT_PC() @ resolve() could throw 8067 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8068 bl dvmResolveInstField @ r0<- resolved InstField ptr 8069 b .LOP_IGET_CHAR_JUMBO_resolved @ resolved, continue 8070 8071 8072/* ------------------------------ */ 8073 .balign 64 8074.L_OP_IGET_SHORT_JUMBO: /* 0x10c */ 8075/* File: armv5te/OP_IGET_SHORT_JUMBO.S */ 8076@include "armv5te/OP_IGET_JUMBO.S" { "load":"ldrsh", "sqnum":"4" } 8077/* File: armv5te/OP_IGET_JUMBO.S */ 8078 /* 8079 * Jumbo 32-bit instance field get. 8080 * 8081 * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo, 8082 * iget-char/jumbo, iget-short/jumbo 8083 */ 8084 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8085 FETCH(r1, 1) @ r1<- aaaa (lo) 8086 FETCH(r2, 2) @ r2<- AAAA (hi) 8087 FETCH(r0, 4) @ r0<- CCCC 8088 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8089 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8090 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8091 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8092 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8093 cmp r0, #0 @ is resolved entry null? 8094 bne .LOP_IGET_SHORT_JUMBO_finish @ no, already resolved 80958: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8096 EXPORT_PC() @ resolve() could throw 8097 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8098 bl dvmResolveInstField @ r0<- resolved InstField ptr 8099 b .LOP_IGET_SHORT_JUMBO_resolved @ resolved, continue 8100 8101 8102/* ------------------------------ */ 8103 .balign 64 8104.L_OP_IPUT_JUMBO: /* 0x10d */ 8105/* File: armv5te/OP_IPUT_JUMBO.S */ 8106 /* 8107 * Jumbo 32-bit instance field put. 8108 * 8109 * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo, 8110 * iput-short/jumbo 8111 */ 8112 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8113 FETCH(r1, 1) @ r1<- aaaa (lo) 8114 FETCH(r2, 2) @ r2<- AAAA (hi) 8115 FETCH(r0, 4) @ r0<- CCCC 8116 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8117 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8118 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8119 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8120 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8121 cmp r0, #0 @ is resolved entry null? 8122 bne .LOP_IPUT_JUMBO_finish @ no, already resolved 81238: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8124 EXPORT_PC() @ resolve() could throw 8125 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8126 bl dvmResolveInstField @ r0<- resolved InstField ptr 8127 b .LOP_IPUT_JUMBO_resolved @ resolved, continue 8128 8129/* ------------------------------ */ 8130 .balign 64 8131.L_OP_IPUT_WIDE_JUMBO: /* 0x10e */ 8132/* File: armv5te/OP_IPUT_WIDE_JUMBO.S */ 8133 /* iput-wide/jumbo vBBBB, vCCCC, field@AAAAAAAA */ 8134 FETCH(r1, 1) @ r1<- aaaa (lo) 8135 FETCH(r2, 2) @ r2<- AAAA (hi) 8136 FETCH(r0, 4) @ r0<- CCCC 8137 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8138 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8139 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 8140 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 8141 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8142 cmp r0, #0 @ is resolved entry null? 8143 bne .LOP_IPUT_WIDE_JUMBO_finish @ no, already resolved 81448: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8145 EXPORT_PC() @ resolve() could throw 8146 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8147 bl dvmResolveInstField @ r0<- resolved InstField ptr 8148 b .LOP_IPUT_WIDE_JUMBO_resolved @ resolved, continue 8149 8150/* ------------------------------ */ 8151 .balign 64 8152.L_OP_IPUT_OBJECT_JUMBO: /* 0x10f */ 8153/* File: armv5te/OP_IPUT_OBJECT_JUMBO.S */ 8154 /* 8155 * Jumbo 32-bit instance field put. 8156 */ 8157 /* iput-object/jumbo vBBBB, vCCCC, field@AAAAAAAA */ 8158 FETCH(r1, 1) @ r1<- aaaa (lo) 8159 FETCH(r2, 2) @ r2<- AAAA (hi) 8160 FETCH(r0, 4) @ r0<- CCCC 8161 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8162 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8163 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8164 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8165 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8166 cmp r0, #0 @ is resolved entry null? 8167 bne .LOP_IPUT_OBJECT_JUMBO_finish @ no, already resolved 81688: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8169 EXPORT_PC() @ resolve() could throw 8170 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8171 bl dvmResolveInstField @ r0<- resolved InstField ptr 8172 b .LOP_IPUT_OBJECT_JUMBO_resolved @ resolved, continue 8173 8174/* ------------------------------ */ 8175 .balign 64 8176.L_OP_IPUT_BOOLEAN_JUMBO: /* 0x110 */ 8177/* File: armv5te/OP_IPUT_BOOLEAN_JUMBO.S */ 8178@include "armv5te/OP_IPUT_JUMBO.S" { "store":"strb", "sqnum":"1" } 8179/* File: armv5te/OP_IPUT_JUMBO.S */ 8180 /* 8181 * Jumbo 32-bit instance field put. 8182 * 8183 * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo, 8184 * iput-short/jumbo 8185 */ 8186 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8187 FETCH(r1, 1) @ r1<- aaaa (lo) 8188 FETCH(r2, 2) @ r2<- AAAA (hi) 8189 FETCH(r0, 4) @ r0<- CCCC 8190 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8191 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8192 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8193 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8194 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8195 cmp r0, #0 @ is resolved entry null? 8196 bne .LOP_IPUT_BOOLEAN_JUMBO_finish @ no, already resolved 81978: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8198 EXPORT_PC() @ resolve() could throw 8199 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8200 bl dvmResolveInstField @ r0<- resolved InstField ptr 8201 b .LOP_IPUT_BOOLEAN_JUMBO_resolved @ resolved, continue 8202 8203 8204/* ------------------------------ */ 8205 .balign 64 8206.L_OP_IPUT_BYTE_JUMBO: /* 0x111 */ 8207/* File: armv5te/OP_IPUT_BYTE_JUMBO.S */ 8208@include "armv5te/OP_IPUT_JUMBO.S" { "store":"strb", "sqnum":"2" } 8209/* File: armv5te/OP_IPUT_JUMBO.S */ 8210 /* 8211 * Jumbo 32-bit instance field put. 8212 * 8213 * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo, 8214 * iput-short/jumbo 8215 */ 8216 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8217 FETCH(r1, 1) @ r1<- aaaa (lo) 8218 FETCH(r2, 2) @ r2<- AAAA (hi) 8219 FETCH(r0, 4) @ r0<- CCCC 8220 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8221 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8222 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8223 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8224 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8225 cmp r0, #0 @ is resolved entry null? 8226 bne .LOP_IPUT_BYTE_JUMBO_finish @ no, already resolved 82278: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8228 EXPORT_PC() @ resolve() could throw 8229 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8230 bl dvmResolveInstField @ r0<- resolved InstField ptr 8231 b .LOP_IPUT_BYTE_JUMBO_resolved @ resolved, continue 8232 8233 8234/* ------------------------------ */ 8235 .balign 64 8236.L_OP_IPUT_CHAR_JUMBO: /* 0x112 */ 8237/* File: armv5te/OP_IPUT_CHAR_JUMBO.S */ 8238@include "armv5te/OP_IPUT_JUMBO.S" { "store":"strh", "sqnum":"3" } 8239/* File: armv5te/OP_IPUT_JUMBO.S */ 8240 /* 8241 * Jumbo 32-bit instance field put. 8242 * 8243 * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo, 8244 * iput-short/jumbo 8245 */ 8246 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8247 FETCH(r1, 1) @ r1<- aaaa (lo) 8248 FETCH(r2, 2) @ r2<- AAAA (hi) 8249 FETCH(r0, 4) @ r0<- CCCC 8250 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8251 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8252 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8253 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8254 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8255 cmp r0, #0 @ is resolved entry null? 8256 bne .LOP_IPUT_CHAR_JUMBO_finish @ no, already resolved 82578: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8258 EXPORT_PC() @ resolve() could throw 8259 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8260 bl dvmResolveInstField @ r0<- resolved InstField ptr 8261 b .LOP_IPUT_CHAR_JUMBO_resolved @ resolved, continue 8262 8263 8264/* ------------------------------ */ 8265 .balign 64 8266.L_OP_IPUT_SHORT_JUMBO: /* 0x113 */ 8267/* File: armv5te/OP_IPUT_SHORT_JUMBO.S */ 8268@include "armv5te/OP_IPUT_JUMBO.S" { "store":"strh", "sqnum":"4" } 8269/* File: armv5te/OP_IPUT_JUMBO.S */ 8270 /* 8271 * Jumbo 32-bit instance field put. 8272 * 8273 * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo, 8274 * iput-short/jumbo 8275 */ 8276 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8277 FETCH(r1, 1) @ r1<- aaaa (lo) 8278 FETCH(r2, 2) @ r2<- AAAA (hi) 8279 FETCH(r0, 4) @ r0<- CCCC 8280 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8281 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8282 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8283 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8284 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8285 cmp r0, #0 @ is resolved entry null? 8286 bne .LOP_IPUT_SHORT_JUMBO_finish @ no, already resolved 82878: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8288 EXPORT_PC() @ resolve() could throw 8289 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8290 bl dvmResolveInstField @ r0<- resolved InstField ptr 8291 b .LOP_IPUT_SHORT_JUMBO_resolved @ resolved, continue 8292 8293 8294/* ------------------------------ */ 8295 .balign 64 8296.L_OP_SGET_JUMBO: /* 0x114 */ 8297/* File: armv5te/OP_SGET_JUMBO.S */ 8298 /* 8299 * Jumbo 32-bit SGET handler. 8300 * 8301 * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo, 8302 * sget-char/jumbo, sget-short/jumbo 8303 */ 8304 /* exop vBBBB, field@AAAAAAAA */ 8305 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8306 FETCH(r0, 1) @ r0<- aaaa (lo) 8307 FETCH(r1, 2) @ r1<- AAAA (hi) 8308 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8309 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8310 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8311 cmp r0, #0 @ is resolved entry null? 8312 beq .LOP_SGET_JUMBO_resolve @ yes, do resolve 8313.LOP_SGET_JUMBO_finish: @ field ptr in r0 8314 ldr r1, [r0, #offStaticField_value] @ r1<- field value 8315 @ no-op @ acquiring load 8316 FETCH(r2, 3) @ r2<- BBBB 8317 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8318 SET_VREG(r1, r2) @ fp[BBBB]<- r1 8319 GET_INST_OPCODE(ip) @ extract opcode from rINST 8320 GOTO_OPCODE(ip) @ jump to next instruction 8321 8322/* ------------------------------ */ 8323 .balign 64 8324.L_OP_SGET_WIDE_JUMBO: /* 0x115 */ 8325/* File: armv5te/OP_SGET_WIDE_JUMBO.S */ 8326 /* 8327 * Jumbo 64-bit SGET handler. 8328 */ 8329 /* sget-wide/jumbo vBBBB, field@AAAAAAAA */ 8330 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8331 FETCH(r0, 1) @ r0<- aaaa (lo) 8332 FETCH(r1, 2) @ r1<- AAAA (hi) 8333 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8334 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8335 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8336 cmp r0, #0 @ is resolved entry null? 8337 beq .LOP_SGET_WIDE_JUMBO_resolve @ yes, do resolve 8338.LOP_SGET_WIDE_JUMBO_finish: 8339 FETCH(r9, 3) @ r9<- BBBB 8340 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 8341 add r9, rFP, r9, lsl #2 @ r9<- &fp[BBBB] 8342 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8343 stmia r9, {r0-r1} @ vBBBB/vBBBB+1<- r0/r1 8344 GET_INST_OPCODE(ip) @ extract opcode from rINST 8345 GOTO_OPCODE(ip) @ jump to next instruction 8346 8347/* ------------------------------ */ 8348 .balign 64 8349.L_OP_SGET_OBJECT_JUMBO: /* 0x116 */ 8350/* File: armv5te/OP_SGET_OBJECT_JUMBO.S */ 8351/* File: armv5te/OP_SGET_JUMBO.S */ 8352 /* 8353 * Jumbo 32-bit SGET handler. 8354 * 8355 * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo, 8356 * sget-char/jumbo, sget-short/jumbo 8357 */ 8358 /* exop vBBBB, field@AAAAAAAA */ 8359 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8360 FETCH(r0, 1) @ r0<- aaaa (lo) 8361 FETCH(r1, 2) @ r1<- AAAA (hi) 8362 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8363 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8364 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8365 cmp r0, #0 @ is resolved entry null? 8366 beq .LOP_SGET_OBJECT_JUMBO_resolve @ yes, do resolve 8367.LOP_SGET_OBJECT_JUMBO_finish: @ field ptr in r0 8368 ldr r1, [r0, #offStaticField_value] @ r1<- field value 8369 @ no-op @ acquiring load 8370 FETCH(r2, 3) @ r2<- BBBB 8371 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8372 SET_VREG(r1, r2) @ fp[BBBB]<- r1 8373 GET_INST_OPCODE(ip) @ extract opcode from rINST 8374 GOTO_OPCODE(ip) @ jump to next instruction 8375 8376 8377/* ------------------------------ */ 8378 .balign 64 8379.L_OP_SGET_BOOLEAN_JUMBO: /* 0x117 */ 8380/* File: armv5te/OP_SGET_BOOLEAN_JUMBO.S */ 8381/* File: armv5te/OP_SGET_JUMBO.S */ 8382 /* 8383 * Jumbo 32-bit SGET handler. 8384 * 8385 * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo, 8386 * sget-char/jumbo, sget-short/jumbo 8387 */ 8388 /* exop vBBBB, field@AAAAAAAA */ 8389 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8390 FETCH(r0, 1) @ r0<- aaaa (lo) 8391 FETCH(r1, 2) @ r1<- AAAA (hi) 8392 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8393 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8394 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8395 cmp r0, #0 @ is resolved entry null? 8396 beq .LOP_SGET_BOOLEAN_JUMBO_resolve @ yes, do resolve 8397.LOP_SGET_BOOLEAN_JUMBO_finish: @ field ptr in r0 8398 ldr r1, [r0, #offStaticField_value] @ r1<- field value 8399 @ no-op @ acquiring load 8400 FETCH(r2, 3) @ r2<- BBBB 8401 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8402 SET_VREG(r1, r2) @ fp[BBBB]<- r1 8403 GET_INST_OPCODE(ip) @ extract opcode from rINST 8404 GOTO_OPCODE(ip) @ jump to next instruction 8405 8406 8407/* ------------------------------ */ 8408 .balign 64 8409.L_OP_SGET_BYTE_JUMBO: /* 0x118 */ 8410/* File: armv5te/OP_SGET_BYTE_JUMBO.S */ 8411/* File: armv5te/OP_SGET_JUMBO.S */ 8412 /* 8413 * Jumbo 32-bit SGET handler. 8414 * 8415 * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo, 8416 * sget-char/jumbo, sget-short/jumbo 8417 */ 8418 /* exop vBBBB, field@AAAAAAAA */ 8419 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8420 FETCH(r0, 1) @ r0<- aaaa (lo) 8421 FETCH(r1, 2) @ r1<- AAAA (hi) 8422 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8423 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8424 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8425 cmp r0, #0 @ is resolved entry null? 8426 beq .LOP_SGET_BYTE_JUMBO_resolve @ yes, do resolve 8427.LOP_SGET_BYTE_JUMBO_finish: @ field ptr in r0 8428 ldr r1, [r0, #offStaticField_value] @ r1<- field value 8429 @ no-op @ acquiring load 8430 FETCH(r2, 3) @ r2<- BBBB 8431 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8432 SET_VREG(r1, r2) @ fp[BBBB]<- r1 8433 GET_INST_OPCODE(ip) @ extract opcode from rINST 8434 GOTO_OPCODE(ip) @ jump to next instruction 8435 8436 8437/* ------------------------------ */ 8438 .balign 64 8439.L_OP_SGET_CHAR_JUMBO: /* 0x119 */ 8440/* File: armv5te/OP_SGET_CHAR_JUMBO.S */ 8441/* File: armv5te/OP_SGET_JUMBO.S */ 8442 /* 8443 * Jumbo 32-bit SGET handler. 8444 * 8445 * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo, 8446 * sget-char/jumbo, sget-short/jumbo 8447 */ 8448 /* exop vBBBB, field@AAAAAAAA */ 8449 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8450 FETCH(r0, 1) @ r0<- aaaa (lo) 8451 FETCH(r1, 2) @ r1<- AAAA (hi) 8452 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8453 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8454 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8455 cmp r0, #0 @ is resolved entry null? 8456 beq .LOP_SGET_CHAR_JUMBO_resolve @ yes, do resolve 8457.LOP_SGET_CHAR_JUMBO_finish: @ field ptr in r0 8458 ldr r1, [r0, #offStaticField_value] @ r1<- field value 8459 @ no-op @ acquiring load 8460 FETCH(r2, 3) @ r2<- BBBB 8461 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8462 SET_VREG(r1, r2) @ fp[BBBB]<- r1 8463 GET_INST_OPCODE(ip) @ extract opcode from rINST 8464 GOTO_OPCODE(ip) @ jump to next instruction 8465 8466 8467/* ------------------------------ */ 8468 .balign 64 8469.L_OP_SGET_SHORT_JUMBO: /* 0x11a */ 8470/* File: armv5te/OP_SGET_SHORT_JUMBO.S */ 8471/* File: armv5te/OP_SGET_JUMBO.S */ 8472 /* 8473 * Jumbo 32-bit SGET handler. 8474 * 8475 * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo, 8476 * sget-char/jumbo, sget-short/jumbo 8477 */ 8478 /* exop vBBBB, field@AAAAAAAA */ 8479 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8480 FETCH(r0, 1) @ r0<- aaaa (lo) 8481 FETCH(r1, 2) @ r1<- AAAA (hi) 8482 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8483 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8484 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8485 cmp r0, #0 @ is resolved entry null? 8486 beq .LOP_SGET_SHORT_JUMBO_resolve @ yes, do resolve 8487.LOP_SGET_SHORT_JUMBO_finish: @ field ptr in r0 8488 ldr r1, [r0, #offStaticField_value] @ r1<- field value 8489 @ no-op @ acquiring load 8490 FETCH(r2, 3) @ r2<- BBBB 8491 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8492 SET_VREG(r1, r2) @ fp[BBBB]<- r1 8493 GET_INST_OPCODE(ip) @ extract opcode from rINST 8494 GOTO_OPCODE(ip) @ jump to next instruction 8495 8496 8497/* ------------------------------ */ 8498 .balign 64 8499.L_OP_SPUT_JUMBO: /* 0x11b */ 8500/* File: armv5te/OP_SPUT_JUMBO.S */ 8501 /* 8502 * Jumbo 32-bit SPUT handler. 8503 * 8504 * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo, 8505 * sput-short/jumbo 8506 */ 8507 /* exop vBBBB, field@AAAAAAAA */ 8508 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8509 FETCH(r0, 1) @ r0<- aaaa (lo) 8510 FETCH(r1, 2) @ r1<- AAAA (hi) 8511 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8512 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8513 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8514 cmp r0, #0 @ is resolved entry null? 8515 beq .LOP_SPUT_JUMBO_resolve @ yes, do resolve 8516.LOP_SPUT_JUMBO_finish: @ field ptr in r0 8517 FETCH(r2, 3) @ r2<- BBBB 8518 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8519 GET_VREG(r1, r2) @ r1<- fp[BBBB] 8520 GET_INST_OPCODE(ip) @ extract opcode from rINST 8521 @ no-op @ releasing store 8522 str r1, [r0, #offStaticField_value] @ field<- vBBBB 8523 GOTO_OPCODE(ip) @ jump to next instruction 8524 8525/* ------------------------------ */ 8526 .balign 64 8527.L_OP_SPUT_WIDE_JUMBO: /* 0x11c */ 8528/* File: armv5te/OP_SPUT_WIDE_JUMBO.S */ 8529 /* 8530 * Jumbo 64-bit SPUT handler. 8531 */ 8532 /* sput-wide/jumbo vBBBB, field@AAAAAAAA */ 8533 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 8534 FETCH(r1, 1) @ r1<- aaaa (lo) 8535 FETCH(r2, 2) @ r2<- AAAA (hi) 8536 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 8537 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8538 FETCH(r9, 3) @ r9<- BBBB 8539 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 8540 add r9, rFP, r9, lsl #2 @ r9<- &fp[BBBB] 8541 cmp r2, #0 @ is resolved entry null? 8542 beq .LOP_SPUT_WIDE_JUMBO_resolve @ yes, do resolve 8543.LOP_SPUT_WIDE_JUMBO_finish: @ field ptr in r2, BBBB in r9 8544 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8545 ldmia r9, {r0-r1} @ r0/r1<- vBBBB/vBBBB+1 8546 GET_INST_OPCODE(r10) @ extract opcode from rINST 8547 strd r0, [r2, #offStaticField_value] @ field<- vBBBB/vBBBB+1 8548 GOTO_OPCODE(r10) @ jump to next instruction 8549 8550/* ------------------------------ */ 8551 .balign 64 8552.L_OP_SPUT_OBJECT_JUMBO: /* 0x11d */ 8553/* File: armv5te/OP_SPUT_OBJECT_JUMBO.S */ 8554 /* 8555 * Jumbo 32-bit SPUT handler for objects 8556 */ 8557 /* sput-object/jumbo vBBBB, field@AAAAAAAA */ 8558 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8559 FETCH(r0, 1) @ r0<- aaaa (lo) 8560 FETCH(r1, 2) @ r1<- AAAA (hi) 8561 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8562 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8563 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8564 cmp r0, #0 @ is resolved entry null? 8565 bne .LOP_SPUT_OBJECT_JUMBO_finish @ no, continue 8566 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 8567 EXPORT_PC() @ resolve() could throw, so export now 8568 ldr r0, [r9, #offMethod_clazz] @ r0<- method->clazz 8569 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8570 cmp r0, #0 @ success? 8571 bne .LOP_SPUT_OBJECT_JUMBO_finish @ yes, finish 8572 b common_exceptionThrown @ no, handle exception 8573 8574/* ------------------------------ */ 8575 .balign 64 8576.L_OP_SPUT_BOOLEAN_JUMBO: /* 0x11e */ 8577/* File: armv5te/OP_SPUT_BOOLEAN_JUMBO.S */ 8578/* File: armv5te/OP_SPUT_JUMBO.S */ 8579 /* 8580 * Jumbo 32-bit SPUT handler. 8581 * 8582 * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo, 8583 * sput-short/jumbo 8584 */ 8585 /* exop vBBBB, field@AAAAAAAA */ 8586 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8587 FETCH(r0, 1) @ r0<- aaaa (lo) 8588 FETCH(r1, 2) @ r1<- AAAA (hi) 8589 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8590 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8591 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8592 cmp r0, #0 @ is resolved entry null? 8593 beq .LOP_SPUT_BOOLEAN_JUMBO_resolve @ yes, do resolve 8594.LOP_SPUT_BOOLEAN_JUMBO_finish: @ field ptr in r0 8595 FETCH(r2, 3) @ r2<- BBBB 8596 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8597 GET_VREG(r1, r2) @ r1<- fp[BBBB] 8598 GET_INST_OPCODE(ip) @ extract opcode from rINST 8599 @ no-op @ releasing store 8600 str r1, [r0, #offStaticField_value] @ field<- vBBBB 8601 GOTO_OPCODE(ip) @ jump to next instruction 8602 8603 8604/* ------------------------------ */ 8605 .balign 64 8606.L_OP_SPUT_BYTE_JUMBO: /* 0x11f */ 8607/* File: armv5te/OP_SPUT_BYTE_JUMBO.S */ 8608/* File: armv5te/OP_SPUT_JUMBO.S */ 8609 /* 8610 * Jumbo 32-bit SPUT handler. 8611 * 8612 * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo, 8613 * sput-short/jumbo 8614 */ 8615 /* exop vBBBB, field@AAAAAAAA */ 8616 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8617 FETCH(r0, 1) @ r0<- aaaa (lo) 8618 FETCH(r1, 2) @ r1<- AAAA (hi) 8619 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8620 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8621 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8622 cmp r0, #0 @ is resolved entry null? 8623 beq .LOP_SPUT_BYTE_JUMBO_resolve @ yes, do resolve 8624.LOP_SPUT_BYTE_JUMBO_finish: @ field ptr in r0 8625 FETCH(r2, 3) @ r2<- BBBB 8626 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8627 GET_VREG(r1, r2) @ r1<- fp[BBBB] 8628 GET_INST_OPCODE(ip) @ extract opcode from rINST 8629 @ no-op @ releasing store 8630 str r1, [r0, #offStaticField_value] @ field<- vBBBB 8631 GOTO_OPCODE(ip) @ jump to next instruction 8632 8633 8634/* ------------------------------ */ 8635 .balign 64 8636.L_OP_SPUT_CHAR_JUMBO: /* 0x120 */ 8637/* File: armv5te/OP_SPUT_CHAR_JUMBO.S */ 8638/* File: armv5te/OP_SPUT_JUMBO.S */ 8639 /* 8640 * Jumbo 32-bit SPUT handler. 8641 * 8642 * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo, 8643 * sput-short/jumbo 8644 */ 8645 /* exop vBBBB, field@AAAAAAAA */ 8646 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8647 FETCH(r0, 1) @ r0<- aaaa (lo) 8648 FETCH(r1, 2) @ r1<- AAAA (hi) 8649 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8650 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8651 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8652 cmp r0, #0 @ is resolved entry null? 8653 beq .LOP_SPUT_CHAR_JUMBO_resolve @ yes, do resolve 8654.LOP_SPUT_CHAR_JUMBO_finish: @ field ptr in r0 8655 FETCH(r2, 3) @ r2<- BBBB 8656 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8657 GET_VREG(r1, r2) @ r1<- fp[BBBB] 8658 GET_INST_OPCODE(ip) @ extract opcode from rINST 8659 @ no-op @ releasing store 8660 str r1, [r0, #offStaticField_value] @ field<- vBBBB 8661 GOTO_OPCODE(ip) @ jump to next instruction 8662 8663 8664/* ------------------------------ */ 8665 .balign 64 8666.L_OP_SPUT_SHORT_JUMBO: /* 0x121 */ 8667/* File: armv5te/OP_SPUT_SHORT_JUMBO.S */ 8668/* File: armv5te/OP_SPUT_JUMBO.S */ 8669 /* 8670 * Jumbo 32-bit SPUT handler. 8671 * 8672 * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo, 8673 * sput-short/jumbo 8674 */ 8675 /* exop vBBBB, field@AAAAAAAA */ 8676 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8677 FETCH(r0, 1) @ r0<- aaaa (lo) 8678 FETCH(r1, 2) @ r1<- AAAA (hi) 8679 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8680 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8681 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8682 cmp r0, #0 @ is resolved entry null? 8683 beq .LOP_SPUT_SHORT_JUMBO_resolve @ yes, do resolve 8684.LOP_SPUT_SHORT_JUMBO_finish: @ field ptr in r0 8685 FETCH(r2, 3) @ r2<- BBBB 8686 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8687 GET_VREG(r1, r2) @ r1<- fp[BBBB] 8688 GET_INST_OPCODE(ip) @ extract opcode from rINST 8689 @ no-op @ releasing store 8690 str r1, [r0, #offStaticField_value] @ field<- vBBBB 8691 GOTO_OPCODE(ip) @ jump to next instruction 8692 8693 8694/* ------------------------------ */ 8695 .balign 64 8696.L_OP_INVOKE_VIRTUAL_JUMBO: /* 0x122 */ 8697/* File: armv5te/OP_INVOKE_VIRTUAL_JUMBO.S */ 8698 /* 8699 * Handle a virtual method call. 8700 */ 8701 /* invoke-virtual/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */ 8702 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 8703 FETCH(r0, 1) @ r1<- aaaa (lo) 8704 FETCH(r1, 2) @ r1<- AAAA (hi) 8705 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 8706 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8707 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 8708 cmp r0, #0 @ already resolved? 8709 EXPORT_PC() @ must export for invoke 8710 bne .LOP_INVOKE_VIRTUAL_JUMBO_continue @ yes, continue on 8711 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8712 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8713 mov r2, #METHOD_VIRTUAL @ resolver method type 8714 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8715 cmp r0, #0 @ got null? 8716 bne .LOP_INVOKE_VIRTUAL_JUMBO_continue @ no, continue 8717 b common_exceptionThrown @ yes, handle exception 8718 8719/* ------------------------------ */ 8720 .balign 64 8721.L_OP_INVOKE_SUPER_JUMBO: /* 0x123 */ 8722/* File: armv5te/OP_INVOKE_SUPER_JUMBO.S */ 8723 /* 8724 * Handle a "super" method call. 8725 */ 8726 /* invoke-super/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */ 8727 FETCH(r10, 4) @ r10<- CCCC 8728 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 8729 FETCH(r0, 1) @ r1<- aaaa (lo) 8730 FETCH(r1, 2) @ r1<- AAAA (hi) 8731 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 8732 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8733 GET_VREG(r2, r10) @ r2<- "this" ptr 8734 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 8735 cmp r2, #0 @ null "this"? 8736 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 8737 beq common_errNullObject @ null "this", throw exception 8738 cmp r0, #0 @ already resolved? 8739 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 8740 EXPORT_PC() @ must export for invoke 8741 bne .LOP_INVOKE_SUPER_JUMBO_continue @ resolved, continue on 8742 b .LOP_INVOKE_SUPER_JUMBO_resolve @ do resolve now 8743 8744/* ------------------------------ */ 8745 .balign 64 8746.L_OP_INVOKE_DIRECT_JUMBO: /* 0x124 */ 8747/* File: armv5te/OP_INVOKE_DIRECT_JUMBO.S */ 8748 /* 8749 * Handle a direct method call. 8750 * 8751 * (We could defer the "is 'this' pointer null" test to the common 8752 * method invocation code, and use a flag to indicate that static 8753 * calls don't count. If we do this as part of copying the arguments 8754 * out we could avoiding loading the first arg twice.) 8755 * 8756 */ 8757 /* invoke-direct/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */ 8758 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 8759 FETCH(r0, 1) @ r1<- aaaa (lo) 8760 FETCH(r1, 2) @ r1<- AAAA (hi) 8761 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 8762 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8763 FETCH(r10, 4) @ r10<- CCCC 8764 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 8765 cmp r0, #0 @ already resolved? 8766 EXPORT_PC() @ must export for invoke 8767 GET_VREG(r2, r10) @ r2<- "this" ptr 8768 beq .LOP_INVOKE_DIRECT_JUMBO_resolve @ not resolved, do it now 8769.LOP_INVOKE_DIRECT_JUMBO_finish: 8770 cmp r2, #0 @ null "this" ref? 8771 bne common_invokeMethodJumbo @ no, continue on 8772 b common_errNullObject @ yes, throw exception 8773 8774/* ------------------------------ */ 8775 .balign 64 8776.L_OP_INVOKE_STATIC_JUMBO: /* 0x125 */ 8777/* File: armv5te/OP_INVOKE_STATIC_JUMBO.S */ 8778 /* 8779 * Handle a static method call. 8780 */ 8781 /* invoke-static/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */ 8782 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 8783 FETCH(r0, 1) @ r1<- aaaa (lo) 8784 FETCH(r1, 2) @ r1<- AAAA (hi) 8785 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 8786 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8787 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 8788 cmp r0, #0 @ already resolved? 8789 EXPORT_PC() @ must export for invoke 8790 bne common_invokeMethodJumbo @ yes, continue on 87910: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8792 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8793 mov r2, #METHOD_STATIC @ resolver method type 8794 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8795 cmp r0, #0 @ got null? 8796 bne common_invokeMethodJumbo @ no, continue 8797 b common_exceptionThrown @ yes, handle exception 8798 8799/* ------------------------------ */ 8800 .balign 64 8801.L_OP_INVOKE_INTERFACE_JUMBO: /* 0x126 */ 8802/* File: armv5te/OP_INVOKE_INTERFACE_JUMBO.S */ 8803 /* 8804 * Handle an interface method call. 8805 */ 8806 /* invoke-interface/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */ 8807 FETCH(r2, 4) @ r2<- CCCC 8808 FETCH(r0, 1) @ r0<- aaaa (lo) 8809 FETCH(r1, 2) @ r1<- AAAA (hi) 8810 EXPORT_PC() @ must export for invoke 8811 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8812 GET_VREG(r0, r2) @ r0<- first arg ("this") 8813 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 8814 cmp r0, #0 @ null obj? 8815 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 8816 beq common_errNullObject @ yes, fail 8817 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 8818 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 8819 cmp r0, #0 @ failed? 8820 beq common_exceptionThrown @ yes, handle exception 8821 b common_invokeMethodJumbo @ jump to common handler 8822 8823/* ------------------------------ */ 8824 .balign 64 8825.L_OP_UNUSED_27FF: /* 0x127 */ 8826/* File: armv5te/OP_UNUSED_27FF.S */ 8827/* File: armv5te/unused.S */ 8828 bl common_abort 8829 8830 8831/* ------------------------------ */ 8832 .balign 64 8833.L_OP_UNUSED_28FF: /* 0x128 */ 8834/* File: armv5te/OP_UNUSED_28FF.S */ 8835/* File: armv5te/unused.S */ 8836 bl common_abort 8837 8838 8839/* ------------------------------ */ 8840 .balign 64 8841.L_OP_UNUSED_29FF: /* 0x129 */ 8842/* File: armv5te/OP_UNUSED_29FF.S */ 8843/* File: armv5te/unused.S */ 8844 bl common_abort 8845 8846 8847/* ------------------------------ */ 8848 .balign 64 8849.L_OP_UNUSED_2AFF: /* 0x12a */ 8850/* File: armv5te/OP_UNUSED_2AFF.S */ 8851/* File: armv5te/unused.S */ 8852 bl common_abort 8853 8854 8855/* ------------------------------ */ 8856 .balign 64 8857.L_OP_UNUSED_2BFF: /* 0x12b */ 8858/* File: armv5te/OP_UNUSED_2BFF.S */ 8859/* File: armv5te/unused.S */ 8860 bl common_abort 8861 8862 8863/* ------------------------------ */ 8864 .balign 64 8865.L_OP_UNUSED_2CFF: /* 0x12c */ 8866/* File: armv5te/OP_UNUSED_2CFF.S */ 8867/* File: armv5te/unused.S */ 8868 bl common_abort 8869 8870 8871/* ------------------------------ */ 8872 .balign 64 8873.L_OP_UNUSED_2DFF: /* 0x12d */ 8874/* File: armv5te/OP_UNUSED_2DFF.S */ 8875/* File: armv5te/unused.S */ 8876 bl common_abort 8877 8878 8879/* ------------------------------ */ 8880 .balign 64 8881.L_OP_UNUSED_2EFF: /* 0x12e */ 8882/* File: armv5te/OP_UNUSED_2EFF.S */ 8883/* File: armv5te/unused.S */ 8884 bl common_abort 8885 8886 8887/* ------------------------------ */ 8888 .balign 64 8889.L_OP_UNUSED_2FFF: /* 0x12f */ 8890/* File: armv5te/OP_UNUSED_2FFF.S */ 8891/* File: armv5te/unused.S */ 8892 bl common_abort 8893 8894 8895/* ------------------------------ */ 8896 .balign 64 8897.L_OP_UNUSED_30FF: /* 0x130 */ 8898/* File: armv5te/OP_UNUSED_30FF.S */ 8899/* File: armv5te/unused.S */ 8900 bl common_abort 8901 8902 8903/* ------------------------------ */ 8904 .balign 64 8905.L_OP_UNUSED_31FF: /* 0x131 */ 8906/* File: armv5te/OP_UNUSED_31FF.S */ 8907/* File: armv5te/unused.S */ 8908 bl common_abort 8909 8910 8911/* ------------------------------ */ 8912 .balign 64 8913.L_OP_UNUSED_32FF: /* 0x132 */ 8914/* File: armv5te/OP_UNUSED_32FF.S */ 8915/* File: armv5te/unused.S */ 8916 bl common_abort 8917 8918 8919/* ------------------------------ */ 8920 .balign 64 8921.L_OP_UNUSED_33FF: /* 0x133 */ 8922/* File: armv5te/OP_UNUSED_33FF.S */ 8923/* File: armv5te/unused.S */ 8924 bl common_abort 8925 8926 8927/* ------------------------------ */ 8928 .balign 64 8929.L_OP_UNUSED_34FF: /* 0x134 */ 8930/* File: armv5te/OP_UNUSED_34FF.S */ 8931/* File: armv5te/unused.S */ 8932 bl common_abort 8933 8934 8935/* ------------------------------ */ 8936 .balign 64 8937.L_OP_UNUSED_35FF: /* 0x135 */ 8938/* File: armv5te/OP_UNUSED_35FF.S */ 8939/* File: armv5te/unused.S */ 8940 bl common_abort 8941 8942 8943/* ------------------------------ */ 8944 .balign 64 8945.L_OP_UNUSED_36FF: /* 0x136 */ 8946/* File: armv5te/OP_UNUSED_36FF.S */ 8947/* File: armv5te/unused.S */ 8948 bl common_abort 8949 8950 8951/* ------------------------------ */ 8952 .balign 64 8953.L_OP_UNUSED_37FF: /* 0x137 */ 8954/* File: armv5te/OP_UNUSED_37FF.S */ 8955/* File: armv5te/unused.S */ 8956 bl common_abort 8957 8958 8959/* ------------------------------ */ 8960 .balign 64 8961.L_OP_UNUSED_38FF: /* 0x138 */ 8962/* File: armv5te/OP_UNUSED_38FF.S */ 8963/* File: armv5te/unused.S */ 8964 bl common_abort 8965 8966 8967/* ------------------------------ */ 8968 .balign 64 8969.L_OP_UNUSED_39FF: /* 0x139 */ 8970/* File: armv5te/OP_UNUSED_39FF.S */ 8971/* File: armv5te/unused.S */ 8972 bl common_abort 8973 8974 8975/* ------------------------------ */ 8976 .balign 64 8977.L_OP_UNUSED_3AFF: /* 0x13a */ 8978/* File: armv5te/OP_UNUSED_3AFF.S */ 8979/* File: armv5te/unused.S */ 8980 bl common_abort 8981 8982 8983/* ------------------------------ */ 8984 .balign 64 8985.L_OP_UNUSED_3BFF: /* 0x13b */ 8986/* File: armv5te/OP_UNUSED_3BFF.S */ 8987/* File: armv5te/unused.S */ 8988 bl common_abort 8989 8990 8991/* ------------------------------ */ 8992 .balign 64 8993.L_OP_UNUSED_3CFF: /* 0x13c */ 8994/* File: armv5te/OP_UNUSED_3CFF.S */ 8995/* File: armv5te/unused.S */ 8996 bl common_abort 8997 8998 8999/* ------------------------------ */ 9000 .balign 64 9001.L_OP_UNUSED_3DFF: /* 0x13d */ 9002/* File: armv5te/OP_UNUSED_3DFF.S */ 9003/* File: armv5te/unused.S */ 9004 bl common_abort 9005 9006 9007/* ------------------------------ */ 9008 .balign 64 9009.L_OP_UNUSED_3EFF: /* 0x13e */ 9010/* File: armv5te/OP_UNUSED_3EFF.S */ 9011/* File: armv5te/unused.S */ 9012 bl common_abort 9013 9014 9015/* ------------------------------ */ 9016 .balign 64 9017.L_OP_UNUSED_3FFF: /* 0x13f */ 9018/* File: armv5te/OP_UNUSED_3FFF.S */ 9019/* File: armv5te/unused.S */ 9020 bl common_abort 9021 9022 9023/* ------------------------------ */ 9024 .balign 64 9025.L_OP_UNUSED_40FF: /* 0x140 */ 9026/* File: armv5te/OP_UNUSED_40FF.S */ 9027/* File: armv5te/unused.S */ 9028 bl common_abort 9029 9030 9031/* ------------------------------ */ 9032 .balign 64 9033.L_OP_UNUSED_41FF: /* 0x141 */ 9034/* File: armv5te/OP_UNUSED_41FF.S */ 9035/* File: armv5te/unused.S */ 9036 bl common_abort 9037 9038 9039/* ------------------------------ */ 9040 .balign 64 9041.L_OP_UNUSED_42FF: /* 0x142 */ 9042/* File: armv5te/OP_UNUSED_42FF.S */ 9043/* File: armv5te/unused.S */ 9044 bl common_abort 9045 9046 9047/* ------------------------------ */ 9048 .balign 64 9049.L_OP_UNUSED_43FF: /* 0x143 */ 9050/* File: armv5te/OP_UNUSED_43FF.S */ 9051/* File: armv5te/unused.S */ 9052 bl common_abort 9053 9054 9055/* ------------------------------ */ 9056 .balign 64 9057.L_OP_UNUSED_44FF: /* 0x144 */ 9058/* File: armv5te/OP_UNUSED_44FF.S */ 9059/* File: armv5te/unused.S */ 9060 bl common_abort 9061 9062 9063/* ------------------------------ */ 9064 .balign 64 9065.L_OP_UNUSED_45FF: /* 0x145 */ 9066/* File: armv5te/OP_UNUSED_45FF.S */ 9067/* File: armv5te/unused.S */ 9068 bl common_abort 9069 9070 9071/* ------------------------------ */ 9072 .balign 64 9073.L_OP_UNUSED_46FF: /* 0x146 */ 9074/* File: armv5te/OP_UNUSED_46FF.S */ 9075/* File: armv5te/unused.S */ 9076 bl common_abort 9077 9078 9079/* ------------------------------ */ 9080 .balign 64 9081.L_OP_UNUSED_47FF: /* 0x147 */ 9082/* File: armv5te/OP_UNUSED_47FF.S */ 9083/* File: armv5te/unused.S */ 9084 bl common_abort 9085 9086 9087/* ------------------------------ */ 9088 .balign 64 9089.L_OP_UNUSED_48FF: /* 0x148 */ 9090/* File: armv5te/OP_UNUSED_48FF.S */ 9091/* File: armv5te/unused.S */ 9092 bl common_abort 9093 9094 9095/* ------------------------------ */ 9096 .balign 64 9097.L_OP_UNUSED_49FF: /* 0x149 */ 9098/* File: armv5te/OP_UNUSED_49FF.S */ 9099/* File: armv5te/unused.S */ 9100 bl common_abort 9101 9102 9103/* ------------------------------ */ 9104 .balign 64 9105.L_OP_UNUSED_4AFF: /* 0x14a */ 9106/* File: armv5te/OP_UNUSED_4AFF.S */ 9107/* File: armv5te/unused.S */ 9108 bl common_abort 9109 9110 9111/* ------------------------------ */ 9112 .balign 64 9113.L_OP_UNUSED_4BFF: /* 0x14b */ 9114/* File: armv5te/OP_UNUSED_4BFF.S */ 9115/* File: armv5te/unused.S */ 9116 bl common_abort 9117 9118 9119/* ------------------------------ */ 9120 .balign 64 9121.L_OP_UNUSED_4CFF: /* 0x14c */ 9122/* File: armv5te/OP_UNUSED_4CFF.S */ 9123/* File: armv5te/unused.S */ 9124 bl common_abort 9125 9126 9127/* ------------------------------ */ 9128 .balign 64 9129.L_OP_UNUSED_4DFF: /* 0x14d */ 9130/* File: armv5te/OP_UNUSED_4DFF.S */ 9131/* File: armv5te/unused.S */ 9132 bl common_abort 9133 9134 9135/* ------------------------------ */ 9136 .balign 64 9137.L_OP_UNUSED_4EFF: /* 0x14e */ 9138/* File: armv5te/OP_UNUSED_4EFF.S */ 9139/* File: armv5te/unused.S */ 9140 bl common_abort 9141 9142 9143/* ------------------------------ */ 9144 .balign 64 9145.L_OP_UNUSED_4FFF: /* 0x14f */ 9146/* File: armv5te/OP_UNUSED_4FFF.S */ 9147/* File: armv5te/unused.S */ 9148 bl common_abort 9149 9150 9151/* ------------------------------ */ 9152 .balign 64 9153.L_OP_UNUSED_50FF: /* 0x150 */ 9154/* File: armv5te/OP_UNUSED_50FF.S */ 9155/* File: armv5te/unused.S */ 9156 bl common_abort 9157 9158 9159/* ------------------------------ */ 9160 .balign 64 9161.L_OP_UNUSED_51FF: /* 0x151 */ 9162/* File: armv5te/OP_UNUSED_51FF.S */ 9163/* File: armv5te/unused.S */ 9164 bl common_abort 9165 9166 9167/* ------------------------------ */ 9168 .balign 64 9169.L_OP_UNUSED_52FF: /* 0x152 */ 9170/* File: armv5te/OP_UNUSED_52FF.S */ 9171/* File: armv5te/unused.S */ 9172 bl common_abort 9173 9174 9175/* ------------------------------ */ 9176 .balign 64 9177.L_OP_UNUSED_53FF: /* 0x153 */ 9178/* File: armv5te/OP_UNUSED_53FF.S */ 9179/* File: armv5te/unused.S */ 9180 bl common_abort 9181 9182 9183/* ------------------------------ */ 9184 .balign 64 9185.L_OP_UNUSED_54FF: /* 0x154 */ 9186/* File: armv5te/OP_UNUSED_54FF.S */ 9187/* File: armv5te/unused.S */ 9188 bl common_abort 9189 9190 9191/* ------------------------------ */ 9192 .balign 64 9193.L_OP_UNUSED_55FF: /* 0x155 */ 9194/* File: armv5te/OP_UNUSED_55FF.S */ 9195/* File: armv5te/unused.S */ 9196 bl common_abort 9197 9198 9199/* ------------------------------ */ 9200 .balign 64 9201.L_OP_UNUSED_56FF: /* 0x156 */ 9202/* File: armv5te/OP_UNUSED_56FF.S */ 9203/* File: armv5te/unused.S */ 9204 bl common_abort 9205 9206 9207/* ------------------------------ */ 9208 .balign 64 9209.L_OP_UNUSED_57FF: /* 0x157 */ 9210/* File: armv5te/OP_UNUSED_57FF.S */ 9211/* File: armv5te/unused.S */ 9212 bl common_abort 9213 9214 9215/* ------------------------------ */ 9216 .balign 64 9217.L_OP_UNUSED_58FF: /* 0x158 */ 9218/* File: armv5te/OP_UNUSED_58FF.S */ 9219/* File: armv5te/unused.S */ 9220 bl common_abort 9221 9222 9223/* ------------------------------ */ 9224 .balign 64 9225.L_OP_UNUSED_59FF: /* 0x159 */ 9226/* File: armv5te/OP_UNUSED_59FF.S */ 9227/* File: armv5te/unused.S */ 9228 bl common_abort 9229 9230 9231/* ------------------------------ */ 9232 .balign 64 9233.L_OP_UNUSED_5AFF: /* 0x15a */ 9234/* File: armv5te/OP_UNUSED_5AFF.S */ 9235/* File: armv5te/unused.S */ 9236 bl common_abort 9237 9238 9239/* ------------------------------ */ 9240 .balign 64 9241.L_OP_UNUSED_5BFF: /* 0x15b */ 9242/* File: armv5te/OP_UNUSED_5BFF.S */ 9243/* File: armv5te/unused.S */ 9244 bl common_abort 9245 9246 9247/* ------------------------------ */ 9248 .balign 64 9249.L_OP_UNUSED_5CFF: /* 0x15c */ 9250/* File: armv5te/OP_UNUSED_5CFF.S */ 9251/* File: armv5te/unused.S */ 9252 bl common_abort 9253 9254 9255/* ------------------------------ */ 9256 .balign 64 9257.L_OP_UNUSED_5DFF: /* 0x15d */ 9258/* File: armv5te/OP_UNUSED_5DFF.S */ 9259/* File: armv5te/unused.S */ 9260 bl common_abort 9261 9262 9263/* ------------------------------ */ 9264 .balign 64 9265.L_OP_UNUSED_5EFF: /* 0x15e */ 9266/* File: armv5te/OP_UNUSED_5EFF.S */ 9267/* File: armv5te/unused.S */ 9268 bl common_abort 9269 9270 9271/* ------------------------------ */ 9272 .balign 64 9273.L_OP_UNUSED_5FFF: /* 0x15f */ 9274/* File: armv5te/OP_UNUSED_5FFF.S */ 9275/* File: armv5te/unused.S */ 9276 bl common_abort 9277 9278 9279/* ------------------------------ */ 9280 .balign 64 9281.L_OP_UNUSED_60FF: /* 0x160 */ 9282/* File: armv5te/OP_UNUSED_60FF.S */ 9283/* File: armv5te/unused.S */ 9284 bl common_abort 9285 9286 9287/* ------------------------------ */ 9288 .balign 64 9289.L_OP_UNUSED_61FF: /* 0x161 */ 9290/* File: armv5te/OP_UNUSED_61FF.S */ 9291/* File: armv5te/unused.S */ 9292 bl common_abort 9293 9294 9295/* ------------------------------ */ 9296 .balign 64 9297.L_OP_UNUSED_62FF: /* 0x162 */ 9298/* File: armv5te/OP_UNUSED_62FF.S */ 9299/* File: armv5te/unused.S */ 9300 bl common_abort 9301 9302 9303/* ------------------------------ */ 9304 .balign 64 9305.L_OP_UNUSED_63FF: /* 0x163 */ 9306/* File: armv5te/OP_UNUSED_63FF.S */ 9307/* File: armv5te/unused.S */ 9308 bl common_abort 9309 9310 9311/* ------------------------------ */ 9312 .balign 64 9313.L_OP_UNUSED_64FF: /* 0x164 */ 9314/* File: armv5te/OP_UNUSED_64FF.S */ 9315/* File: armv5te/unused.S */ 9316 bl common_abort 9317 9318 9319/* ------------------------------ */ 9320 .balign 64 9321.L_OP_UNUSED_65FF: /* 0x165 */ 9322/* File: armv5te/OP_UNUSED_65FF.S */ 9323/* File: armv5te/unused.S */ 9324 bl common_abort 9325 9326 9327/* ------------------------------ */ 9328 .balign 64 9329.L_OP_UNUSED_66FF: /* 0x166 */ 9330/* File: armv5te/OP_UNUSED_66FF.S */ 9331/* File: armv5te/unused.S */ 9332 bl common_abort 9333 9334 9335/* ------------------------------ */ 9336 .balign 64 9337.L_OP_UNUSED_67FF: /* 0x167 */ 9338/* File: armv5te/OP_UNUSED_67FF.S */ 9339/* File: armv5te/unused.S */ 9340 bl common_abort 9341 9342 9343/* ------------------------------ */ 9344 .balign 64 9345.L_OP_UNUSED_68FF: /* 0x168 */ 9346/* File: armv5te/OP_UNUSED_68FF.S */ 9347/* File: armv5te/unused.S */ 9348 bl common_abort 9349 9350 9351/* ------------------------------ */ 9352 .balign 64 9353.L_OP_UNUSED_69FF: /* 0x169 */ 9354/* File: armv5te/OP_UNUSED_69FF.S */ 9355/* File: armv5te/unused.S */ 9356 bl common_abort 9357 9358 9359/* ------------------------------ */ 9360 .balign 64 9361.L_OP_UNUSED_6AFF: /* 0x16a */ 9362/* File: armv5te/OP_UNUSED_6AFF.S */ 9363/* File: armv5te/unused.S */ 9364 bl common_abort 9365 9366 9367/* ------------------------------ */ 9368 .balign 64 9369.L_OP_UNUSED_6BFF: /* 0x16b */ 9370/* File: armv5te/OP_UNUSED_6BFF.S */ 9371/* File: armv5te/unused.S */ 9372 bl common_abort 9373 9374 9375/* ------------------------------ */ 9376 .balign 64 9377.L_OP_UNUSED_6CFF: /* 0x16c */ 9378/* File: armv5te/OP_UNUSED_6CFF.S */ 9379/* File: armv5te/unused.S */ 9380 bl common_abort 9381 9382 9383/* ------------------------------ */ 9384 .balign 64 9385.L_OP_UNUSED_6DFF: /* 0x16d */ 9386/* File: armv5te/OP_UNUSED_6DFF.S */ 9387/* File: armv5te/unused.S */ 9388 bl common_abort 9389 9390 9391/* ------------------------------ */ 9392 .balign 64 9393.L_OP_UNUSED_6EFF: /* 0x16e */ 9394/* File: armv5te/OP_UNUSED_6EFF.S */ 9395/* File: armv5te/unused.S */ 9396 bl common_abort 9397 9398 9399/* ------------------------------ */ 9400 .balign 64 9401.L_OP_UNUSED_6FFF: /* 0x16f */ 9402/* File: armv5te/OP_UNUSED_6FFF.S */ 9403/* File: armv5te/unused.S */ 9404 bl common_abort 9405 9406 9407/* ------------------------------ */ 9408 .balign 64 9409.L_OP_UNUSED_70FF: /* 0x170 */ 9410/* File: armv5te/OP_UNUSED_70FF.S */ 9411/* File: armv5te/unused.S */ 9412 bl common_abort 9413 9414 9415/* ------------------------------ */ 9416 .balign 64 9417.L_OP_UNUSED_71FF: /* 0x171 */ 9418/* File: armv5te/OP_UNUSED_71FF.S */ 9419/* File: armv5te/unused.S */ 9420 bl common_abort 9421 9422 9423/* ------------------------------ */ 9424 .balign 64 9425.L_OP_UNUSED_72FF: /* 0x172 */ 9426/* File: armv5te/OP_UNUSED_72FF.S */ 9427/* File: armv5te/unused.S */ 9428 bl common_abort 9429 9430 9431/* ------------------------------ */ 9432 .balign 64 9433.L_OP_UNUSED_73FF: /* 0x173 */ 9434/* File: armv5te/OP_UNUSED_73FF.S */ 9435/* File: armv5te/unused.S */ 9436 bl common_abort 9437 9438 9439/* ------------------------------ */ 9440 .balign 64 9441.L_OP_UNUSED_74FF: /* 0x174 */ 9442/* File: armv5te/OP_UNUSED_74FF.S */ 9443/* File: armv5te/unused.S */ 9444 bl common_abort 9445 9446 9447/* ------------------------------ */ 9448 .balign 64 9449.L_OP_UNUSED_75FF: /* 0x175 */ 9450/* File: armv5te/OP_UNUSED_75FF.S */ 9451/* File: armv5te/unused.S */ 9452 bl common_abort 9453 9454 9455/* ------------------------------ */ 9456 .balign 64 9457.L_OP_UNUSED_76FF: /* 0x176 */ 9458/* File: armv5te/OP_UNUSED_76FF.S */ 9459/* File: armv5te/unused.S */ 9460 bl common_abort 9461 9462 9463/* ------------------------------ */ 9464 .balign 64 9465.L_OP_UNUSED_77FF: /* 0x177 */ 9466/* File: armv5te/OP_UNUSED_77FF.S */ 9467/* File: armv5te/unused.S */ 9468 bl common_abort 9469 9470 9471/* ------------------------------ */ 9472 .balign 64 9473.L_OP_UNUSED_78FF: /* 0x178 */ 9474/* File: armv5te/OP_UNUSED_78FF.S */ 9475/* File: armv5te/unused.S */ 9476 bl common_abort 9477 9478 9479/* ------------------------------ */ 9480 .balign 64 9481.L_OP_UNUSED_79FF: /* 0x179 */ 9482/* File: armv5te/OP_UNUSED_79FF.S */ 9483/* File: armv5te/unused.S */ 9484 bl common_abort 9485 9486 9487/* ------------------------------ */ 9488 .balign 64 9489.L_OP_UNUSED_7AFF: /* 0x17a */ 9490/* File: armv5te/OP_UNUSED_7AFF.S */ 9491/* File: armv5te/unused.S */ 9492 bl common_abort 9493 9494 9495/* ------------------------------ */ 9496 .balign 64 9497.L_OP_UNUSED_7BFF: /* 0x17b */ 9498/* File: armv5te/OP_UNUSED_7BFF.S */ 9499/* File: armv5te/unused.S */ 9500 bl common_abort 9501 9502 9503/* ------------------------------ */ 9504 .balign 64 9505.L_OP_UNUSED_7CFF: /* 0x17c */ 9506/* File: armv5te/OP_UNUSED_7CFF.S */ 9507/* File: armv5te/unused.S */ 9508 bl common_abort 9509 9510 9511/* ------------------------------ */ 9512 .balign 64 9513.L_OP_UNUSED_7DFF: /* 0x17d */ 9514/* File: armv5te/OP_UNUSED_7DFF.S */ 9515/* File: armv5te/unused.S */ 9516 bl common_abort 9517 9518 9519/* ------------------------------ */ 9520 .balign 64 9521.L_OP_UNUSED_7EFF: /* 0x17e */ 9522/* File: armv5te/OP_UNUSED_7EFF.S */ 9523/* File: armv5te/unused.S */ 9524 bl common_abort 9525 9526 9527/* ------------------------------ */ 9528 .balign 64 9529.L_OP_UNUSED_7FFF: /* 0x17f */ 9530/* File: armv5te/OP_UNUSED_7FFF.S */ 9531/* File: armv5te/unused.S */ 9532 bl common_abort 9533 9534 9535/* ------------------------------ */ 9536 .balign 64 9537.L_OP_UNUSED_80FF: /* 0x180 */ 9538/* File: armv5te/OP_UNUSED_80FF.S */ 9539/* File: armv5te/unused.S */ 9540 bl common_abort 9541 9542 9543/* ------------------------------ */ 9544 .balign 64 9545.L_OP_UNUSED_81FF: /* 0x181 */ 9546/* File: armv5te/OP_UNUSED_81FF.S */ 9547/* File: armv5te/unused.S */ 9548 bl common_abort 9549 9550 9551/* ------------------------------ */ 9552 .balign 64 9553.L_OP_UNUSED_82FF: /* 0x182 */ 9554/* File: armv5te/OP_UNUSED_82FF.S */ 9555/* File: armv5te/unused.S */ 9556 bl common_abort 9557 9558 9559/* ------------------------------ */ 9560 .balign 64 9561.L_OP_UNUSED_83FF: /* 0x183 */ 9562/* File: armv5te/OP_UNUSED_83FF.S */ 9563/* File: armv5te/unused.S */ 9564 bl common_abort 9565 9566 9567/* ------------------------------ */ 9568 .balign 64 9569.L_OP_UNUSED_84FF: /* 0x184 */ 9570/* File: armv5te/OP_UNUSED_84FF.S */ 9571/* File: armv5te/unused.S */ 9572 bl common_abort 9573 9574 9575/* ------------------------------ */ 9576 .balign 64 9577.L_OP_UNUSED_85FF: /* 0x185 */ 9578/* File: armv5te/OP_UNUSED_85FF.S */ 9579/* File: armv5te/unused.S */ 9580 bl common_abort 9581 9582 9583/* ------------------------------ */ 9584 .balign 64 9585.L_OP_UNUSED_86FF: /* 0x186 */ 9586/* File: armv5te/OP_UNUSED_86FF.S */ 9587/* File: armv5te/unused.S */ 9588 bl common_abort 9589 9590 9591/* ------------------------------ */ 9592 .balign 64 9593.L_OP_UNUSED_87FF: /* 0x187 */ 9594/* File: armv5te/OP_UNUSED_87FF.S */ 9595/* File: armv5te/unused.S */ 9596 bl common_abort 9597 9598 9599/* ------------------------------ */ 9600 .balign 64 9601.L_OP_UNUSED_88FF: /* 0x188 */ 9602/* File: armv5te/OP_UNUSED_88FF.S */ 9603/* File: armv5te/unused.S */ 9604 bl common_abort 9605 9606 9607/* ------------------------------ */ 9608 .balign 64 9609.L_OP_UNUSED_89FF: /* 0x189 */ 9610/* File: armv5te/OP_UNUSED_89FF.S */ 9611/* File: armv5te/unused.S */ 9612 bl common_abort 9613 9614 9615/* ------------------------------ */ 9616 .balign 64 9617.L_OP_UNUSED_8AFF: /* 0x18a */ 9618/* File: armv5te/OP_UNUSED_8AFF.S */ 9619/* File: armv5te/unused.S */ 9620 bl common_abort 9621 9622 9623/* ------------------------------ */ 9624 .balign 64 9625.L_OP_UNUSED_8BFF: /* 0x18b */ 9626/* File: armv5te/OP_UNUSED_8BFF.S */ 9627/* File: armv5te/unused.S */ 9628 bl common_abort 9629 9630 9631/* ------------------------------ */ 9632 .balign 64 9633.L_OP_UNUSED_8CFF: /* 0x18c */ 9634/* File: armv5te/OP_UNUSED_8CFF.S */ 9635/* File: armv5te/unused.S */ 9636 bl common_abort 9637 9638 9639/* ------------------------------ */ 9640 .balign 64 9641.L_OP_UNUSED_8DFF: /* 0x18d */ 9642/* File: armv5te/OP_UNUSED_8DFF.S */ 9643/* File: armv5te/unused.S */ 9644 bl common_abort 9645 9646 9647/* ------------------------------ */ 9648 .balign 64 9649.L_OP_UNUSED_8EFF: /* 0x18e */ 9650/* File: armv5te/OP_UNUSED_8EFF.S */ 9651/* File: armv5te/unused.S */ 9652 bl common_abort 9653 9654 9655/* ------------------------------ */ 9656 .balign 64 9657.L_OP_UNUSED_8FFF: /* 0x18f */ 9658/* File: armv5te/OP_UNUSED_8FFF.S */ 9659/* File: armv5te/unused.S */ 9660 bl common_abort 9661 9662 9663/* ------------------------------ */ 9664 .balign 64 9665.L_OP_UNUSED_90FF: /* 0x190 */ 9666/* File: armv5te/OP_UNUSED_90FF.S */ 9667/* File: armv5te/unused.S */ 9668 bl common_abort 9669 9670 9671/* ------------------------------ */ 9672 .balign 64 9673.L_OP_UNUSED_91FF: /* 0x191 */ 9674/* File: armv5te/OP_UNUSED_91FF.S */ 9675/* File: armv5te/unused.S */ 9676 bl common_abort 9677 9678 9679/* ------------------------------ */ 9680 .balign 64 9681.L_OP_UNUSED_92FF: /* 0x192 */ 9682/* File: armv5te/OP_UNUSED_92FF.S */ 9683/* File: armv5te/unused.S */ 9684 bl common_abort 9685 9686 9687/* ------------------------------ */ 9688 .balign 64 9689.L_OP_UNUSED_93FF: /* 0x193 */ 9690/* File: armv5te/OP_UNUSED_93FF.S */ 9691/* File: armv5te/unused.S */ 9692 bl common_abort 9693 9694 9695/* ------------------------------ */ 9696 .balign 64 9697.L_OP_UNUSED_94FF: /* 0x194 */ 9698/* File: armv5te/OP_UNUSED_94FF.S */ 9699/* File: armv5te/unused.S */ 9700 bl common_abort 9701 9702 9703/* ------------------------------ */ 9704 .balign 64 9705.L_OP_UNUSED_95FF: /* 0x195 */ 9706/* File: armv5te/OP_UNUSED_95FF.S */ 9707/* File: armv5te/unused.S */ 9708 bl common_abort 9709 9710 9711/* ------------------------------ */ 9712 .balign 64 9713.L_OP_UNUSED_96FF: /* 0x196 */ 9714/* File: armv5te/OP_UNUSED_96FF.S */ 9715/* File: armv5te/unused.S */ 9716 bl common_abort 9717 9718 9719/* ------------------------------ */ 9720 .balign 64 9721.L_OP_UNUSED_97FF: /* 0x197 */ 9722/* File: armv5te/OP_UNUSED_97FF.S */ 9723/* File: armv5te/unused.S */ 9724 bl common_abort 9725 9726 9727/* ------------------------------ */ 9728 .balign 64 9729.L_OP_UNUSED_98FF: /* 0x198 */ 9730/* File: armv5te/OP_UNUSED_98FF.S */ 9731/* File: armv5te/unused.S */ 9732 bl common_abort 9733 9734 9735/* ------------------------------ */ 9736 .balign 64 9737.L_OP_UNUSED_99FF: /* 0x199 */ 9738/* File: armv5te/OP_UNUSED_99FF.S */ 9739/* File: armv5te/unused.S */ 9740 bl common_abort 9741 9742 9743/* ------------------------------ */ 9744 .balign 64 9745.L_OP_UNUSED_9AFF: /* 0x19a */ 9746/* File: armv5te/OP_UNUSED_9AFF.S */ 9747/* File: armv5te/unused.S */ 9748 bl common_abort 9749 9750 9751/* ------------------------------ */ 9752 .balign 64 9753.L_OP_UNUSED_9BFF: /* 0x19b */ 9754/* File: armv5te/OP_UNUSED_9BFF.S */ 9755/* File: armv5te/unused.S */ 9756 bl common_abort 9757 9758 9759/* ------------------------------ */ 9760 .balign 64 9761.L_OP_UNUSED_9CFF: /* 0x19c */ 9762/* File: armv5te/OP_UNUSED_9CFF.S */ 9763/* File: armv5te/unused.S */ 9764 bl common_abort 9765 9766 9767/* ------------------------------ */ 9768 .balign 64 9769.L_OP_UNUSED_9DFF: /* 0x19d */ 9770/* File: armv5te/OP_UNUSED_9DFF.S */ 9771/* File: armv5te/unused.S */ 9772 bl common_abort 9773 9774 9775/* ------------------------------ */ 9776 .balign 64 9777.L_OP_UNUSED_9EFF: /* 0x19e */ 9778/* File: armv5te/OP_UNUSED_9EFF.S */ 9779/* File: armv5te/unused.S */ 9780 bl common_abort 9781 9782 9783/* ------------------------------ */ 9784 .balign 64 9785.L_OP_UNUSED_9FFF: /* 0x19f */ 9786/* File: armv5te/OP_UNUSED_9FFF.S */ 9787/* File: armv5te/unused.S */ 9788 bl common_abort 9789 9790 9791/* ------------------------------ */ 9792 .balign 64 9793.L_OP_UNUSED_A0FF: /* 0x1a0 */ 9794/* File: armv5te/OP_UNUSED_A0FF.S */ 9795/* File: armv5te/unused.S */ 9796 bl common_abort 9797 9798 9799/* ------------------------------ */ 9800 .balign 64 9801.L_OP_UNUSED_A1FF: /* 0x1a1 */ 9802/* File: armv5te/OP_UNUSED_A1FF.S */ 9803/* File: armv5te/unused.S */ 9804 bl common_abort 9805 9806 9807/* ------------------------------ */ 9808 .balign 64 9809.L_OP_UNUSED_A2FF: /* 0x1a2 */ 9810/* File: armv5te/OP_UNUSED_A2FF.S */ 9811/* File: armv5te/unused.S */ 9812 bl common_abort 9813 9814 9815/* ------------------------------ */ 9816 .balign 64 9817.L_OP_UNUSED_A3FF: /* 0x1a3 */ 9818/* File: armv5te/OP_UNUSED_A3FF.S */ 9819/* File: armv5te/unused.S */ 9820 bl common_abort 9821 9822 9823/* ------------------------------ */ 9824 .balign 64 9825.L_OP_UNUSED_A4FF: /* 0x1a4 */ 9826/* File: armv5te/OP_UNUSED_A4FF.S */ 9827/* File: armv5te/unused.S */ 9828 bl common_abort 9829 9830 9831/* ------------------------------ */ 9832 .balign 64 9833.L_OP_UNUSED_A5FF: /* 0x1a5 */ 9834/* File: armv5te/OP_UNUSED_A5FF.S */ 9835/* File: armv5te/unused.S */ 9836 bl common_abort 9837 9838 9839/* ------------------------------ */ 9840 .balign 64 9841.L_OP_UNUSED_A6FF: /* 0x1a6 */ 9842/* File: armv5te/OP_UNUSED_A6FF.S */ 9843/* File: armv5te/unused.S */ 9844 bl common_abort 9845 9846 9847/* ------------------------------ */ 9848 .balign 64 9849.L_OP_UNUSED_A7FF: /* 0x1a7 */ 9850/* File: armv5te/OP_UNUSED_A7FF.S */ 9851/* File: armv5te/unused.S */ 9852 bl common_abort 9853 9854 9855/* ------------------------------ */ 9856 .balign 64 9857.L_OP_UNUSED_A8FF: /* 0x1a8 */ 9858/* File: armv5te/OP_UNUSED_A8FF.S */ 9859/* File: armv5te/unused.S */ 9860 bl common_abort 9861 9862 9863/* ------------------------------ */ 9864 .balign 64 9865.L_OP_UNUSED_A9FF: /* 0x1a9 */ 9866/* File: armv5te/OP_UNUSED_A9FF.S */ 9867/* File: armv5te/unused.S */ 9868 bl common_abort 9869 9870 9871/* ------------------------------ */ 9872 .balign 64 9873.L_OP_UNUSED_AAFF: /* 0x1aa */ 9874/* File: armv5te/OP_UNUSED_AAFF.S */ 9875/* File: armv5te/unused.S */ 9876 bl common_abort 9877 9878 9879/* ------------------------------ */ 9880 .balign 64 9881.L_OP_UNUSED_ABFF: /* 0x1ab */ 9882/* File: armv5te/OP_UNUSED_ABFF.S */ 9883/* File: armv5te/unused.S */ 9884 bl common_abort 9885 9886 9887/* ------------------------------ */ 9888 .balign 64 9889.L_OP_UNUSED_ACFF: /* 0x1ac */ 9890/* File: armv5te/OP_UNUSED_ACFF.S */ 9891/* File: armv5te/unused.S */ 9892 bl common_abort 9893 9894 9895/* ------------------------------ */ 9896 .balign 64 9897.L_OP_UNUSED_ADFF: /* 0x1ad */ 9898/* File: armv5te/OP_UNUSED_ADFF.S */ 9899/* File: armv5te/unused.S */ 9900 bl common_abort 9901 9902 9903/* ------------------------------ */ 9904 .balign 64 9905.L_OP_UNUSED_AEFF: /* 0x1ae */ 9906/* File: armv5te/OP_UNUSED_AEFF.S */ 9907/* File: armv5te/unused.S */ 9908 bl common_abort 9909 9910 9911/* ------------------------------ */ 9912 .balign 64 9913.L_OP_UNUSED_AFFF: /* 0x1af */ 9914/* File: armv5te/OP_UNUSED_AFFF.S */ 9915/* File: armv5te/unused.S */ 9916 bl common_abort 9917 9918 9919/* ------------------------------ */ 9920 .balign 64 9921.L_OP_UNUSED_B0FF: /* 0x1b0 */ 9922/* File: armv5te/OP_UNUSED_B0FF.S */ 9923/* File: armv5te/unused.S */ 9924 bl common_abort 9925 9926 9927/* ------------------------------ */ 9928 .balign 64 9929.L_OP_UNUSED_B1FF: /* 0x1b1 */ 9930/* File: armv5te/OP_UNUSED_B1FF.S */ 9931/* File: armv5te/unused.S */ 9932 bl common_abort 9933 9934 9935/* ------------------------------ */ 9936 .balign 64 9937.L_OP_UNUSED_B2FF: /* 0x1b2 */ 9938/* File: armv5te/OP_UNUSED_B2FF.S */ 9939/* File: armv5te/unused.S */ 9940 bl common_abort 9941 9942 9943/* ------------------------------ */ 9944 .balign 64 9945.L_OP_UNUSED_B3FF: /* 0x1b3 */ 9946/* File: armv5te/OP_UNUSED_B3FF.S */ 9947/* File: armv5te/unused.S */ 9948 bl common_abort 9949 9950 9951/* ------------------------------ */ 9952 .balign 64 9953.L_OP_UNUSED_B4FF: /* 0x1b4 */ 9954/* File: armv5te/OP_UNUSED_B4FF.S */ 9955/* File: armv5te/unused.S */ 9956 bl common_abort 9957 9958 9959/* ------------------------------ */ 9960 .balign 64 9961.L_OP_UNUSED_B5FF: /* 0x1b5 */ 9962/* File: armv5te/OP_UNUSED_B5FF.S */ 9963/* File: armv5te/unused.S */ 9964 bl common_abort 9965 9966 9967/* ------------------------------ */ 9968 .balign 64 9969.L_OP_UNUSED_B6FF: /* 0x1b6 */ 9970/* File: armv5te/OP_UNUSED_B6FF.S */ 9971/* File: armv5te/unused.S */ 9972 bl common_abort 9973 9974 9975/* ------------------------------ */ 9976 .balign 64 9977.L_OP_UNUSED_B7FF: /* 0x1b7 */ 9978/* File: armv5te/OP_UNUSED_B7FF.S */ 9979/* File: armv5te/unused.S */ 9980 bl common_abort 9981 9982 9983/* ------------------------------ */ 9984 .balign 64 9985.L_OP_UNUSED_B8FF: /* 0x1b8 */ 9986/* File: armv5te/OP_UNUSED_B8FF.S */ 9987/* File: armv5te/unused.S */ 9988 bl common_abort 9989 9990 9991/* ------------------------------ */ 9992 .balign 64 9993.L_OP_UNUSED_B9FF: /* 0x1b9 */ 9994/* File: armv5te/OP_UNUSED_B9FF.S */ 9995/* File: armv5te/unused.S */ 9996 bl common_abort 9997 9998 9999/* ------------------------------ */ 10000 .balign 64 10001.L_OP_UNUSED_BAFF: /* 0x1ba */ 10002/* File: armv5te/OP_UNUSED_BAFF.S */ 10003/* File: armv5te/unused.S */ 10004 bl common_abort 10005 10006 10007/* ------------------------------ */ 10008 .balign 64 10009.L_OP_UNUSED_BBFF: /* 0x1bb */ 10010/* File: armv5te/OP_UNUSED_BBFF.S */ 10011/* File: armv5te/unused.S */ 10012 bl common_abort 10013 10014 10015/* ------------------------------ */ 10016 .balign 64 10017.L_OP_UNUSED_BCFF: /* 0x1bc */ 10018/* File: armv5te/OP_UNUSED_BCFF.S */ 10019/* File: armv5te/unused.S */ 10020 bl common_abort 10021 10022 10023/* ------------------------------ */ 10024 .balign 64 10025.L_OP_UNUSED_BDFF: /* 0x1bd */ 10026/* File: armv5te/OP_UNUSED_BDFF.S */ 10027/* File: armv5te/unused.S */ 10028 bl common_abort 10029 10030 10031/* ------------------------------ */ 10032 .balign 64 10033.L_OP_UNUSED_BEFF: /* 0x1be */ 10034/* File: armv5te/OP_UNUSED_BEFF.S */ 10035/* File: armv5te/unused.S */ 10036 bl common_abort 10037 10038 10039/* ------------------------------ */ 10040 .balign 64 10041.L_OP_UNUSED_BFFF: /* 0x1bf */ 10042/* File: armv5te/OP_UNUSED_BFFF.S */ 10043/* File: armv5te/unused.S */ 10044 bl common_abort 10045 10046 10047/* ------------------------------ */ 10048 .balign 64 10049.L_OP_UNUSED_C0FF: /* 0x1c0 */ 10050/* File: armv5te/OP_UNUSED_C0FF.S */ 10051/* File: armv5te/unused.S */ 10052 bl common_abort 10053 10054 10055/* ------------------------------ */ 10056 .balign 64 10057.L_OP_UNUSED_C1FF: /* 0x1c1 */ 10058/* File: armv5te/OP_UNUSED_C1FF.S */ 10059/* File: armv5te/unused.S */ 10060 bl common_abort 10061 10062 10063/* ------------------------------ */ 10064 .balign 64 10065.L_OP_UNUSED_C2FF: /* 0x1c2 */ 10066/* File: armv5te/OP_UNUSED_C2FF.S */ 10067/* File: armv5te/unused.S */ 10068 bl common_abort 10069 10070 10071/* ------------------------------ */ 10072 .balign 64 10073.L_OP_UNUSED_C3FF: /* 0x1c3 */ 10074/* File: armv5te/OP_UNUSED_C3FF.S */ 10075/* File: armv5te/unused.S */ 10076 bl common_abort 10077 10078 10079/* ------------------------------ */ 10080 .balign 64 10081.L_OP_UNUSED_C4FF: /* 0x1c4 */ 10082/* File: armv5te/OP_UNUSED_C4FF.S */ 10083/* File: armv5te/unused.S */ 10084 bl common_abort 10085 10086 10087/* ------------------------------ */ 10088 .balign 64 10089.L_OP_UNUSED_C5FF: /* 0x1c5 */ 10090/* File: armv5te/OP_UNUSED_C5FF.S */ 10091/* File: armv5te/unused.S */ 10092 bl common_abort 10093 10094 10095/* ------------------------------ */ 10096 .balign 64 10097.L_OP_UNUSED_C6FF: /* 0x1c6 */ 10098/* File: armv5te/OP_UNUSED_C6FF.S */ 10099/* File: armv5te/unused.S */ 10100 bl common_abort 10101 10102 10103/* ------------------------------ */ 10104 .balign 64 10105.L_OP_UNUSED_C7FF: /* 0x1c7 */ 10106/* File: armv5te/OP_UNUSED_C7FF.S */ 10107/* File: armv5te/unused.S */ 10108 bl common_abort 10109 10110 10111/* ------------------------------ */ 10112 .balign 64 10113.L_OP_UNUSED_C8FF: /* 0x1c8 */ 10114/* File: armv5te/OP_UNUSED_C8FF.S */ 10115/* File: armv5te/unused.S */ 10116 bl common_abort 10117 10118 10119/* ------------------------------ */ 10120 .balign 64 10121.L_OP_UNUSED_C9FF: /* 0x1c9 */ 10122/* File: armv5te/OP_UNUSED_C9FF.S */ 10123/* File: armv5te/unused.S */ 10124 bl common_abort 10125 10126 10127/* ------------------------------ */ 10128 .balign 64 10129.L_OP_UNUSED_CAFF: /* 0x1ca */ 10130/* File: armv5te/OP_UNUSED_CAFF.S */ 10131/* File: armv5te/unused.S */ 10132 bl common_abort 10133 10134 10135/* ------------------------------ */ 10136 .balign 64 10137.L_OP_UNUSED_CBFF: /* 0x1cb */ 10138/* File: armv5te/OP_UNUSED_CBFF.S */ 10139/* File: armv5te/unused.S */ 10140 bl common_abort 10141 10142 10143/* ------------------------------ */ 10144 .balign 64 10145.L_OP_UNUSED_CCFF: /* 0x1cc */ 10146/* File: armv5te/OP_UNUSED_CCFF.S */ 10147/* File: armv5te/unused.S */ 10148 bl common_abort 10149 10150 10151/* ------------------------------ */ 10152 .balign 64 10153.L_OP_UNUSED_CDFF: /* 0x1cd */ 10154/* File: armv5te/OP_UNUSED_CDFF.S */ 10155/* File: armv5te/unused.S */ 10156 bl common_abort 10157 10158 10159/* ------------------------------ */ 10160 .balign 64 10161.L_OP_UNUSED_CEFF: /* 0x1ce */ 10162/* File: armv5te/OP_UNUSED_CEFF.S */ 10163/* File: armv5te/unused.S */ 10164 bl common_abort 10165 10166 10167/* ------------------------------ */ 10168 .balign 64 10169.L_OP_UNUSED_CFFF: /* 0x1cf */ 10170/* File: armv5te/OP_UNUSED_CFFF.S */ 10171/* File: armv5te/unused.S */ 10172 bl common_abort 10173 10174 10175/* ------------------------------ */ 10176 .balign 64 10177.L_OP_UNUSED_D0FF: /* 0x1d0 */ 10178/* File: armv5te/OP_UNUSED_D0FF.S */ 10179/* File: armv5te/unused.S */ 10180 bl common_abort 10181 10182 10183/* ------------------------------ */ 10184 .balign 64 10185.L_OP_UNUSED_D1FF: /* 0x1d1 */ 10186/* File: armv5te/OP_UNUSED_D1FF.S */ 10187/* File: armv5te/unused.S */ 10188 bl common_abort 10189 10190 10191/* ------------------------------ */ 10192 .balign 64 10193.L_OP_UNUSED_D2FF: /* 0x1d2 */ 10194/* File: armv5te/OP_UNUSED_D2FF.S */ 10195/* File: armv5te/unused.S */ 10196 bl common_abort 10197 10198 10199/* ------------------------------ */ 10200 .balign 64 10201.L_OP_UNUSED_D3FF: /* 0x1d3 */ 10202/* File: armv5te/OP_UNUSED_D3FF.S */ 10203/* File: armv5te/unused.S */ 10204 bl common_abort 10205 10206 10207/* ------------------------------ */ 10208 .balign 64 10209.L_OP_UNUSED_D4FF: /* 0x1d4 */ 10210/* File: armv5te/OP_UNUSED_D4FF.S */ 10211/* File: armv5te/unused.S */ 10212 bl common_abort 10213 10214 10215/* ------------------------------ */ 10216 .balign 64 10217.L_OP_UNUSED_D5FF: /* 0x1d5 */ 10218/* File: armv5te/OP_UNUSED_D5FF.S */ 10219/* File: armv5te/unused.S */ 10220 bl common_abort 10221 10222 10223/* ------------------------------ */ 10224 .balign 64 10225.L_OP_UNUSED_D6FF: /* 0x1d6 */ 10226/* File: armv5te/OP_UNUSED_D6FF.S */ 10227/* File: armv5te/unused.S */ 10228 bl common_abort 10229 10230 10231/* ------------------------------ */ 10232 .balign 64 10233.L_OP_UNUSED_D7FF: /* 0x1d7 */ 10234/* File: armv5te/OP_UNUSED_D7FF.S */ 10235/* File: armv5te/unused.S */ 10236 bl common_abort 10237 10238 10239/* ------------------------------ */ 10240 .balign 64 10241.L_OP_UNUSED_D8FF: /* 0x1d8 */ 10242/* File: armv5te/OP_UNUSED_D8FF.S */ 10243/* File: armv5te/unused.S */ 10244 bl common_abort 10245 10246 10247/* ------------------------------ */ 10248 .balign 64 10249.L_OP_UNUSED_D9FF: /* 0x1d9 */ 10250/* File: armv5te/OP_UNUSED_D9FF.S */ 10251/* File: armv5te/unused.S */ 10252 bl common_abort 10253 10254 10255/* ------------------------------ */ 10256 .balign 64 10257.L_OP_UNUSED_DAFF: /* 0x1da */ 10258/* File: armv5te/OP_UNUSED_DAFF.S */ 10259/* File: armv5te/unused.S */ 10260 bl common_abort 10261 10262 10263/* ------------------------------ */ 10264 .balign 64 10265.L_OP_UNUSED_DBFF: /* 0x1db */ 10266/* File: armv5te/OP_UNUSED_DBFF.S */ 10267/* File: armv5te/unused.S */ 10268 bl common_abort 10269 10270 10271/* ------------------------------ */ 10272 .balign 64 10273.L_OP_UNUSED_DCFF: /* 0x1dc */ 10274/* File: armv5te/OP_UNUSED_DCFF.S */ 10275/* File: armv5te/unused.S */ 10276 bl common_abort 10277 10278 10279/* ------------------------------ */ 10280 .balign 64 10281.L_OP_UNUSED_DDFF: /* 0x1dd */ 10282/* File: armv5te/OP_UNUSED_DDFF.S */ 10283/* File: armv5te/unused.S */ 10284 bl common_abort 10285 10286 10287/* ------------------------------ */ 10288 .balign 64 10289.L_OP_UNUSED_DEFF: /* 0x1de */ 10290/* File: armv5te/OP_UNUSED_DEFF.S */ 10291/* File: armv5te/unused.S */ 10292 bl common_abort 10293 10294 10295/* ------------------------------ */ 10296 .balign 64 10297.L_OP_UNUSED_DFFF: /* 0x1df */ 10298/* File: armv5te/OP_UNUSED_DFFF.S */ 10299/* File: armv5te/unused.S */ 10300 bl common_abort 10301 10302 10303/* ------------------------------ */ 10304 .balign 64 10305.L_OP_UNUSED_E0FF: /* 0x1e0 */ 10306/* File: armv5te/OP_UNUSED_E0FF.S */ 10307/* File: armv5te/unused.S */ 10308 bl common_abort 10309 10310 10311/* ------------------------------ */ 10312 .balign 64 10313.L_OP_UNUSED_E1FF: /* 0x1e1 */ 10314/* File: armv5te/OP_UNUSED_E1FF.S */ 10315/* File: armv5te/unused.S */ 10316 bl common_abort 10317 10318 10319/* ------------------------------ */ 10320 .balign 64 10321.L_OP_UNUSED_E2FF: /* 0x1e2 */ 10322/* File: armv5te/OP_UNUSED_E2FF.S */ 10323/* File: armv5te/unused.S */ 10324 bl common_abort 10325 10326 10327/* ------------------------------ */ 10328 .balign 64 10329.L_OP_UNUSED_E3FF: /* 0x1e3 */ 10330/* File: armv5te/OP_UNUSED_E3FF.S */ 10331/* File: armv5te/unused.S */ 10332 bl common_abort 10333 10334 10335/* ------------------------------ */ 10336 .balign 64 10337.L_OP_UNUSED_E4FF: /* 0x1e4 */ 10338/* File: armv5te/OP_UNUSED_E4FF.S */ 10339/* File: armv5te/unused.S */ 10340 bl common_abort 10341 10342 10343/* ------------------------------ */ 10344 .balign 64 10345.L_OP_UNUSED_E5FF: /* 0x1e5 */ 10346/* File: armv5te/OP_UNUSED_E5FF.S */ 10347/* File: armv5te/unused.S */ 10348 bl common_abort 10349 10350 10351/* ------------------------------ */ 10352 .balign 64 10353.L_OP_UNUSED_E6FF: /* 0x1e6 */ 10354/* File: armv5te/OP_UNUSED_E6FF.S */ 10355/* File: armv5te/unused.S */ 10356 bl common_abort 10357 10358 10359/* ------------------------------ */ 10360 .balign 64 10361.L_OP_UNUSED_E7FF: /* 0x1e7 */ 10362/* File: armv5te/OP_UNUSED_E7FF.S */ 10363/* File: armv5te/unused.S */ 10364 bl common_abort 10365 10366 10367/* ------------------------------ */ 10368 .balign 64 10369.L_OP_UNUSED_E8FF: /* 0x1e8 */ 10370/* File: armv5te/OP_UNUSED_E8FF.S */ 10371/* File: armv5te/unused.S */ 10372 bl common_abort 10373 10374 10375/* ------------------------------ */ 10376 .balign 64 10377.L_OP_UNUSED_E9FF: /* 0x1e9 */ 10378/* File: armv5te/OP_UNUSED_E9FF.S */ 10379/* File: armv5te/unused.S */ 10380 bl common_abort 10381 10382 10383/* ------------------------------ */ 10384 .balign 64 10385.L_OP_UNUSED_EAFF: /* 0x1ea */ 10386/* File: armv5te/OP_UNUSED_EAFF.S */ 10387/* File: armv5te/unused.S */ 10388 bl common_abort 10389 10390 10391/* ------------------------------ */ 10392 .balign 64 10393.L_OP_UNUSED_EBFF: /* 0x1eb */ 10394/* File: armv5te/OP_UNUSED_EBFF.S */ 10395/* File: armv5te/unused.S */ 10396 bl common_abort 10397 10398 10399/* ------------------------------ */ 10400 .balign 64 10401.L_OP_UNUSED_ECFF: /* 0x1ec */ 10402/* File: armv5te/OP_UNUSED_ECFF.S */ 10403/* File: armv5te/unused.S */ 10404 bl common_abort 10405 10406 10407/* ------------------------------ */ 10408 .balign 64 10409.L_OP_UNUSED_EDFF: /* 0x1ed */ 10410/* File: armv5te/OP_UNUSED_EDFF.S */ 10411/* File: armv5te/unused.S */ 10412 bl common_abort 10413 10414 10415/* ------------------------------ */ 10416 .balign 64 10417.L_OP_UNUSED_EEFF: /* 0x1ee */ 10418/* File: armv5te/OP_UNUSED_EEFF.S */ 10419/* File: armv5te/unused.S */ 10420 bl common_abort 10421 10422 10423/* ------------------------------ */ 10424 .balign 64 10425.L_OP_UNUSED_EFFF: /* 0x1ef */ 10426/* File: armv5te/OP_UNUSED_EFFF.S */ 10427/* File: armv5te/unused.S */ 10428 bl common_abort 10429 10430 10431/* ------------------------------ */ 10432 .balign 64 10433.L_OP_UNUSED_F0FF: /* 0x1f0 */ 10434/* File: armv5te/OP_UNUSED_F0FF.S */ 10435/* File: armv5te/unused.S */ 10436 bl common_abort 10437 10438 10439/* ------------------------------ */ 10440 .balign 64 10441.L_OP_UNUSED_F1FF: /* 0x1f1 */ 10442/* File: armv5te/OP_UNUSED_F1FF.S */ 10443/* File: armv5te/unused.S */ 10444 bl common_abort 10445 10446 10447/* ------------------------------ */ 10448 .balign 64 10449.L_OP_UNUSED_F2FF: /* 0x1f2 */ 10450/* File: armv5te/OP_UNUSED_F2FF.S */ 10451/* File: armv5te/unused.S */ 10452 bl common_abort 10453 10454 10455/* ------------------------------ */ 10456 .balign 64 10457.L_OP_UNUSED_F3FF: /* 0x1f3 */ 10458/* File: armv5te/OP_UNUSED_F3FF.S */ 10459/* File: armv5te/unused.S */ 10460 bl common_abort 10461 10462 10463/* ------------------------------ */ 10464 .balign 64 10465.L_OP_UNUSED_F4FF: /* 0x1f4 */ 10466/* File: armv5te/OP_UNUSED_F4FF.S */ 10467/* File: armv5te/unused.S */ 10468 bl common_abort 10469 10470 10471/* ------------------------------ */ 10472 .balign 64 10473.L_OP_UNUSED_F5FF: /* 0x1f5 */ 10474/* File: armv5te/OP_UNUSED_F5FF.S */ 10475/* File: armv5te/unused.S */ 10476 bl common_abort 10477 10478 10479/* ------------------------------ */ 10480 .balign 64 10481.L_OP_UNUSED_F6FF: /* 0x1f6 */ 10482/* File: armv5te/OP_UNUSED_F6FF.S */ 10483/* File: armv5te/unused.S */ 10484 bl common_abort 10485 10486 10487/* ------------------------------ */ 10488 .balign 64 10489.L_OP_UNUSED_F7FF: /* 0x1f7 */ 10490/* File: armv5te/OP_UNUSED_F7FF.S */ 10491/* File: armv5te/unused.S */ 10492 bl common_abort 10493 10494 10495/* ------------------------------ */ 10496 .balign 64 10497.L_OP_UNUSED_F8FF: /* 0x1f8 */ 10498/* File: armv5te/OP_UNUSED_F8FF.S */ 10499/* File: armv5te/unused.S */ 10500 bl common_abort 10501 10502 10503/* ------------------------------ */ 10504 .balign 64 10505.L_OP_UNUSED_F9FF: /* 0x1f9 */ 10506/* File: armv5te/OP_UNUSED_F9FF.S */ 10507/* File: armv5te/unused.S */ 10508 bl common_abort 10509 10510 10511/* ------------------------------ */ 10512 .balign 64 10513.L_OP_UNUSED_FAFF: /* 0x1fa */ 10514/* File: armv5te/OP_UNUSED_FAFF.S */ 10515/* File: armv5te/unused.S */ 10516 bl common_abort 10517 10518 10519/* ------------------------------ */ 10520 .balign 64 10521.L_OP_UNUSED_FBFF: /* 0x1fb */ 10522/* File: armv5te/OP_UNUSED_FBFF.S */ 10523/* File: armv5te/unused.S */ 10524 bl common_abort 10525 10526 10527/* ------------------------------ */ 10528 .balign 64 10529.L_OP_UNUSED_FCFF: /* 0x1fc */ 10530/* File: armv5te/OP_UNUSED_FCFF.S */ 10531/* File: armv5te/unused.S */ 10532 bl common_abort 10533 10534 10535/* ------------------------------ */ 10536 .balign 64 10537.L_OP_UNUSED_FDFF: /* 0x1fd */ 10538/* File: armv5te/OP_UNUSED_FDFF.S */ 10539/* File: armv5te/unused.S */ 10540 bl common_abort 10541 10542 10543/* ------------------------------ */ 10544 .balign 64 10545.L_OP_UNUSED_FEFF: /* 0x1fe */ 10546/* File: armv5te/OP_UNUSED_FEFF.S */ 10547/* File: armv5te/unused.S */ 10548 bl common_abort 10549 10550 10551/* ------------------------------ */ 10552 .balign 64 10553.L_OP_THROW_VERIFICATION_ERROR_JUMBO: /* 0x1ff */ 10554/* File: armv5te/OP_THROW_VERIFICATION_ERROR_JUMBO.S */ 10555 /* 10556 * Handle a jumbo throw-verification-error instruction. This throws an 10557 * exception for an error discovered during verification. The 10558 * exception is indicated by BBBB, with some detail provided by AAAAAAAA. 10559 */ 10560 /* exop BBBB, Class@AAAAAAAA */ 10561 FETCH(r1, 1) @ r1<- aaaa (lo) 10562 FETCH(r2, 2) @ r2<- AAAA (hi) 10563 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 10564 orr r2, r1, r2, lsl #16 @ r2<- AAAAaaaa 10565 EXPORT_PC() @ export the PC 10566 FETCH(r1, 3) @ r1<- BBBB 10567 bl dvmThrowVerificationError @ always throws 10568 b common_exceptionThrown @ handle exception 10569 10570 10571 .balign 64 10572 .size .L_OP_NOP, .-.L_OP_NOP 10573 .global dvmAsmInstructionEnd 10574dvmAsmInstructionEnd: 10575 10576/* 10577 * =========================================================================== 10578 * Sister implementations 10579 * =========================================================================== 10580 */ 10581 .global dvmAsmSisterStart 10582 .type dvmAsmSisterStart, %function 10583 .text 10584 .balign 4 10585dvmAsmSisterStart: 10586 10587/* continuation for OP_CONST_STRING */ 10588 10589 /* 10590 * Continuation if the String has not yet been resolved. 10591 * r1: BBBB (String ref) 10592 * r9: target register 10593 */ 10594.LOP_CONST_STRING_resolve: 10595 EXPORT_PC() 10596 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 10597 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 10598 bl dvmResolveString @ r0<- String reference 10599 cmp r0, #0 @ failed? 10600 beq common_exceptionThrown @ yup, handle the exception 10601 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 10602 GET_INST_OPCODE(ip) @ extract opcode from rINST 10603 SET_VREG(r0, r9) @ vAA<- r0 10604 GOTO_OPCODE(ip) @ jump to next instruction 10605 10606/* continuation for OP_CONST_STRING_JUMBO */ 10607 10608 /* 10609 * Continuation if the String has not yet been resolved. 10610 * r1: BBBBBBBB (String ref) 10611 * r9: target register 10612 */ 10613.LOP_CONST_STRING_JUMBO_resolve: 10614 EXPORT_PC() 10615 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 10616 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 10617 bl dvmResolveString @ r0<- String reference 10618 cmp r0, #0 @ failed? 10619 beq common_exceptionThrown @ yup, handle the exception 10620 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 10621 GET_INST_OPCODE(ip) @ extract opcode from rINST 10622 SET_VREG(r0, r9) @ vAA<- r0 10623 GOTO_OPCODE(ip) @ jump to next instruction 10624 10625/* continuation for OP_CONST_CLASS */ 10626 10627 /* 10628 * Continuation if the Class has not yet been resolved. 10629 * r1: BBBB (Class ref) 10630 * r9: target register 10631 */ 10632.LOP_CONST_CLASS_resolve: 10633 EXPORT_PC() 10634 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 10635 mov r2, #1 @ r2<- true 10636 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 10637 bl dvmResolveClass @ r0<- Class reference 10638 cmp r0, #0 @ failed? 10639 beq common_exceptionThrown @ yup, handle the exception 10640 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 10641 GET_INST_OPCODE(ip) @ extract opcode from rINST 10642 SET_VREG(r0, r9) @ vAA<- r0 10643 GOTO_OPCODE(ip) @ jump to next instruction 10644 10645/* continuation for OP_CHECK_CAST */ 10646 10647 /* 10648 * Trivial test failed, need to perform full check. This is common. 10649 * r0 holds obj->clazz 10650 * r1 holds desired class resolved from BBBB 10651 * r9 holds object 10652 */ 10653.LOP_CHECK_CAST_fullcheck: 10654 mov r10, r1 @ avoid ClassObject getting clobbered 10655 bl dvmInstanceofNonTrivial @ r0<- boolean result 10656 cmp r0, #0 @ failed? 10657 bne .LOP_CHECK_CAST_okay @ no, success 10658 10659 @ A cast has failed. We need to throw a ClassCastException. 10660 EXPORT_PC() @ about to throw 10661 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz (actual class) 10662 mov r1, r10 @ r1<- desired class 10663 bl dvmThrowClassCastException 10664 b common_exceptionThrown 10665 10666 /* 10667 * Resolution required. This is the least-likely path. 10668 * 10669 * r2 holds BBBB 10670 * r9 holds object 10671 */ 10672.LOP_CHECK_CAST_resolve: 10673 EXPORT_PC() @ resolve() could throw 10674 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 10675 mov r1, r2 @ r1<- BBBB 10676 mov r2, #0 @ r2<- false 10677 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 10678 bl dvmResolveClass @ r0<- resolved ClassObject ptr 10679 cmp r0, #0 @ got null? 10680 beq common_exceptionThrown @ yes, handle exception 10681 mov r1, r0 @ r1<- class resolved from BBB 10682 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 10683 b .LOP_CHECK_CAST_resolved @ pick up where we left off 10684 10685/* continuation for OP_INSTANCE_OF */ 10686 10687 /* 10688 * Trivial test failed, need to perform full check. This is common. 10689 * r0 holds obj->clazz 10690 * r1 holds class resolved from BBBB 10691 * r9 holds A 10692 */ 10693.LOP_INSTANCE_OF_fullcheck: 10694 bl dvmInstanceofNonTrivial @ r0<- boolean result 10695 @ fall through to OP_INSTANCE_OF_store 10696 10697 /* 10698 * r0 holds boolean result 10699 * r9 holds A 10700 */ 10701.LOP_INSTANCE_OF_store: 10702 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 10703 SET_VREG(r0, r9) @ vA<- r0 10704 GET_INST_OPCODE(ip) @ extract opcode from rINST 10705 GOTO_OPCODE(ip) @ jump to next instruction 10706 10707 /* 10708 * Trivial test succeeded, save and bail. 10709 * r9 holds A 10710 */ 10711.LOP_INSTANCE_OF_trivial: 10712 mov r0, #1 @ indicate success 10713 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 10714 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 10715 SET_VREG(r0, r9) @ vA<- r0 10716 GET_INST_OPCODE(ip) @ extract opcode from rINST 10717 GOTO_OPCODE(ip) @ jump to next instruction 10718 10719 /* 10720 * Resolution required. This is the least-likely path. 10721 * 10722 * r3 holds BBBB 10723 * r9 holds A 10724 */ 10725.LOP_INSTANCE_OF_resolve: 10726 EXPORT_PC() @ resolve() could throw 10727 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 10728 mov r1, r3 @ r1<- BBBB 10729 mov r2, #1 @ r2<- true 10730 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 10731 bl dvmResolveClass @ r0<- resolved ClassObject ptr 10732 cmp r0, #0 @ got null? 10733 beq common_exceptionThrown @ yes, handle exception 10734 mov r1, r0 @ r1<- class resolved from BBB 10735 mov r3, rINST, lsr #12 @ r3<- B 10736 GET_VREG(r0, r3) @ r0<- vB (object) 10737 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 10738 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 10739 10740/* continuation for OP_NEW_INSTANCE */ 10741 10742 .balign 32 @ minimize cache lines 10743.LOP_NEW_INSTANCE_finish: @ r0=new object 10744 mov r3, rINST, lsr #8 @ r3<- AA 10745 cmp r0, #0 @ failed? 10746 beq common_exceptionThrown @ yes, handle the exception 10747 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 10748 GET_INST_OPCODE(ip) @ extract opcode from rINST 10749 SET_VREG(r0, r3) @ vAA<- r0 10750 GOTO_OPCODE(ip) @ jump to next instruction 10751 10752 /* 10753 * Class initialization required. 10754 * 10755 * r0 holds class object 10756 */ 10757.LOP_NEW_INSTANCE_needinit: 10758 mov r9, r0 @ save r0 10759 bl dvmInitClass @ initialize class 10760 cmp r0, #0 @ check boolean result 10761 mov r0, r9 @ restore r0 10762 bne .LOP_NEW_INSTANCE_initialized @ success, continue 10763 b common_exceptionThrown @ failed, deal with init exception 10764 10765 /* 10766 * Resolution required. This is the least-likely path. 10767 * 10768 * r1 holds BBBB 10769 */ 10770.LOP_NEW_INSTANCE_resolve: 10771 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 10772 mov r2, #0 @ r2<- false 10773 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 10774 bl dvmResolveClass @ r0<- resolved ClassObject ptr 10775 cmp r0, #0 @ got null? 10776 bne .LOP_NEW_INSTANCE_resolved @ no, continue 10777 b common_exceptionThrown @ yes, handle exception 10778 10779.LstrInstantiationErrorPtr: 10780 .word .LstrInstantiationError 10781 10782/* continuation for OP_NEW_ARRAY */ 10783 10784 10785 /* 10786 * Resolve class. (This is an uncommon case.) 10787 * 10788 * r1 holds array length 10789 * r2 holds class ref CCCC 10790 */ 10791.LOP_NEW_ARRAY_resolve: 10792 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 10793 mov r9, r1 @ r9<- length (save) 10794 mov r1, r2 @ r1<- CCCC 10795 mov r2, #0 @ r2<- false 10796 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 10797 bl dvmResolveClass @ r0<- call(clazz, ref) 10798 cmp r0, #0 @ got null? 10799 mov r1, r9 @ r1<- length (restore) 10800 beq common_exceptionThrown @ yes, handle exception 10801 @ fall through to OP_NEW_ARRAY_finish 10802 10803 /* 10804 * Finish allocation. 10805 * 10806 * r0 holds class 10807 * r1 holds array length 10808 */ 10809.LOP_NEW_ARRAY_finish: 10810 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 10811 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 10812 cmp r0, #0 @ failed? 10813 mov r2, rINST, lsr #8 @ r2<- A+ 10814 beq common_exceptionThrown @ yes, handle the exception 10815 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 10816 and r2, r2, #15 @ r2<- A 10817 GET_INST_OPCODE(ip) @ extract opcode from rINST 10818 SET_VREG(r0, r2) @ vA<- r0 10819 GOTO_OPCODE(ip) @ jump to next instruction 10820 10821/* continuation for OP_FILLED_NEW_ARRAY */ 10822 10823 /* 10824 * On entry: 10825 * r0 holds array class 10826 * r10 holds AA or BA 10827 */ 10828.LOP_FILLED_NEW_ARRAY_continue: 10829 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 10830 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 10831 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 10832 .if 0 10833 mov r1, r10 @ r1<- AA (length) 10834 .else 10835 mov r1, r10, lsr #4 @ r1<- B (length) 10836 .endif 10837 cmp rINST, #'I' @ array of ints? 10838 cmpne rINST, #'L' @ array of objects? 10839 cmpne rINST, #'[' @ array of arrays? 10840 mov r9, r1 @ save length in r9 10841 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 10842 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 10843 cmp r0, #0 @ null return? 10844 beq common_exceptionThrown @ alloc failed, handle exception 10845 10846 FETCH(r1, 2) @ r1<- FEDC or CCCC 10847 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 10848 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 10849 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 10850 subs r9, r9, #1 @ length--, check for neg 10851 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 10852 bmi 2f @ was zero, bail 10853 10854 @ copy values from registers into the array 10855 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 10856 .if 0 10857 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 108581: ldr r3, [r2], #4 @ r3<- *r2++ 10859 subs r9, r9, #1 @ count-- 10860 str r3, [r0], #4 @ *contents++ = vX 10861 bpl 1b 10862 @ continue at 2 10863 .else 10864 cmp r9, #4 @ length was initially 5? 10865 and r2, r10, #15 @ r2<- A 10866 bne 1f @ <= 4 args, branch 10867 GET_VREG(r3, r2) @ r3<- vA 10868 sub r9, r9, #1 @ count-- 10869 str r3, [r0, #16] @ contents[4] = vA 108701: and r2, r1, #15 @ r2<- F/E/D/C 10871 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 10872 mov r1, r1, lsr #4 @ r1<- next reg in low 4 10873 subs r9, r9, #1 @ count-- 10874 str r3, [r0], #4 @ *contents++ = vX 10875 bpl 1b 10876 @ continue at 2 10877 .endif 10878 108792: 10880 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 10881 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 10882 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 10883 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 10884 cmp r1, #'I' @ Is int array? 10885 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 10886 GOTO_OPCODE(ip) @ execute it 10887 10888 /* 10889 * Throw an exception indicating that we have not implemented this 10890 * mode of filled-new-array. 10891 */ 10892.LOP_FILLED_NEW_ARRAY_notimpl: 10893 ldr r0, .L_strInternalError 10894 ldr r1, .L_strFilledNewArrayNotImpl 10895 bl dvmThrowException 10896 b common_exceptionThrown 10897 10898 .if (!0) @ define in one or the other, not both 10899.L_strFilledNewArrayNotImpl: 10900 .word .LstrFilledNewArrayNotImpl 10901.L_strInternalError: 10902 .word .LstrInternalError 10903 .endif 10904 10905/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 10906 10907 /* 10908 * On entry: 10909 * r0 holds array class 10910 * r10 holds AA or BA 10911 */ 10912.LOP_FILLED_NEW_ARRAY_RANGE_continue: 10913 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 10914 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 10915 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 10916 .if 1 10917 mov r1, r10 @ r1<- AA (length) 10918 .else 10919 mov r1, r10, lsr #4 @ r1<- B (length) 10920 .endif 10921 cmp rINST, #'I' @ array of ints? 10922 cmpne rINST, #'L' @ array of objects? 10923 cmpne rINST, #'[' @ array of arrays? 10924 mov r9, r1 @ save length in r9 10925 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 10926 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 10927 cmp r0, #0 @ null return? 10928 beq common_exceptionThrown @ alloc failed, handle exception 10929 10930 FETCH(r1, 2) @ r1<- FEDC or CCCC 10931 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 10932 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 10933 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 10934 subs r9, r9, #1 @ length--, check for neg 10935 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 10936 bmi 2f @ was zero, bail 10937 10938 @ copy values from registers into the array 10939 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 10940 .if 1 10941 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 109421: ldr r3, [r2], #4 @ r3<- *r2++ 10943 subs r9, r9, #1 @ count-- 10944 str r3, [r0], #4 @ *contents++ = vX 10945 bpl 1b 10946 @ continue at 2 10947 .else 10948 cmp r9, #4 @ length was initially 5? 10949 and r2, r10, #15 @ r2<- A 10950 bne 1f @ <= 4 args, branch 10951 GET_VREG(r3, r2) @ r3<- vA 10952 sub r9, r9, #1 @ count-- 10953 str r3, [r0, #16] @ contents[4] = vA 109541: and r2, r1, #15 @ r2<- F/E/D/C 10955 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 10956 mov r1, r1, lsr #4 @ r1<- next reg in low 4 10957 subs r9, r9, #1 @ count-- 10958 str r3, [r0], #4 @ *contents++ = vX 10959 bpl 1b 10960 @ continue at 2 10961 .endif 10962 109632: 10964 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 10965 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 10966 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 10967 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 10968 cmp r1, #'I' @ Is int array? 10969 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 10970 GOTO_OPCODE(ip) @ execute it 10971 10972 /* 10973 * Throw an exception indicating that we have not implemented this 10974 * mode of filled-new-array. 10975 */ 10976.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 10977 ldr r0, .L_strInternalError 10978 ldr r1, .L_strFilledNewArrayNotImpl 10979 bl dvmThrowException 10980 b common_exceptionThrown 10981 10982 .if (!1) @ define in one or the other, not both 10983.L_strFilledNewArrayNotImpl: 10984 .word .LstrFilledNewArrayNotImpl 10985.L_strInternalError: 10986 .word .LstrInternalError 10987 .endif 10988 10989/* continuation for OP_CMPL_FLOAT */ 10990.LOP_CMPL_FLOAT_finish: 10991 SET_VREG(r0, r9) @ vAA<- r0 10992 GOTO_OPCODE(ip) @ jump to next instruction 10993 10994/* continuation for OP_CMPG_FLOAT */ 10995.LOP_CMPG_FLOAT_finish: 10996 SET_VREG(r0, r9) @ vAA<- r0 10997 GOTO_OPCODE(ip) @ jump to next instruction 10998 10999/* continuation for OP_CMPL_DOUBLE */ 11000.LOP_CMPL_DOUBLE_finish: 11001 SET_VREG(r0, r9) @ vAA<- r0 11002 GOTO_OPCODE(ip) @ jump to next instruction 11003 11004/* continuation for OP_CMPG_DOUBLE */ 11005.LOP_CMPG_DOUBLE_finish: 11006 SET_VREG(r0, r9) @ vAA<- r0 11007 GOTO_OPCODE(ip) @ jump to next instruction 11008 11009/* continuation for OP_CMP_LONG */ 11010 11011.LOP_CMP_LONG_less: 11012 mvn r1, #0 @ r1<- -1 11013 @ Want to cond code the next mov so we can avoid branch, but don't see it; 11014 @ instead, we just replicate the tail end. 11015 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11016 SET_VREG(r1, r9) @ vAA<- r1 11017 GET_INST_OPCODE(ip) @ extract opcode from rINST 11018 GOTO_OPCODE(ip) @ jump to next instruction 11019 11020.LOP_CMP_LONG_greater: 11021 mov r1, #1 @ r1<- 1 11022 @ fall through to _finish 11023 11024.LOP_CMP_LONG_finish: 11025 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11026 SET_VREG(r1, r9) @ vAA<- r1 11027 GET_INST_OPCODE(ip) @ extract opcode from rINST 11028 GOTO_OPCODE(ip) @ jump to next instruction 11029 11030/* continuation for OP_AGET_WIDE */ 11031 11032.LOP_AGET_WIDE_finish: 11033 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11034 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 11035 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 11036 GET_INST_OPCODE(ip) @ extract opcode from rINST 11037 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 11038 GOTO_OPCODE(ip) @ jump to next instruction 11039 11040/* continuation for OP_APUT_WIDE */ 11041 11042.LOP_APUT_WIDE_finish: 11043 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11044 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 11045 GET_INST_OPCODE(ip) @ extract opcode from rINST 11046 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 11047 GOTO_OPCODE(ip) @ jump to next instruction 11048 11049/* continuation for OP_APUT_OBJECT */ 11050 /* 11051 * On entry: 11052 * rINST = vBB (arrayObj) 11053 * r9 = vAA (obj) 11054 * r10 = offset into array (vBB + vCC * width) 11055 */ 11056.LOP_APUT_OBJECT_finish: 11057 cmp r9, #0 @ storing null reference? 11058 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 11059 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 11060 ldr r1, [rINST, #offObject_clazz] @ r1<- arrayObj->clazz 11061 bl dvmCanPutArrayElement @ test object type vs. array type 11062 cmp r0, #0 @ okay? 11063 beq .LOP_APUT_OBJECT_throw @ no 11064 mov r1, rINST @ r1<- arrayObj 11065 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11066 ldr r2, [rGLUE, #offGlue_cardTable] @ get biased CT base 11067 add r10, #offArrayObject_contents @ r0<- pointer to slot 11068 GET_INST_OPCODE(ip) @ extract opcode from rINST 11069 str r9, [r10] @ vBB[vCC]<- vAA 11070 strb r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head 11071 GOTO_OPCODE(ip) @ jump to next instruction 11072.LOP_APUT_OBJECT_skip_check: 11073 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11074 GET_INST_OPCODE(ip) @ extract opcode from rINST 11075 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 11076 GOTO_OPCODE(ip) @ jump to next instruction 11077.LOP_APUT_OBJECT_throw: 11078 @ The types don't match. We need to throw an ArrayStoreException. 11079 ldr r0, [r9, #offObject_clazz] 11080 ldr r1, [rINST, #offObject_clazz] 11081 EXPORT_PC() 11082 bl dvmThrowArrayStoreException 11083 b common_exceptionThrown 11084 11085/* continuation for OP_IGET */ 11086 11087 /* 11088 * Currently: 11089 * r0 holds resolved field 11090 * r9 holds object 11091 */ 11092.LOP_IGET_finish: 11093 @bl common_squeak0 11094 cmp r9, #0 @ check object for null 11095 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11096 beq common_errNullObject @ object was null 11097 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11098 @ no-op @ acquiring load 11099 mov r2, rINST, lsr #8 @ r2<- A+ 11100 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11101 and r2, r2, #15 @ r2<- A 11102 GET_INST_OPCODE(ip) @ extract opcode from rINST 11103 SET_VREG(r0, r2) @ fp[A]<- r0 11104 GOTO_OPCODE(ip) @ jump to next instruction 11105 11106/* continuation for OP_IGET_WIDE */ 11107 11108 /* 11109 * Currently: 11110 * r0 holds resolved field 11111 * r9 holds object 11112 */ 11113.LOP_IGET_WIDE_finish: 11114 cmp r9, #0 @ check object for null 11115 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11116 beq common_errNullObject @ object was null 11117 .if 0 11118 add r0, r9, r3 @ r0<- address of field 11119 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 11120 .else 11121 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 11122 .endif 11123 mov r2, rINST, lsr #8 @ r2<- A+ 11124 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11125 and r2, r2, #15 @ r2<- A 11126 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 11127 GET_INST_OPCODE(ip) @ extract opcode from rINST 11128 stmia r3, {r0-r1} @ fp[A]<- r0/r1 11129 GOTO_OPCODE(ip) @ jump to next instruction 11130 11131/* continuation for OP_IGET_OBJECT */ 11132 11133 /* 11134 * Currently: 11135 * r0 holds resolved field 11136 * r9 holds object 11137 */ 11138.LOP_IGET_OBJECT_finish: 11139 @bl common_squeak0 11140 cmp r9, #0 @ check object for null 11141 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11142 beq common_errNullObject @ object was null 11143 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11144 @ no-op @ acquiring load 11145 mov r2, rINST, lsr #8 @ r2<- A+ 11146 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11147 and r2, r2, #15 @ r2<- A 11148 GET_INST_OPCODE(ip) @ extract opcode from rINST 11149 SET_VREG(r0, r2) @ fp[A]<- r0 11150 GOTO_OPCODE(ip) @ jump to next instruction 11151 11152/* continuation for OP_IGET_BOOLEAN */ 11153 11154 /* 11155 * Currently: 11156 * r0 holds resolved field 11157 * r9 holds object 11158 */ 11159.LOP_IGET_BOOLEAN_finish: 11160 @bl common_squeak1 11161 cmp r9, #0 @ check object for null 11162 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11163 beq common_errNullObject @ object was null 11164 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11165 @ no-op @ acquiring load 11166 mov r2, rINST, lsr #8 @ r2<- A+ 11167 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11168 and r2, r2, #15 @ r2<- A 11169 GET_INST_OPCODE(ip) @ extract opcode from rINST 11170 SET_VREG(r0, r2) @ fp[A]<- r0 11171 GOTO_OPCODE(ip) @ jump to next instruction 11172 11173/* continuation for OP_IGET_BYTE */ 11174 11175 /* 11176 * Currently: 11177 * r0 holds resolved field 11178 * r9 holds object 11179 */ 11180.LOP_IGET_BYTE_finish: 11181 @bl common_squeak2 11182 cmp r9, #0 @ check object for null 11183 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11184 beq common_errNullObject @ object was null 11185 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11186 @ no-op @ acquiring load 11187 mov r2, rINST, lsr #8 @ r2<- A+ 11188 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11189 and r2, r2, #15 @ r2<- A 11190 GET_INST_OPCODE(ip) @ extract opcode from rINST 11191 SET_VREG(r0, r2) @ fp[A]<- r0 11192 GOTO_OPCODE(ip) @ jump to next instruction 11193 11194/* continuation for OP_IGET_CHAR */ 11195 11196 /* 11197 * Currently: 11198 * r0 holds resolved field 11199 * r9 holds object 11200 */ 11201.LOP_IGET_CHAR_finish: 11202 @bl common_squeak3 11203 cmp r9, #0 @ check object for null 11204 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11205 beq common_errNullObject @ object was null 11206 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11207 @ no-op @ acquiring load 11208 mov r2, rINST, lsr #8 @ r2<- A+ 11209 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11210 and r2, r2, #15 @ r2<- A 11211 GET_INST_OPCODE(ip) @ extract opcode from rINST 11212 SET_VREG(r0, r2) @ fp[A]<- r0 11213 GOTO_OPCODE(ip) @ jump to next instruction 11214 11215/* continuation for OP_IGET_SHORT */ 11216 11217 /* 11218 * Currently: 11219 * r0 holds resolved field 11220 * r9 holds object 11221 */ 11222.LOP_IGET_SHORT_finish: 11223 @bl common_squeak4 11224 cmp r9, #0 @ check object for null 11225 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11226 beq common_errNullObject @ object was null 11227 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11228 @ no-op @ acquiring load 11229 mov r2, rINST, lsr #8 @ r2<- A+ 11230 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11231 and r2, r2, #15 @ r2<- A 11232 GET_INST_OPCODE(ip) @ extract opcode from rINST 11233 SET_VREG(r0, r2) @ fp[A]<- r0 11234 GOTO_OPCODE(ip) @ jump to next instruction 11235 11236/* continuation for OP_IPUT */ 11237 11238 /* 11239 * Currently: 11240 * r0 holds resolved field 11241 * r9 holds object 11242 */ 11243.LOP_IPUT_finish: 11244 @bl common_squeak0 11245 mov r1, rINST, lsr #8 @ r1<- A+ 11246 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11247 and r1, r1, #15 @ r1<- A 11248 cmp r9, #0 @ check object for null 11249 GET_VREG(r0, r1) @ r0<- fp[A] 11250 beq common_errNullObject @ object was null 11251 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11252 GET_INST_OPCODE(ip) @ extract opcode from rINST 11253 @ no-op @ releasing store 11254 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 11255 GOTO_OPCODE(ip) @ jump to next instruction 11256 11257/* continuation for OP_IPUT_WIDE */ 11258 11259 /* 11260 * Currently: 11261 * r0 holds resolved field 11262 * r9 holds object 11263 */ 11264.LOP_IPUT_WIDE_finish: 11265 mov r2, rINST, lsr #8 @ r2<- A+ 11266 cmp r9, #0 @ check object for null 11267 and r2, r2, #15 @ r2<- A 11268 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11269 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 11270 beq common_errNullObject @ object was null 11271 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11272 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 11273 GET_INST_OPCODE(r10) @ extract opcode from rINST 11274 .if 0 11275 add r2, r9, r3 @ r2<- target address 11276 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 11277 .else 11278 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 11279 .endif 11280 GOTO_OPCODE(r10) @ jump to next instruction 11281 11282/* continuation for OP_IPUT_OBJECT */ 11283 11284 /* 11285 * Currently: 11286 * r0 holds resolved field 11287 * r9 holds object 11288 */ 11289.LOP_IPUT_OBJECT_finish: 11290 @bl common_squeak0 11291 mov r1, rINST, lsr #8 @ r1<- A+ 11292 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11293 and r1, r1, #15 @ r1<- A 11294 cmp r9, #0 @ check object for null 11295 GET_VREG(r0, r1) @ r0<- fp[A] 11296 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 11297 beq common_errNullObject @ object was null 11298 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11299 GET_INST_OPCODE(ip) @ extract opcode from rINST 11300 @ no-op @ releasing store 11301 str r0, [r9, r3] @ obj.field (32 bits)<- r0 11302 cmp r0, #0 @ stored a null reference? 11303 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 11304 GOTO_OPCODE(ip) @ jump to next instruction 11305 11306/* continuation for OP_IPUT_BOOLEAN */ 11307 11308 /* 11309 * Currently: 11310 * r0 holds resolved field 11311 * r9 holds object 11312 */ 11313.LOP_IPUT_BOOLEAN_finish: 11314 @bl common_squeak1 11315 mov r1, rINST, lsr #8 @ r1<- A+ 11316 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11317 and r1, r1, #15 @ r1<- A 11318 cmp r9, #0 @ check object for null 11319 GET_VREG(r0, r1) @ r0<- fp[A] 11320 beq common_errNullObject @ object was null 11321 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11322 GET_INST_OPCODE(ip) @ extract opcode from rINST 11323 @ no-op @ releasing store 11324 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 11325 GOTO_OPCODE(ip) @ jump to next instruction 11326 11327/* continuation for OP_IPUT_BYTE */ 11328 11329 /* 11330 * Currently: 11331 * r0 holds resolved field 11332 * r9 holds object 11333 */ 11334.LOP_IPUT_BYTE_finish: 11335 @bl common_squeak2 11336 mov r1, rINST, lsr #8 @ r1<- A+ 11337 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11338 and r1, r1, #15 @ r1<- A 11339 cmp r9, #0 @ check object for null 11340 GET_VREG(r0, r1) @ r0<- fp[A] 11341 beq common_errNullObject @ object was null 11342 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11343 GET_INST_OPCODE(ip) @ extract opcode from rINST 11344 @ no-op @ releasing store 11345 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 11346 GOTO_OPCODE(ip) @ jump to next instruction 11347 11348/* continuation for OP_IPUT_CHAR */ 11349 11350 /* 11351 * Currently: 11352 * r0 holds resolved field 11353 * r9 holds object 11354 */ 11355.LOP_IPUT_CHAR_finish: 11356 @bl common_squeak3 11357 mov r1, rINST, lsr #8 @ r1<- A+ 11358 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11359 and r1, r1, #15 @ r1<- A 11360 cmp r9, #0 @ check object for null 11361 GET_VREG(r0, r1) @ r0<- fp[A] 11362 beq common_errNullObject @ object was null 11363 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11364 GET_INST_OPCODE(ip) @ extract opcode from rINST 11365 @ no-op @ releasing store 11366 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 11367 GOTO_OPCODE(ip) @ jump to next instruction 11368 11369/* continuation for OP_IPUT_SHORT */ 11370 11371 /* 11372 * Currently: 11373 * r0 holds resolved field 11374 * r9 holds object 11375 */ 11376.LOP_IPUT_SHORT_finish: 11377 @bl common_squeak4 11378 mov r1, rINST, lsr #8 @ r1<- A+ 11379 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11380 and r1, r1, #15 @ r1<- A 11381 cmp r9, #0 @ check object for null 11382 GET_VREG(r0, r1) @ r0<- fp[A] 11383 beq common_errNullObject @ object was null 11384 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11385 GET_INST_OPCODE(ip) @ extract opcode from rINST 11386 @ no-op @ releasing store 11387 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 11388 GOTO_OPCODE(ip) @ jump to next instruction 11389 11390/* continuation for OP_SGET */ 11391 11392 /* 11393 * Continuation if the field has not yet been resolved. 11394 * r1: BBBB field ref 11395 */ 11396.LOP_SGET_resolve: 11397 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11398 EXPORT_PC() @ resolve() could throw, so export now 11399 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11400 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11401 cmp r0, #0 @ success? 11402 bne .LOP_SGET_finish @ yes, finish 11403 b common_exceptionThrown @ no, handle exception 11404 11405/* continuation for OP_SGET_WIDE */ 11406 11407 /* 11408 * Continuation if the field has not yet been resolved. 11409 * r1: BBBB field ref 11410 * 11411 * Returns StaticField pointer in r0. 11412 */ 11413.LOP_SGET_WIDE_resolve: 11414 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11415 EXPORT_PC() @ resolve() could throw, so export now 11416 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11417 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11418 cmp r0, #0 @ success? 11419 bne .LOP_SGET_WIDE_finish @ yes, finish 11420 b common_exceptionThrown @ no, handle exception 11421 11422/* continuation for OP_SGET_OBJECT */ 11423 11424 /* 11425 * Continuation if the field has not yet been resolved. 11426 * r1: BBBB field ref 11427 */ 11428.LOP_SGET_OBJECT_resolve: 11429 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11430 EXPORT_PC() @ resolve() could throw, so export now 11431 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11432 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11433 cmp r0, #0 @ success? 11434 bne .LOP_SGET_OBJECT_finish @ yes, finish 11435 b common_exceptionThrown @ no, handle exception 11436 11437/* continuation for OP_SGET_BOOLEAN */ 11438 11439 /* 11440 * Continuation if the field has not yet been resolved. 11441 * r1: BBBB field ref 11442 */ 11443.LOP_SGET_BOOLEAN_resolve: 11444 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11445 EXPORT_PC() @ resolve() could throw, so export now 11446 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11447 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11448 cmp r0, #0 @ success? 11449 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 11450 b common_exceptionThrown @ no, handle exception 11451 11452/* continuation for OP_SGET_BYTE */ 11453 11454 /* 11455 * Continuation if the field has not yet been resolved. 11456 * r1: BBBB field ref 11457 */ 11458.LOP_SGET_BYTE_resolve: 11459 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11460 EXPORT_PC() @ resolve() could throw, so export now 11461 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11462 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11463 cmp r0, #0 @ success? 11464 bne .LOP_SGET_BYTE_finish @ yes, finish 11465 b common_exceptionThrown @ no, handle exception 11466 11467/* continuation for OP_SGET_CHAR */ 11468 11469 /* 11470 * Continuation if the field has not yet been resolved. 11471 * r1: BBBB field ref 11472 */ 11473.LOP_SGET_CHAR_resolve: 11474 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11475 EXPORT_PC() @ resolve() could throw, so export now 11476 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11477 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11478 cmp r0, #0 @ success? 11479 bne .LOP_SGET_CHAR_finish @ yes, finish 11480 b common_exceptionThrown @ no, handle exception 11481 11482/* continuation for OP_SGET_SHORT */ 11483 11484 /* 11485 * Continuation if the field has not yet been resolved. 11486 * r1: BBBB field ref 11487 */ 11488.LOP_SGET_SHORT_resolve: 11489 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11490 EXPORT_PC() @ resolve() could throw, so export now 11491 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11492 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11493 cmp r0, #0 @ success? 11494 bne .LOP_SGET_SHORT_finish @ yes, finish 11495 b common_exceptionThrown @ no, handle exception 11496 11497/* continuation for OP_SPUT */ 11498 11499 /* 11500 * Continuation if the field has not yet been resolved. 11501 * r1: BBBB field ref 11502 */ 11503.LOP_SPUT_resolve: 11504 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11505 EXPORT_PC() @ resolve() could throw, so export now 11506 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11507 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11508 cmp r0, #0 @ success? 11509 bne .LOP_SPUT_finish @ yes, finish 11510 b common_exceptionThrown @ no, handle exception 11511 11512/* continuation for OP_SPUT_WIDE */ 11513 11514 /* 11515 * Continuation if the field has not yet been resolved. 11516 * r1: BBBB field ref 11517 * r9: &fp[AA] 11518 * 11519 * Returns StaticField pointer in r2. 11520 */ 11521.LOP_SPUT_WIDE_resolve: 11522 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11523 EXPORT_PC() @ resolve() could throw, so export now 11524 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11525 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11526 cmp r0, #0 @ success? 11527 mov r2, r0 @ copy to r2 11528 bne .LOP_SPUT_WIDE_finish @ yes, finish 11529 b common_exceptionThrown @ no, handle exception 11530 11531/* continuation for OP_SPUT_OBJECT */ 11532.LOP_SPUT_OBJECT_finish: @ field ptr in r0 11533 mov r2, rINST, lsr #8 @ r2<- AA 11534 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11535 GET_VREG(r1, r2) @ r1<- fp[AA] 11536 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 11537 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz 11538 GET_INST_OPCODE(ip) @ extract opcode from rINST 11539 @ no-op @ releasing store 11540 str r1, [r0, #offStaticField_value] @ field<- vAA 11541 cmp r1, #0 @ stored a null object? 11542 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 11543 GOTO_OPCODE(ip) @ jump to next instruction 11544 11545/* continuation for OP_SPUT_BOOLEAN */ 11546 11547 /* 11548 * Continuation if the field has not yet been resolved. 11549 * r1: BBBB field ref 11550 */ 11551.LOP_SPUT_BOOLEAN_resolve: 11552 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11553 EXPORT_PC() @ resolve() could throw, so export now 11554 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11555 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11556 cmp r0, #0 @ success? 11557 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 11558 b common_exceptionThrown @ no, handle exception 11559 11560/* continuation for OP_SPUT_BYTE */ 11561 11562 /* 11563 * Continuation if the field has not yet been resolved. 11564 * r1: BBBB field ref 11565 */ 11566.LOP_SPUT_BYTE_resolve: 11567 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11568 EXPORT_PC() @ resolve() could throw, so export now 11569 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11570 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11571 cmp r0, #0 @ success? 11572 bne .LOP_SPUT_BYTE_finish @ yes, finish 11573 b common_exceptionThrown @ no, handle exception 11574 11575/* continuation for OP_SPUT_CHAR */ 11576 11577 /* 11578 * Continuation if the field has not yet been resolved. 11579 * r1: BBBB field ref 11580 */ 11581.LOP_SPUT_CHAR_resolve: 11582 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11583 EXPORT_PC() @ resolve() could throw, so export now 11584 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11585 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11586 cmp r0, #0 @ success? 11587 bne .LOP_SPUT_CHAR_finish @ yes, finish 11588 b common_exceptionThrown @ no, handle exception 11589 11590/* continuation for OP_SPUT_SHORT */ 11591 11592 /* 11593 * Continuation if the field has not yet been resolved. 11594 * r1: BBBB field ref 11595 */ 11596.LOP_SPUT_SHORT_resolve: 11597 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11598 EXPORT_PC() @ resolve() could throw, so export now 11599 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11600 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11601 cmp r0, #0 @ success? 11602 bne .LOP_SPUT_SHORT_finish @ yes, finish 11603 b common_exceptionThrown @ no, handle exception 11604 11605/* continuation for OP_INVOKE_VIRTUAL */ 11606 11607 /* 11608 * At this point: 11609 * r0 = resolved base method 11610 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 11611 */ 11612.LOP_INVOKE_VIRTUAL_continue: 11613 GET_VREG(r1, r10) @ r1<- "this" ptr 11614 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 11615 cmp r1, #0 @ is "this" null? 11616 beq common_errNullObject @ null "this", throw exception 11617 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 11618 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 11619 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 11620 bl common_invokeMethodNoRange @ continue on 11621 11622/* continuation for OP_INVOKE_SUPER */ 11623 11624 /* 11625 * At this point: 11626 * r0 = resolved base method 11627 * r9 = method->clazz 11628 */ 11629.LOP_INVOKE_SUPER_continue: 11630 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 11631 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 11632 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 11633 EXPORT_PC() @ must export for invoke 11634 cmp r2, r3 @ compare (methodIndex, vtableCount) 11635 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 11636 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 11637 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 11638 bl common_invokeMethodNoRange @ continue on 11639 11640.LOP_INVOKE_SUPER_resolve: 11641 mov r0, r9 @ r0<- method->clazz 11642 mov r2, #METHOD_VIRTUAL @ resolver method type 11643 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 11644 cmp r0, #0 @ got null? 11645 bne .LOP_INVOKE_SUPER_continue @ no, continue 11646 b common_exceptionThrown @ yes, handle exception 11647 11648 /* 11649 * Throw a NoSuchMethodError with the method name as the message. 11650 * r0 = resolved base method 11651 */ 11652.LOP_INVOKE_SUPER_nsm: 11653 ldr r1, [r0, #offMethod_name] @ r1<- method name 11654 b common_errNoSuchMethod 11655 11656/* continuation for OP_INVOKE_DIRECT */ 11657 11658 /* 11659 * On entry: 11660 * r1 = reference (BBBB or CCCC) 11661 * r10 = "this" register 11662 */ 11663.LOP_INVOKE_DIRECT_resolve: 11664 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 11665 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 11666 mov r2, #METHOD_DIRECT @ resolver method type 11667 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 11668 cmp r0, #0 @ got null? 11669 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 11670 bne .LOP_INVOKE_DIRECT_finish @ no, continue 11671 b common_exceptionThrown @ yes, handle exception 11672 11673/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 11674 11675 /* 11676 * At this point: 11677 * r0 = resolved base method 11678 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 11679 */ 11680.LOP_INVOKE_VIRTUAL_RANGE_continue: 11681 GET_VREG(r1, r10) @ r1<- "this" ptr 11682 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 11683 cmp r1, #0 @ is "this" null? 11684 beq common_errNullObject @ null "this", throw exception 11685 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 11686 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 11687 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 11688 bl common_invokeMethodRange @ continue on 11689 11690/* continuation for OP_INVOKE_SUPER_RANGE */ 11691 11692 /* 11693 * At this point: 11694 * r0 = resolved base method 11695 * r9 = method->clazz 11696 */ 11697.LOP_INVOKE_SUPER_RANGE_continue: 11698 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 11699 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 11700 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 11701 EXPORT_PC() @ must export for invoke 11702 cmp r2, r3 @ compare (methodIndex, vtableCount) 11703 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 11704 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 11705 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 11706 bl common_invokeMethodRange @ continue on 11707 11708.LOP_INVOKE_SUPER_RANGE_resolve: 11709 mov r0, r9 @ r0<- method->clazz 11710 mov r2, #METHOD_VIRTUAL @ resolver method type 11711 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 11712 cmp r0, #0 @ got null? 11713 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 11714 b common_exceptionThrown @ yes, handle exception 11715 11716 /* 11717 * Throw a NoSuchMethodError with the method name as the message. 11718 * r0 = resolved base method 11719 */ 11720.LOP_INVOKE_SUPER_RANGE_nsm: 11721 ldr r1, [r0, #offMethod_name] @ r1<- method name 11722 b common_errNoSuchMethod 11723 11724/* continuation for OP_INVOKE_DIRECT_RANGE */ 11725 11726 /* 11727 * On entry: 11728 * r1 = reference (BBBB or CCCC) 11729 * r10 = "this" register 11730 */ 11731.LOP_INVOKE_DIRECT_RANGE_resolve: 11732 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 11733 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 11734 mov r2, #METHOD_DIRECT @ resolver method type 11735 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 11736 cmp r0, #0 @ got null? 11737 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 11738 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 11739 b common_exceptionThrown @ yes, handle exception 11740 11741/* continuation for OP_FLOAT_TO_LONG */ 11742/* 11743 * Convert the float in r0 to a long in r0/r1. 11744 * 11745 * We have to clip values to long min/max per the specification. The 11746 * expected common case is a "reasonable" value that converts directly 11747 * to modest integer. The EABI convert function isn't doing this for us. 11748 */ 11749f2l_doconv: 11750 stmfd sp!, {r4, lr} 11751 mov r1, #0x5f000000 @ (float)maxlong 11752 mov r4, r0 11753 bl __aeabi_fcmpge @ is arg >= maxlong? 11754 cmp r0, #0 @ nonzero == yes 11755 mvnne r0, #0 @ return maxlong (7fffffff) 11756 mvnne r1, #0x80000000 11757 ldmnefd sp!, {r4, pc} 11758 11759 mov r0, r4 @ recover arg 11760 mov r1, #0xdf000000 @ (float)minlong 11761 bl __aeabi_fcmple @ is arg <= minlong? 11762 cmp r0, #0 @ nonzero == yes 11763 movne r0, #0 @ return minlong (80000000) 11764 movne r1, #0x80000000 11765 ldmnefd sp!, {r4, pc} 11766 11767 mov r0, r4 @ recover arg 11768 mov r1, r4 11769 bl __aeabi_fcmpeq @ is arg == self? 11770 cmp r0, #0 @ zero == no 11771 moveq r1, #0 @ return zero for NaN 11772 ldmeqfd sp!, {r4, pc} 11773 11774 mov r0, r4 @ recover arg 11775 bl __aeabi_f2lz @ convert float to long 11776 ldmfd sp!, {r4, pc} 11777 11778/* continuation for OP_DOUBLE_TO_LONG */ 11779/* 11780 * Convert the double in r0/r1 to a long in r0/r1. 11781 * 11782 * We have to clip values to long min/max per the specification. The 11783 * expected common case is a "reasonable" value that converts directly 11784 * to modest integer. The EABI convert function isn't doing this for us. 11785 */ 11786d2l_doconv: 11787 stmfd sp!, {r4, r5, lr} @ save regs 11788 mov r3, #0x43000000 @ maxlong, as a double (high word) 11789 add r3, #0x00e00000 @ 0x43e00000 11790 mov r2, #0 @ maxlong, as a double (low word) 11791 sub sp, sp, #4 @ align for EABI 11792 mov r4, r0 @ save a copy of r0 11793 mov r5, r1 @ and r1 11794 bl __aeabi_dcmpge @ is arg >= maxlong? 11795 cmp r0, #0 @ nonzero == yes 11796 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 11797 mvnne r1, #0x80000000 11798 bne 1f 11799 11800 mov r0, r4 @ recover arg 11801 mov r1, r5 11802 mov r3, #0xc3000000 @ minlong, as a double (high word) 11803 add r3, #0x00e00000 @ 0xc3e00000 11804 mov r2, #0 @ minlong, as a double (low word) 11805 bl __aeabi_dcmple @ is arg <= minlong? 11806 cmp r0, #0 @ nonzero == yes 11807 movne r0, #0 @ return minlong (8000000000000000) 11808 movne r1, #0x80000000 11809 bne 1f 11810 11811 mov r0, r4 @ recover arg 11812 mov r1, r5 11813 mov r2, r4 @ compare against self 11814 mov r3, r5 11815 bl __aeabi_dcmpeq @ is arg == self? 11816 cmp r0, #0 @ zero == no 11817 moveq r1, #0 @ return zero for NaN 11818 beq 1f 11819 11820 mov r0, r4 @ recover arg 11821 mov r1, r5 11822 bl __aeabi_d2lz @ convert double to long 11823 118241: 11825 add sp, sp, #4 11826 ldmfd sp!, {r4, r5, pc} 11827 11828/* continuation for OP_MUL_LONG */ 11829 11830.LOP_MUL_LONG_finish: 11831 GET_INST_OPCODE(ip) @ extract opcode from rINST 11832 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 11833 GOTO_OPCODE(ip) @ jump to next instruction 11834 11835/* continuation for OP_SHL_LONG */ 11836 11837.LOP_SHL_LONG_finish: 11838 mov r0, r0, asl r2 @ r0<- r0 << r2 11839 GET_INST_OPCODE(ip) @ extract opcode from rINST 11840 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 11841 GOTO_OPCODE(ip) @ jump to next instruction 11842 11843/* continuation for OP_SHR_LONG */ 11844 11845.LOP_SHR_LONG_finish: 11846 mov r1, r1, asr r2 @ r1<- r1 >> r2 11847 GET_INST_OPCODE(ip) @ extract opcode from rINST 11848 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 11849 GOTO_OPCODE(ip) @ jump to next instruction 11850 11851/* continuation for OP_USHR_LONG */ 11852 11853.LOP_USHR_LONG_finish: 11854 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 11855 GET_INST_OPCODE(ip) @ extract opcode from rINST 11856 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 11857 GOTO_OPCODE(ip) @ jump to next instruction 11858 11859/* continuation for OP_SHL_LONG_2ADDR */ 11860 11861.LOP_SHL_LONG_2ADDR_finish: 11862 GET_INST_OPCODE(ip) @ extract opcode from rINST 11863 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 11864 GOTO_OPCODE(ip) @ jump to next instruction 11865 11866/* continuation for OP_SHR_LONG_2ADDR */ 11867 11868.LOP_SHR_LONG_2ADDR_finish: 11869 GET_INST_OPCODE(ip) @ extract opcode from rINST 11870 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 11871 GOTO_OPCODE(ip) @ jump to next instruction 11872 11873/* continuation for OP_USHR_LONG_2ADDR */ 11874 11875.LOP_USHR_LONG_2ADDR_finish: 11876 GET_INST_OPCODE(ip) @ extract opcode from rINST 11877 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 11878 GOTO_OPCODE(ip) @ jump to next instruction 11879 11880/* continuation for OP_IGET_VOLATILE */ 11881 11882 /* 11883 * Currently: 11884 * r0 holds resolved field 11885 * r9 holds object 11886 */ 11887.LOP_IGET_VOLATILE_finish: 11888 @bl common_squeak0 11889 cmp r9, #0 @ check object for null 11890 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11891 beq common_errNullObject @ object was null 11892 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11893 SMP_DMB @ acquiring load 11894 mov r2, rINST, lsr #8 @ r2<- A+ 11895 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11896 and r2, r2, #15 @ r2<- A 11897 GET_INST_OPCODE(ip) @ extract opcode from rINST 11898 SET_VREG(r0, r2) @ fp[A]<- r0 11899 GOTO_OPCODE(ip) @ jump to next instruction 11900 11901/* continuation for OP_IPUT_VOLATILE */ 11902 11903 /* 11904 * Currently: 11905 * r0 holds resolved field 11906 * r9 holds object 11907 */ 11908.LOP_IPUT_VOLATILE_finish: 11909 @bl common_squeak0 11910 mov r1, rINST, lsr #8 @ r1<- A+ 11911 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11912 and r1, r1, #15 @ r1<- A 11913 cmp r9, #0 @ check object for null 11914 GET_VREG(r0, r1) @ r0<- fp[A] 11915 beq common_errNullObject @ object was null 11916 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11917 GET_INST_OPCODE(ip) @ extract opcode from rINST 11918 SMP_DMB @ releasing store 11919 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 11920 GOTO_OPCODE(ip) @ jump to next instruction 11921 11922/* continuation for OP_SGET_VOLATILE */ 11923 11924 /* 11925 * Continuation if the field has not yet been resolved. 11926 * r1: BBBB field ref 11927 */ 11928.LOP_SGET_VOLATILE_resolve: 11929 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11930 EXPORT_PC() @ resolve() could throw, so export now 11931 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11932 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11933 cmp r0, #0 @ success? 11934 bne .LOP_SGET_VOLATILE_finish @ yes, finish 11935 b common_exceptionThrown @ no, handle exception 11936 11937/* continuation for OP_SPUT_VOLATILE */ 11938 11939 /* 11940 * Continuation if the field has not yet been resolved. 11941 * r1: BBBB field ref 11942 */ 11943.LOP_SPUT_VOLATILE_resolve: 11944 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11945 EXPORT_PC() @ resolve() could throw, so export now 11946 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11947 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11948 cmp r0, #0 @ success? 11949 bne .LOP_SPUT_VOLATILE_finish @ yes, finish 11950 b common_exceptionThrown @ no, handle exception 11951 11952/* continuation for OP_IGET_OBJECT_VOLATILE */ 11953 11954 /* 11955 * Currently: 11956 * r0 holds resolved field 11957 * r9 holds object 11958 */ 11959.LOP_IGET_OBJECT_VOLATILE_finish: 11960 @bl common_squeak0 11961 cmp r9, #0 @ check object for null 11962 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11963 beq common_errNullObject @ object was null 11964 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11965 SMP_DMB @ acquiring load 11966 mov r2, rINST, lsr #8 @ r2<- A+ 11967 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11968 and r2, r2, #15 @ r2<- A 11969 GET_INST_OPCODE(ip) @ extract opcode from rINST 11970 SET_VREG(r0, r2) @ fp[A]<- r0 11971 GOTO_OPCODE(ip) @ jump to next instruction 11972 11973/* continuation for OP_IGET_WIDE_VOLATILE */ 11974 11975 /* 11976 * Currently: 11977 * r0 holds resolved field 11978 * r9 holds object 11979 */ 11980.LOP_IGET_WIDE_VOLATILE_finish: 11981 cmp r9, #0 @ check object for null 11982 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11983 beq common_errNullObject @ object was null 11984 .if 1 11985 add r0, r9, r3 @ r0<- address of field 11986 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 11987 .else 11988 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 11989 .endif 11990 mov r2, rINST, lsr #8 @ r2<- A+ 11991 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11992 and r2, r2, #15 @ r2<- A 11993 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 11994 GET_INST_OPCODE(ip) @ extract opcode from rINST 11995 stmia r3, {r0-r1} @ fp[A]<- r0/r1 11996 GOTO_OPCODE(ip) @ jump to next instruction 11997 11998/* continuation for OP_IPUT_WIDE_VOLATILE */ 11999 12000 /* 12001 * Currently: 12002 * r0 holds resolved field 12003 * r9 holds object 12004 */ 12005.LOP_IPUT_WIDE_VOLATILE_finish: 12006 mov r2, rINST, lsr #8 @ r2<- A+ 12007 cmp r9, #0 @ check object for null 12008 and r2, r2, #15 @ r2<- A 12009 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12010 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 12011 beq common_errNullObject @ object was null 12012 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 12013 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 12014 GET_INST_OPCODE(r10) @ extract opcode from rINST 12015 .if 1 12016 add r2, r9, r3 @ r2<- target address 12017 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 12018 .else 12019 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 12020 .endif 12021 GOTO_OPCODE(r10) @ jump to next instruction 12022 12023/* continuation for OP_SGET_WIDE_VOLATILE */ 12024 12025 /* 12026 * Continuation if the field has not yet been resolved. 12027 * r1: BBBB field ref 12028 * 12029 * Returns StaticField pointer in r0. 12030 */ 12031.LOP_SGET_WIDE_VOLATILE_resolve: 12032 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12033 EXPORT_PC() @ resolve() could throw, so export now 12034 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12035 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12036 cmp r0, #0 @ success? 12037 bne .LOP_SGET_WIDE_VOLATILE_finish @ yes, finish 12038 b common_exceptionThrown @ no, handle exception 12039 12040/* continuation for OP_SPUT_WIDE_VOLATILE */ 12041 12042 /* 12043 * Continuation if the field has not yet been resolved. 12044 * r1: BBBB field ref 12045 * r9: &fp[AA] 12046 * 12047 * Returns StaticField pointer in r2. 12048 */ 12049.LOP_SPUT_WIDE_VOLATILE_resolve: 12050 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12051 EXPORT_PC() @ resolve() could throw, so export now 12052 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12053 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12054 cmp r0, #0 @ success? 12055 mov r2, r0 @ copy to r2 12056 bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish 12057 b common_exceptionThrown @ no, handle exception 12058 12059/* continuation for OP_EXECUTE_INLINE */ 12060 12061 /* 12062 * Extract args, call function. 12063 * r0 = #of args (0-4) 12064 * r10 = call index 12065 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 12066 * 12067 * Other ideas: 12068 * - Use a jump table from the main piece to jump directly into the 12069 * AND/LDR pairs. Costs a data load, saves a branch. 12070 * - Have five separate pieces that do the loading, so we can work the 12071 * interleave a little better. Increases code size. 12072 */ 12073.LOP_EXECUTE_INLINE_continue: 12074 rsb r0, r0, #4 @ r0<- 4-r0 12075 FETCH(r9, 2) @ r9<- FEDC 12076 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 12077 bl common_abort @ (skipped due to ARM prefetch) 120784: and ip, r9, #0xf000 @ isolate F 12079 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 120803: and ip, r9, #0x0f00 @ isolate E 12081 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 120822: and ip, r9, #0x00f0 @ isolate D 12083 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 120841: and ip, r9, #0x000f @ isolate C 12085 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 120860: 12087 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 12088 ldr pc, [r9, r10, lsl #4] @ sizeof=16, "func" is first entry 12089 @ (not reached) 12090 12091.LOP_EXECUTE_INLINE_table: 12092 .word gDvmInlineOpsTable 12093 12094/* continuation for OP_EXECUTE_INLINE_RANGE */ 12095 12096 /* 12097 * Extract args, call function. 12098 * r0 = #of args (0-4) 12099 * r10 = call index 12100 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 12101 */ 12102.LOP_EXECUTE_INLINE_RANGE_continue: 12103 rsb r0, r0, #4 @ r0<- 4-r0 12104 FETCH(r9, 2) @ r9<- CCCC 12105 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 12106 bl common_abort @ (skipped due to ARM prefetch) 121074: add ip, r9, #3 @ base+3 12108 GET_VREG(r3, ip) @ r3<- vBase[3] 121093: add ip, r9, #2 @ base+2 12110 GET_VREG(r2, ip) @ r2<- vBase[2] 121112: add ip, r9, #1 @ base+1 12112 GET_VREG(r1, ip) @ r1<- vBase[1] 121131: add ip, r9, #0 @ (nop) 12114 GET_VREG(r0, ip) @ r0<- vBase[0] 121150: 12116 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation 12117 ldr pc, [r9, r10, lsl #4] @ sizeof=16, "func" is first entry 12118 @ (not reached) 12119 12120.LOP_EXECUTE_INLINE_RANGE_table: 12121 .word gDvmInlineOpsTable 12122 12123/* continuation for OP_IPUT_OBJECT_VOLATILE */ 12124 12125 /* 12126 * Currently: 12127 * r0 holds resolved field 12128 * r9 holds object 12129 */ 12130.LOP_IPUT_OBJECT_VOLATILE_finish: 12131 @bl common_squeak0 12132 mov r1, rINST, lsr #8 @ r1<- A+ 12133 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12134 and r1, r1, #15 @ r1<- A 12135 cmp r9, #0 @ check object for null 12136 GET_VREG(r0, r1) @ r0<- fp[A] 12137 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 12138 beq common_errNullObject @ object was null 12139 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 12140 GET_INST_OPCODE(ip) @ extract opcode from rINST 12141 SMP_DMB @ releasing store 12142 str r0, [r9, r3] @ obj.field (32 bits)<- r0 12143 cmp r0, #0 @ stored a null reference? 12144 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 12145 GOTO_OPCODE(ip) @ jump to next instruction 12146 12147/* continuation for OP_SGET_OBJECT_VOLATILE */ 12148 12149 /* 12150 * Continuation if the field has not yet been resolved. 12151 * r1: BBBB field ref 12152 */ 12153.LOP_SGET_OBJECT_VOLATILE_resolve: 12154 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12155 EXPORT_PC() @ resolve() could throw, so export now 12156 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12157 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12158 cmp r0, #0 @ success? 12159 bne .LOP_SGET_OBJECT_VOLATILE_finish @ yes, finish 12160 b common_exceptionThrown @ no, handle exception 12161 12162/* continuation for OP_SPUT_OBJECT_VOLATILE */ 12163.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0 12164 mov r2, rINST, lsr #8 @ r2<- AA 12165 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 12166 GET_VREG(r1, r2) @ r1<- fp[AA] 12167 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 12168 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz 12169 GET_INST_OPCODE(ip) @ extract opcode from rINST 12170 SMP_DMB @ releasing store 12171 str r1, [r0, #offStaticField_value] @ field<- vAA 12172 cmp r1, #0 @ stored a null object? 12173 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 12174 GOTO_OPCODE(ip) @ jump to next instruction 12175 12176/* continuation for OP_CONST_CLASS_JUMBO */ 12177 12178 /* 12179 * Continuation if the Class has not yet been resolved. 12180 * r1: AAAAAAAA (Class ref) 12181 * r9: target register 12182 */ 12183.LOP_CONST_CLASS_JUMBO_resolve: 12184 EXPORT_PC() 12185 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 12186 mov r2, #1 @ r2<- true 12187 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 12188 bl dvmResolveClass @ r0<- Class reference 12189 cmp r0, #0 @ failed? 12190 beq common_exceptionThrown @ yup, handle the exception 12191 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 12192 GET_INST_OPCODE(ip) @ extract opcode from rINST 12193 SET_VREG(r0, r9) @ vBBBB<- r0 12194 GOTO_OPCODE(ip) @ jump to next instruction 12195 12196/* continuation for OP_CHECK_CAST_JUMBO */ 12197 12198 /* 12199 * Trivial test failed, need to perform full check. This is common. 12200 * r0 holds obj->clazz 12201 * r1 holds desired class resolved from AAAAAAAA 12202 * r9 holds object 12203 */ 12204.LOP_CHECK_CAST_JUMBO_fullcheck: 12205 mov r10, r1 @ avoid ClassObject getting clobbered 12206 bl dvmInstanceofNonTrivial @ r0<- boolean result 12207 cmp r0, #0 @ failed? 12208 bne .LOP_CHECK_CAST_JUMBO_okay @ no, success 12209 12210 @ A cast has failed. We need to throw a ClassCastException. 12211 EXPORT_PC() @ about to throw 12212 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz (actual class) 12213 mov r1, r10 @ r1<- desired class 12214 bl dvmThrowClassCastException 12215 b common_exceptionThrown 12216 12217 /* 12218 * Advance PC and get the next opcode. 12219 */ 12220.LOP_CHECK_CAST_JUMBO_okay: 12221 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 12222 GET_INST_OPCODE(ip) @ extract opcode from rINST 12223 GOTO_OPCODE(ip) @ jump to next instruction 12224 12225 /* 12226 * Resolution required. This is the least-likely path. 12227 * 12228 * r2 holds AAAAAAAA 12229 * r9 holds object 12230 */ 12231.LOP_CHECK_CAST_JUMBO_resolve: 12232 EXPORT_PC() @ resolve() could throw 12233 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 12234 mov r1, r2 @ r1<- AAAAAAAA 12235 mov r2, #0 @ r2<- false 12236 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 12237 bl dvmResolveClass @ r0<- resolved ClassObject ptr 12238 cmp r0, #0 @ got null? 12239 beq common_exceptionThrown @ yes, handle exception 12240 mov r1, r0 @ r1<- class resolved from AAAAAAAA 12241 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 12242 b .LOP_CHECK_CAST_JUMBO_resolved @ pick up where we left off 12243 12244/* continuation for OP_INSTANCE_OF_JUMBO */ 12245 12246 /* 12247 * Class resolved, determine type of check necessary. This is common. 12248 * r0 holds obj->clazz 12249 * r1 holds class resolved from AAAAAAAA 12250 * r9 holds BBBB 12251 */ 12252.LOP_INSTANCE_OF_JUMBO_resolved: 12253 cmp r0, r1 @ same class (trivial success)? 12254 beq .LOP_INSTANCE_OF_JUMBO_trivial @ yes, trivial finish 12255 @ fall through to OP_INSTANCE_OF_JUMBO_fullcheck 12256 12257 /* 12258 * Trivial test failed, need to perform full check. This is common. 12259 * r0 holds obj->clazz 12260 * r1 holds class resolved from AAAAAAAA 12261 * r9 holds BBBB 12262 */ 12263.LOP_INSTANCE_OF_JUMBO_fullcheck: 12264 bl dvmInstanceofNonTrivial @ r0<- boolean result 12265 @ fall through to OP_INSTANCE_OF_JUMBO_store 12266 12267 /* 12268 * r0 holds boolean result 12269 * r9 holds BBBB 12270 */ 12271.LOP_INSTANCE_OF_JUMBO_store: 12272 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12273 SET_VREG(r0, r9) @ vBBBB<- r0 12274 GET_INST_OPCODE(ip) @ extract opcode from rINST 12275 GOTO_OPCODE(ip) @ jump to next instruction 12276 12277 /* 12278 * Trivial test succeeded, save and bail. 12279 * r9 holds BBBB 12280 */ 12281.LOP_INSTANCE_OF_JUMBO_trivial: 12282 mov r0, #1 @ indicate success 12283 @ could b OP_INSTANCE_OF_JUMBO_store, but copying is faster and cheaper 12284 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12285 SET_VREG(r0, r9) @ vBBBB<- r0 12286 GET_INST_OPCODE(ip) @ extract opcode from rINST 12287 GOTO_OPCODE(ip) @ jump to next instruction 12288 12289 /* 12290 * Resolution required. This is the least-likely path. 12291 * 12292 * r3 holds AAAAAAAA 12293 * r9 holds BBBB 12294 */ 12295 12296.LOP_INSTANCE_OF_JUMBO_resolve: 12297 EXPORT_PC() @ resolve() could throw 12298 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 12299 mov r1, r3 @ r1<- AAAAAAAA 12300 mov r2, #1 @ r2<- true 12301 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 12302 bl dvmResolveClass @ r0<- resolved ClassObject ptr 12303 cmp r0, #0 @ got null? 12304 beq common_exceptionThrown @ yes, handle exception 12305 FETCH(r3, 4) @ r3<- vCCCC 12306 mov r1, r0 @ r1<- class resolved from AAAAAAAA 12307 GET_VREG(r0, r3) @ r0<- vCCCC (object) 12308 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 12309 b .LOP_INSTANCE_OF_JUMBO_resolved @ pick up where we left off 12310 12311/* continuation for OP_NEW_INSTANCE_JUMBO */ 12312 12313 .balign 32 @ minimize cache lines 12314.LOP_NEW_INSTANCE_JUMBO_finish: @ r0=new object 12315 FETCH(r3, 3) @ r3<- BBBB 12316 cmp r0, #0 @ failed? 12317 beq common_exceptionThrown @ yes, handle the exception 12318 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 12319 GET_INST_OPCODE(ip) @ extract opcode from rINST 12320 SET_VREG(r0, r3) @ vBBBB<- r0 12321 GOTO_OPCODE(ip) @ jump to next instruction 12322 12323 /* 12324 * Class initialization required. 12325 * 12326 * r0 holds class object 12327 */ 12328.LOP_NEW_INSTANCE_JUMBO_needinit: 12329 mov r9, r0 @ save r0 12330 bl dvmInitClass @ initialize class 12331 cmp r0, #0 @ check boolean result 12332 mov r0, r9 @ restore r0 12333 bne .LOP_NEW_INSTANCE_JUMBO_initialized @ success, continue 12334 b common_exceptionThrown @ failed, deal with init exception 12335 12336 /* 12337 * Resolution required. This is the least-likely path. 12338 * 12339 * r1 holds AAAAAAAA 12340 */ 12341.LOP_NEW_INSTANCE_JUMBO_resolve: 12342 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 12343 mov r2, #0 @ r2<- false 12344 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 12345 bl dvmResolveClass @ r0<- resolved ClassObject ptr 12346 cmp r0, #0 @ got null? 12347 bne .LOP_NEW_INSTANCE_JUMBO_resolved @ no, continue 12348 b common_exceptionThrown @ yes, handle exception 12349 12350/* continuation for OP_NEW_ARRAY_JUMBO */ 12351 12352 12353 /* 12354 * Resolve class. (This is an uncommon case.) 12355 * 12356 * r1 holds array length 12357 * r2 holds class ref AAAAAAAA 12358 */ 12359.LOP_NEW_ARRAY_JUMBO_resolve: 12360 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 12361 mov r9, r1 @ r9<- length (save) 12362 mov r1, r2 @ r1<- AAAAAAAA 12363 mov r2, #0 @ r2<- false 12364 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 12365 bl dvmResolveClass @ r0<- call(clazz, ref) 12366 cmp r0, #0 @ got null? 12367 mov r1, r9 @ r1<- length (restore) 12368 beq common_exceptionThrown @ yes, handle exception 12369 @ fall through to OP_NEW_ARRAY_JUMBO_finish 12370 12371 /* 12372 * Finish allocation. 12373 * 12374 * r0 holds class 12375 * r1 holds array length 12376 */ 12377.LOP_NEW_ARRAY_JUMBO_finish: 12378 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 12379 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 12380 cmp r0, #0 @ failed? 12381 FETCH(r2, 3) @ r2<- vBBBB 12382 beq common_exceptionThrown @ yes, handle the exception 12383 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12384 GET_INST_OPCODE(ip) @ extract opcode from rINST 12385 SET_VREG(r0, r2) @ vBBBB<- r0 12386 GOTO_OPCODE(ip) @ jump to next instruction 12387 12388/* continuation for OP_FILLED_NEW_ARRAY_JUMBO */ 12389 12390 /* 12391 * On entry: 12392 * r0 holds array class 12393 */ 12394.LOP_FILLED_NEW_ARRAY_JUMBO_continue: 12395 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 12396 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 12397 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 12398 FETCH(r1, 3) @ r1<- BBBB (length) 12399 cmp rINST, #'I' @ array of ints? 12400 cmpne rINST, #'L' @ array of objects? 12401 cmpne rINST, #'[' @ array of arrays? 12402 mov r9, r1 @ save length in r9 12403 bne .LOP_FILLED_NEW_ARRAY_JUMBO_notimpl @ no, not handled yet 12404 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 12405 cmp r0, #0 @ null return? 12406 beq common_exceptionThrown @ alloc failed, handle exception 12407 12408 FETCH(r1, 4) @ r1<- CCCC 12409 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 12410 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 12411 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 12412 subs r9, r9, #1 @ length--, check for neg 12413 FETCH_ADVANCE_INST(5) @ advance to next instr, load rINST 12414 bmi 2f @ was zero, bail 12415 12416 @ copy values from registers into the array 12417 @ r0=array, r1=CCCC, r9=BBBB (length) 12418 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 124191: ldr r3, [r2], #4 @ r3<- *r2++ 12420 subs r9, r9, #1 @ count-- 12421 str r3, [r0], #4 @ *contents++ = vX 12422 bpl 1b 12423 124242: ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 12425 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 12426 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 12427 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 12428 cmp r1, #'I' @ Is int array? 12429 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 12430 GOTO_OPCODE(ip) @ execute it 12431 12432 /* 12433 * Throw an exception indicating that we have not implemented this 12434 * mode of filled-new-array. 12435 */ 12436.LOP_FILLED_NEW_ARRAY_JUMBO_notimpl: 12437 ldr r0, .L_strInternalError 12438 ldr r1, .L_strFilledNewArrayNotImpl 12439 bl dvmThrowException 12440 b common_exceptionThrown 12441 12442/* continuation for OP_IGET_JUMBO */ 12443 12444 /* 12445 * Currently: 12446 * r0 holds resolved field 12447 * r9 holds object 12448 */ 12449.LOP_IGET_JUMBO_resolved: 12450 cmp r0, #0 @ resolution unsuccessful? 12451 beq common_exceptionThrown @ yes, throw exception 12452 @ fall through to OP_IGET_JUMBO_finish 12453 12454 /* 12455 * Currently: 12456 * r0 holds resolved field 12457 * r9 holds object 12458 */ 12459.LOP_IGET_JUMBO_finish: 12460 @bl common_squeak0 12461 cmp r9, #0 @ check object for null 12462 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12463 beq common_errNullObject @ object was null 12464 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 12465 @ no-op @ acquiring load 12466 FETCH(r2, 3) @ r2<- BBBB 12467 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12468 SET_VREG(r0, r2) @ fp[BBBB]<- r0 12469 GET_INST_OPCODE(ip) @ extract opcode from rINST 12470 GOTO_OPCODE(ip) @ jump to next instruction 12471 12472/* continuation for OP_IGET_WIDE_JUMBO */ 12473 12474 /* 12475 * Currently: 12476 * r0 holds resolved field 12477 * r9 holds object 12478 */ 12479.LOP_IGET_WIDE_JUMBO_resolved: 12480 cmp r0, #0 @ resolution unsuccessful? 12481 beq common_exceptionThrown @ yes, throw exception 12482 @ fall through to OP_IGET_WIDE_JUMBO_finish 12483 12484 /* 12485 * Currently: 12486 * r0 holds resolved field 12487 * r9 holds object 12488 */ 12489.LOP_IGET_WIDE_JUMBO_finish: 12490 cmp r9, #0 @ check object for null 12491 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12492 beq common_errNullObject @ object was null 12493 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 12494 FETCH(r2, 3) @ r2<- BBBB 12495 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12496 add r3, rFP, r2, lsl #2 @ r3<- &fp[BBBB] 12497 GET_INST_OPCODE(ip) @ extract opcode from rINST 12498 stmia r3, {r0-r1} @ fp[BBBB]<- r0/r1 12499 GOTO_OPCODE(ip) @ jump to next instruction 12500 12501/* continuation for OP_IGET_OBJECT_JUMBO */ 12502 12503 /* 12504 * Currently: 12505 * r0 holds resolved field 12506 * r9 holds object 12507 */ 12508.LOP_IGET_OBJECT_JUMBO_resolved: 12509 cmp r0, #0 @ resolution unsuccessful? 12510 beq common_exceptionThrown @ yes, throw exception 12511 @ fall through to OP_IGET_OBJECT_JUMBO_finish 12512 12513 /* 12514 * Currently: 12515 * r0 holds resolved field 12516 * r9 holds object 12517 */ 12518.LOP_IGET_OBJECT_JUMBO_finish: 12519 @bl common_squeak0 12520 cmp r9, #0 @ check object for null 12521 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12522 beq common_errNullObject @ object was null 12523 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 12524 @ no-op @ acquiring load 12525 FETCH(r2, 3) @ r2<- BBBB 12526 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12527 SET_VREG(r0, r2) @ fp[BBBB]<- r0 12528 GET_INST_OPCODE(ip) @ extract opcode from rINST 12529 GOTO_OPCODE(ip) @ jump to next instruction 12530 12531/* continuation for OP_IGET_BOOLEAN_JUMBO */ 12532 12533 /* 12534 * Currently: 12535 * r0 holds resolved field 12536 * r9 holds object 12537 */ 12538.LOP_IGET_BOOLEAN_JUMBO_resolved: 12539 cmp r0, #0 @ resolution unsuccessful? 12540 beq common_exceptionThrown @ yes, throw exception 12541 @ fall through to OP_IGET_BOOLEAN_JUMBO_finish 12542 12543 /* 12544 * Currently: 12545 * r0 holds resolved field 12546 * r9 holds object 12547 */ 12548.LOP_IGET_BOOLEAN_JUMBO_finish: 12549 @bl common_squeak1 12550 cmp r9, #0 @ check object for null 12551 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12552 beq common_errNullObject @ object was null 12553 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 12554 @ no-op @ acquiring load 12555 FETCH(r2, 3) @ r2<- BBBB 12556 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12557 SET_VREG(r0, r2) @ fp[BBBB]<- r0 12558 GET_INST_OPCODE(ip) @ extract opcode from rINST 12559 GOTO_OPCODE(ip) @ jump to next instruction 12560 12561/* continuation for OP_IGET_BYTE_JUMBO */ 12562 12563 /* 12564 * Currently: 12565 * r0 holds resolved field 12566 * r9 holds object 12567 */ 12568.LOP_IGET_BYTE_JUMBO_resolved: 12569 cmp r0, #0 @ resolution unsuccessful? 12570 beq common_exceptionThrown @ yes, throw exception 12571 @ fall through to OP_IGET_BYTE_JUMBO_finish 12572 12573 /* 12574 * Currently: 12575 * r0 holds resolved field 12576 * r9 holds object 12577 */ 12578.LOP_IGET_BYTE_JUMBO_finish: 12579 @bl common_squeak2 12580 cmp r9, #0 @ check object for null 12581 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12582 beq common_errNullObject @ object was null 12583 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 12584 @ no-op @ acquiring load 12585 FETCH(r2, 3) @ r2<- BBBB 12586 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12587 SET_VREG(r0, r2) @ fp[BBBB]<- r0 12588 GET_INST_OPCODE(ip) @ extract opcode from rINST 12589 GOTO_OPCODE(ip) @ jump to next instruction 12590 12591/* continuation for OP_IGET_CHAR_JUMBO */ 12592 12593 /* 12594 * Currently: 12595 * r0 holds resolved field 12596 * r9 holds object 12597 */ 12598.LOP_IGET_CHAR_JUMBO_resolved: 12599 cmp r0, #0 @ resolution unsuccessful? 12600 beq common_exceptionThrown @ yes, throw exception 12601 @ fall through to OP_IGET_CHAR_JUMBO_finish 12602 12603 /* 12604 * Currently: 12605 * r0 holds resolved field 12606 * r9 holds object 12607 */ 12608.LOP_IGET_CHAR_JUMBO_finish: 12609 @bl common_squeak3 12610 cmp r9, #0 @ check object for null 12611 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12612 beq common_errNullObject @ object was null 12613 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 12614 @ no-op @ acquiring load 12615 FETCH(r2, 3) @ r2<- BBBB 12616 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12617 SET_VREG(r0, r2) @ fp[BBBB]<- r0 12618 GET_INST_OPCODE(ip) @ extract opcode from rINST 12619 GOTO_OPCODE(ip) @ jump to next instruction 12620 12621/* continuation for OP_IGET_SHORT_JUMBO */ 12622 12623 /* 12624 * Currently: 12625 * r0 holds resolved field 12626 * r9 holds object 12627 */ 12628.LOP_IGET_SHORT_JUMBO_resolved: 12629 cmp r0, #0 @ resolution unsuccessful? 12630 beq common_exceptionThrown @ yes, throw exception 12631 @ fall through to OP_IGET_SHORT_JUMBO_finish 12632 12633 /* 12634 * Currently: 12635 * r0 holds resolved field 12636 * r9 holds object 12637 */ 12638.LOP_IGET_SHORT_JUMBO_finish: 12639 @bl common_squeak4 12640 cmp r9, #0 @ check object for null 12641 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12642 beq common_errNullObject @ object was null 12643 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 12644 @ no-op @ acquiring load 12645 FETCH(r2, 3) @ r2<- BBBB 12646 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12647 SET_VREG(r0, r2) @ fp[BBBB]<- r0 12648 GET_INST_OPCODE(ip) @ extract opcode from rINST 12649 GOTO_OPCODE(ip) @ jump to next instruction 12650 12651/* continuation for OP_IPUT_JUMBO */ 12652 12653 /* 12654 * Currently: 12655 * r0 holds resolved field 12656 * r9 holds object 12657 */ 12658.LOP_IPUT_JUMBO_resolved: 12659 cmp r0, #0 @ resolution unsuccessful? 12660 beq common_exceptionThrown @ yes, throw exception 12661 @ fall through to OP_IPUT_JUMBO_finish 12662 12663 /* 12664 * Currently: 12665 * r0 holds resolved field 12666 * r9 holds object 12667 */ 12668.LOP_IPUT_JUMBO_finish: 12669 @bl common_squeak0 12670 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12671 FETCH(r1, 3) @ r1<- BBBB 12672 cmp r9, #0 @ check object for null 12673 GET_VREG(r0, r1) @ r0<- fp[BBBB] 12674 beq common_errNullObject @ object was null 12675 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12676 GET_INST_OPCODE(ip) @ extract opcode from rINST 12677 @ no-op @ releasing store 12678 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 12679 GOTO_OPCODE(ip) @ jump to next instruction 12680 12681/* continuation for OP_IPUT_WIDE_JUMBO */ 12682 12683 /* 12684 * Currently: 12685 * r0 holds resolved field 12686 * r9 holds object 12687 */ 12688.LOP_IPUT_WIDE_JUMBO_resolved: 12689 cmp r0, #0 @ resolution unsuccessful? 12690 beq common_exceptionThrown @ yes, throw exception 12691 @ fall through to OP_IPUT_WIDE_JUMBO_finish 12692 12693 /* 12694 * Currently: 12695 * r0 holds resolved field 12696 * r9 holds object 12697 */ 12698.LOP_IPUT_WIDE_JUMBO_finish: 12699 cmp r9, #0 @ check object for null 12700 FETCH(r2, 3) @ r1<- BBBB 12701 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12702 add r2, rFP, r2, lsl #2 @ r3<- &fp[BBBB] 12703 beq common_errNullObject @ object was null 12704 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12705 ldmia r2, {r0-r1} @ r0/r1<- fp[BBBB] 12706 GET_INST_OPCODE(r10) @ extract opcode from rINST 12707 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 12708 GOTO_OPCODE(r10) @ jump to next instruction 12709 12710/* continuation for OP_IPUT_OBJECT_JUMBO */ 12711 12712 /* 12713 * Currently: 12714 * r0 holds resolved field 12715 * r9 holds object 12716 */ 12717.LOP_IPUT_OBJECT_JUMBO_resolved: 12718 cmp r0, #0 @ resolution unsuccessful? 12719 beq common_exceptionThrown @ yes, throw exception 12720 @ fall through to OP_IPUT_OBJECT_JUMBO_finish 12721 12722 /* 12723 * Currently: 12724 * r0 holds resolved field 12725 * r9 holds object 12726 */ 12727.LOP_IPUT_OBJECT_JUMBO_finish: 12728 @bl common_squeak0 12729 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12730 FETCH(r1, 3) @ r1<- BBBB 12731 cmp r9, #0 @ check object for null 12732 GET_VREG(r0, r1) @ r0<- fp[BBBB] 12733 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 12734 beq common_errNullObject @ object was null 12735 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12736 GET_INST_OPCODE(ip) @ extract opcode from rINST 12737 @ no-op @ releasing store 12738 str r0, [r9, r3] @ obj.field (32 bits)<- r0 12739 cmp r0, #0 @ stored a null reference? 12740 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 12741 GOTO_OPCODE(ip) @ jump to next instruction 12742 12743/* continuation for OP_IPUT_BOOLEAN_JUMBO */ 12744 12745 /* 12746 * Currently: 12747 * r0 holds resolved field 12748 * r9 holds object 12749 */ 12750.LOP_IPUT_BOOLEAN_JUMBO_resolved: 12751 cmp r0, #0 @ resolution unsuccessful? 12752 beq common_exceptionThrown @ yes, throw exception 12753 @ fall through to OP_IPUT_BOOLEAN_JUMBO_finish 12754 12755 /* 12756 * Currently: 12757 * r0 holds resolved field 12758 * r9 holds object 12759 */ 12760.LOP_IPUT_BOOLEAN_JUMBO_finish: 12761 @bl common_squeak1 12762 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12763 FETCH(r1, 3) @ r1<- BBBB 12764 cmp r9, #0 @ check object for null 12765 GET_VREG(r0, r1) @ r0<- fp[BBBB] 12766 beq common_errNullObject @ object was null 12767 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12768 GET_INST_OPCODE(ip) @ extract opcode from rINST 12769 @ no-op @ releasing store 12770 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 12771 GOTO_OPCODE(ip) @ jump to next instruction 12772 12773/* continuation for OP_IPUT_BYTE_JUMBO */ 12774 12775 /* 12776 * Currently: 12777 * r0 holds resolved field 12778 * r9 holds object 12779 */ 12780.LOP_IPUT_BYTE_JUMBO_resolved: 12781 cmp r0, #0 @ resolution unsuccessful? 12782 beq common_exceptionThrown @ yes, throw exception 12783 @ fall through to OP_IPUT_BYTE_JUMBO_finish 12784 12785 /* 12786 * Currently: 12787 * r0 holds resolved field 12788 * r9 holds object 12789 */ 12790.LOP_IPUT_BYTE_JUMBO_finish: 12791 @bl common_squeak2 12792 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12793 FETCH(r1, 3) @ r1<- BBBB 12794 cmp r9, #0 @ check object for null 12795 GET_VREG(r0, r1) @ r0<- fp[BBBB] 12796 beq common_errNullObject @ object was null 12797 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12798 GET_INST_OPCODE(ip) @ extract opcode from rINST 12799 @ no-op @ releasing store 12800 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 12801 GOTO_OPCODE(ip) @ jump to next instruction 12802 12803/* continuation for OP_IPUT_CHAR_JUMBO */ 12804 12805 /* 12806 * Currently: 12807 * r0 holds resolved field 12808 * r9 holds object 12809 */ 12810.LOP_IPUT_CHAR_JUMBO_resolved: 12811 cmp r0, #0 @ resolution unsuccessful? 12812 beq common_exceptionThrown @ yes, throw exception 12813 @ fall through to OP_IPUT_CHAR_JUMBO_finish 12814 12815 /* 12816 * Currently: 12817 * r0 holds resolved field 12818 * r9 holds object 12819 */ 12820.LOP_IPUT_CHAR_JUMBO_finish: 12821 @bl common_squeak3 12822 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12823 FETCH(r1, 3) @ r1<- BBBB 12824 cmp r9, #0 @ check object for null 12825 GET_VREG(r0, r1) @ r0<- fp[BBBB] 12826 beq common_errNullObject @ object was null 12827 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12828 GET_INST_OPCODE(ip) @ extract opcode from rINST 12829 @ no-op @ releasing store 12830 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 12831 GOTO_OPCODE(ip) @ jump to next instruction 12832 12833/* continuation for OP_IPUT_SHORT_JUMBO */ 12834 12835 /* 12836 * Currently: 12837 * r0 holds resolved field 12838 * r9 holds object 12839 */ 12840.LOP_IPUT_SHORT_JUMBO_resolved: 12841 cmp r0, #0 @ resolution unsuccessful? 12842 beq common_exceptionThrown @ yes, throw exception 12843 @ fall through to OP_IPUT_SHORT_JUMBO_finish 12844 12845 /* 12846 * Currently: 12847 * r0 holds resolved field 12848 * r9 holds object 12849 */ 12850.LOP_IPUT_SHORT_JUMBO_finish: 12851 @bl common_squeak4 12852 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12853 FETCH(r1, 3) @ r1<- BBBB 12854 cmp r9, #0 @ check object for null 12855 GET_VREG(r0, r1) @ r0<- fp[BBBB] 12856 beq common_errNullObject @ object was null 12857 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12858 GET_INST_OPCODE(ip) @ extract opcode from rINST 12859 @ no-op @ releasing store 12860 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 12861 GOTO_OPCODE(ip) @ jump to next instruction 12862 12863/* continuation for OP_SGET_JUMBO */ 12864 12865 /* 12866 * Continuation if the field has not yet been resolved. 12867 * r1: AAAAAAAA field ref 12868 */ 12869.LOP_SGET_JUMBO_resolve: 12870 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12871 EXPORT_PC() @ resolve() could throw, so export now 12872 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12873 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12874 cmp r0, #0 @ success? 12875 bne .LOP_SGET_JUMBO_finish @ yes, finish 12876 b common_exceptionThrown @ no, handle exception 12877 12878/* continuation for OP_SGET_WIDE_JUMBO */ 12879 12880 /* 12881 * Continuation if the field has not yet been resolved. 12882 * r1: BBBB field ref 12883 * 12884 * Returns StaticField pointer in r0. 12885 */ 12886.LOP_SGET_WIDE_JUMBO_resolve: 12887 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12888 EXPORT_PC() @ resolve() could throw, so export now 12889 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12890 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12891 cmp r0, #0 @ success? 12892 bne .LOP_SGET_WIDE_JUMBO_finish @ yes, finish 12893 b common_exceptionThrown @ no, handle exception 12894 12895/* continuation for OP_SGET_OBJECT_JUMBO */ 12896 12897 /* 12898 * Continuation if the field has not yet been resolved. 12899 * r1: AAAAAAAA field ref 12900 */ 12901.LOP_SGET_OBJECT_JUMBO_resolve: 12902 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12903 EXPORT_PC() @ resolve() could throw, so export now 12904 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12905 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12906 cmp r0, #0 @ success? 12907 bne .LOP_SGET_OBJECT_JUMBO_finish @ yes, finish 12908 b common_exceptionThrown @ no, handle exception 12909 12910/* continuation for OP_SGET_BOOLEAN_JUMBO */ 12911 12912 /* 12913 * Continuation if the field has not yet been resolved. 12914 * r1: AAAAAAAA field ref 12915 */ 12916.LOP_SGET_BOOLEAN_JUMBO_resolve: 12917 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12918 EXPORT_PC() @ resolve() could throw, so export now 12919 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12920 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12921 cmp r0, #0 @ success? 12922 bne .LOP_SGET_BOOLEAN_JUMBO_finish @ yes, finish 12923 b common_exceptionThrown @ no, handle exception 12924 12925/* continuation for OP_SGET_BYTE_JUMBO */ 12926 12927 /* 12928 * Continuation if the field has not yet been resolved. 12929 * r1: AAAAAAAA field ref 12930 */ 12931.LOP_SGET_BYTE_JUMBO_resolve: 12932 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12933 EXPORT_PC() @ resolve() could throw, so export now 12934 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12935 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12936 cmp r0, #0 @ success? 12937 bne .LOP_SGET_BYTE_JUMBO_finish @ yes, finish 12938 b common_exceptionThrown @ no, handle exception 12939 12940/* continuation for OP_SGET_CHAR_JUMBO */ 12941 12942 /* 12943 * Continuation if the field has not yet been resolved. 12944 * r1: AAAAAAAA field ref 12945 */ 12946.LOP_SGET_CHAR_JUMBO_resolve: 12947 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12948 EXPORT_PC() @ resolve() could throw, so export now 12949 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12950 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12951 cmp r0, #0 @ success? 12952 bne .LOP_SGET_CHAR_JUMBO_finish @ yes, finish 12953 b common_exceptionThrown @ no, handle exception 12954 12955/* continuation for OP_SGET_SHORT_JUMBO */ 12956 12957 /* 12958 * Continuation if the field has not yet been resolved. 12959 * r1: AAAAAAAA field ref 12960 */ 12961.LOP_SGET_SHORT_JUMBO_resolve: 12962 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12963 EXPORT_PC() @ resolve() could throw, so export now 12964 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12965 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12966 cmp r0, #0 @ success? 12967 bne .LOP_SGET_SHORT_JUMBO_finish @ yes, finish 12968 b common_exceptionThrown @ no, handle exception 12969 12970/* continuation for OP_SPUT_JUMBO */ 12971 12972 /* 12973 * Continuation if the field has not yet been resolved. 12974 * r1: AAAAAAAA field ref 12975 */ 12976.LOP_SPUT_JUMBO_resolve: 12977 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12978 EXPORT_PC() @ resolve() could throw, so export now 12979 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12980 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12981 cmp r0, #0 @ success? 12982 bne .LOP_SPUT_JUMBO_finish @ yes, finish 12983 b common_exceptionThrown @ no, handle exception 12984 12985/* continuation for OP_SPUT_WIDE_JUMBO */ 12986 12987 /* 12988 * Continuation if the field has not yet been resolved. 12989 * r1: BBBB field ref 12990 * r9: &fp[AA] 12991 * 12992 * Returns StaticField pointer in r2. 12993 */ 12994.LOP_SPUT_WIDE_JUMBO_resolve: 12995 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12996 EXPORT_PC() @ resolve() could throw, so export now 12997 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12998 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12999 cmp r0, #0 @ success? 13000 mov r2, r0 @ copy to r2 13001 bne .LOP_SPUT_WIDE_JUMBO_finish @ yes, finish 13002 b common_exceptionThrown @ no, handle exception 13003 13004/* continuation for OP_SPUT_OBJECT_JUMBO */ 13005 13006.LOP_SPUT_OBJECT_JUMBO_finish: @ field ptr in r0 13007 FETCH(r2, 3) @ r2<- BBBB 13008 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 13009 GET_VREG(r1, r2) @ r1<- fp[BBBB] 13010 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 13011 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz 13012 GET_INST_OPCODE(ip) @ extract opcode from rINST 13013 @ no-op @ releasing store 13014 str r1, [r0, #offStaticField_value] @ field<- vBBBB 13015 cmp r1, #0 @ stored a null object? 13016 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 13017 GOTO_OPCODE(ip) @ jump to next instruction 13018 13019/* continuation for OP_SPUT_BOOLEAN_JUMBO */ 13020 13021 /* 13022 * Continuation if the field has not yet been resolved. 13023 * r1: AAAAAAAA field ref 13024 */ 13025.LOP_SPUT_BOOLEAN_JUMBO_resolve: 13026 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 13027 EXPORT_PC() @ resolve() could throw, so export now 13028 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 13029 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 13030 cmp r0, #0 @ success? 13031 bne .LOP_SPUT_BOOLEAN_JUMBO_finish @ yes, finish 13032 b common_exceptionThrown @ no, handle exception 13033 13034/* continuation for OP_SPUT_BYTE_JUMBO */ 13035 13036 /* 13037 * Continuation if the field has not yet been resolved. 13038 * r1: AAAAAAAA field ref 13039 */ 13040.LOP_SPUT_BYTE_JUMBO_resolve: 13041 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 13042 EXPORT_PC() @ resolve() could throw, so export now 13043 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 13044 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 13045 cmp r0, #0 @ success? 13046 bne .LOP_SPUT_BYTE_JUMBO_finish @ yes, finish 13047 b common_exceptionThrown @ no, handle exception 13048 13049/* continuation for OP_SPUT_CHAR_JUMBO */ 13050 13051 /* 13052 * Continuation if the field has not yet been resolved. 13053 * r1: AAAAAAAA field ref 13054 */ 13055.LOP_SPUT_CHAR_JUMBO_resolve: 13056 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 13057 EXPORT_PC() @ resolve() could throw, so export now 13058 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 13059 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 13060 cmp r0, #0 @ success? 13061 bne .LOP_SPUT_CHAR_JUMBO_finish @ yes, finish 13062 b common_exceptionThrown @ no, handle exception 13063 13064/* continuation for OP_SPUT_SHORT_JUMBO */ 13065 13066 /* 13067 * Continuation if the field has not yet been resolved. 13068 * r1: AAAAAAAA field ref 13069 */ 13070.LOP_SPUT_SHORT_JUMBO_resolve: 13071 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 13072 EXPORT_PC() @ resolve() could throw, so export now 13073 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 13074 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 13075 cmp r0, #0 @ success? 13076 bne .LOP_SPUT_SHORT_JUMBO_finish @ yes, finish 13077 b common_exceptionThrown @ no, handle exception 13078 13079/* continuation for OP_INVOKE_VIRTUAL_JUMBO */ 13080 13081 /* 13082 * At this point: 13083 * r0 = resolved base method 13084 */ 13085.LOP_INVOKE_VIRTUAL_JUMBO_continue: 13086 FETCH(r10, 4) @ r10<- CCCC 13087 GET_VREG(r1, r10) @ r1<- "this" ptr 13088 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 13089 cmp r1, #0 @ is "this" null? 13090 beq common_errNullObject @ null "this", throw exception 13091 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 13092 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 13093 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 13094 bl common_invokeMethodJumbo @ continue on 13095 13096/* continuation for OP_INVOKE_SUPER_JUMBO */ 13097 13098 /* 13099 * At this point: 13100 * r0 = resolved base method 13101 * r9 = method->clazz 13102 */ 13103.LOP_INVOKE_SUPER_JUMBO_continue: 13104 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 13105 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 13106 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 13107 EXPORT_PC() @ must export for invoke 13108 cmp r2, r3 @ compare (methodIndex, vtableCount) 13109 bcs .LOP_INVOKE_SUPER_JUMBO_nsm @ method not present in superclass 13110 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 13111 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 13112 bl common_invokeMethodJumbo @ continue on 13113 13114.LOP_INVOKE_SUPER_JUMBO_resolve: 13115 mov r0, r9 @ r0<- method->clazz 13116 mov r2, #METHOD_VIRTUAL @ resolver method type 13117 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 13118 cmp r0, #0 @ got null? 13119 bne .LOP_INVOKE_SUPER_JUMBO_continue @ no, continue 13120 b common_exceptionThrown @ yes, handle exception 13121 13122 /* 13123 * Throw a NoSuchMethodError with the method name as the message. 13124 * r0 = resolved base method 13125 */ 13126.LOP_INVOKE_SUPER_JUMBO_nsm: 13127 ldr r1, [r0, #offMethod_name] @ r1<- method name 13128 b common_errNoSuchMethod 13129 13130/* continuation for OP_INVOKE_DIRECT_JUMBO */ 13131 13132 /* 13133 * On entry: 13134 * r1 = reference (CCCC) 13135 * r10 = "this" register 13136 */ 13137.LOP_INVOKE_DIRECT_JUMBO_resolve: 13138 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 13139 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 13140 mov r2, #METHOD_DIRECT @ resolver method type 13141 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 13142 cmp r0, #0 @ got null? 13143 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 13144 bne .LOP_INVOKE_DIRECT_JUMBO_finish @ no, continue 13145 b common_exceptionThrown @ yes, handle exception 13146 13147 .size dvmAsmSisterStart, .-dvmAsmSisterStart 13148 .global dvmAsmSisterEnd 13149dvmAsmSisterEnd: 13150 13151/* File: armv5te/footer.S */ 13152 13153/* 13154 * =========================================================================== 13155 * Common subroutines and data 13156 * =========================================================================== 13157 */ 13158 13159 13160 13161 .text 13162 .align 2 13163 13164#if defined(WITH_JIT) 13165#if defined(WITH_SELF_VERIFICATION) 13166 .global dvmJitToInterpPunt 13167dvmJitToInterpPunt: 13168 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13169 mov r2,#kSVSPunt @ r2<- interpreter entry point 13170 mov r3, #0 13171 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 13172 b jitSVShadowRunEnd @ doesn't return 13173 13174 .global dvmJitToInterpSingleStep 13175dvmJitToInterpSingleStep: 13176 str lr,[rGLUE,#offGlue_jitResumeNPC] 13177 str r1,[rGLUE,#offGlue_jitResumeDPC] 13178 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 13179 b jitSVShadowRunEnd @ doesn't return 13180 13181 .global dvmJitToInterpNoChainNoProfile 13182dvmJitToInterpNoChainNoProfile: 13183 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13184 mov r0,rPC @ pass our target PC 13185 mov r2,#kSVSNoProfile @ r2<- interpreter entry point 13186 mov r3, #0 @ 0 means !inJitCodeCache 13187 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land 13188 b jitSVShadowRunEnd @ doesn't return 13189 13190 .global dvmJitToInterpTraceSelectNoChain 13191dvmJitToInterpTraceSelectNoChain: 13192 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13193 mov r0,rPC @ pass our target PC 13194 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 13195 mov r3, #0 @ 0 means !inJitCodeCache 13196 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 13197 b jitSVShadowRunEnd @ doesn't return 13198 13199 .global dvmJitToInterpTraceSelect 13200dvmJitToInterpTraceSelect: 13201 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13202 ldr r0,[lr, #-1] @ pass our target PC 13203 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 13204 mov r3, #0 @ 0 means !inJitCodeCache 13205 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 13206 b jitSVShadowRunEnd @ doesn't return 13207 13208 .global dvmJitToInterpBackwardBranch 13209dvmJitToInterpBackwardBranch: 13210 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13211 ldr r0,[lr, #-1] @ pass our target PC 13212 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 13213 mov r3, #0 @ 0 means !inJitCodeCache 13214 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 13215 b jitSVShadowRunEnd @ doesn't return 13216 13217 .global dvmJitToInterpNormal 13218dvmJitToInterpNormal: 13219 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13220 ldr r0,[lr, #-1] @ pass our target PC 13221 mov r2,#kSVSNormal @ r2<- interpreter entry point 13222 mov r3, #0 @ 0 means !inJitCodeCache 13223 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 13224 b jitSVShadowRunEnd @ doesn't return 13225 13226 .global dvmJitToInterpNoChain 13227dvmJitToInterpNoChain: 13228 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13229 mov r0,rPC @ pass our target PC 13230 mov r2,#kSVSNoChain @ r2<- interpreter entry point 13231 mov r3, #0 @ 0 means !inJitCodeCache 13232 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 13233 b jitSVShadowRunEnd @ doesn't return 13234#else 13235/* 13236 * Return from the translation cache to the interpreter when the compiler is 13237 * having issues translating/executing a Dalvik instruction. We have to skip 13238 * the code cache lookup otherwise it is possible to indefinitely bouce 13239 * between the interpreter and the code cache if the instruction that fails 13240 * to be compiled happens to be at a trace start. 13241 */ 13242 .global dvmJitToInterpPunt 13243dvmJitToInterpPunt: 13244 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13245 mov rPC, r0 13246#if defined(WITH_JIT_TUNING) 13247 mov r0,lr 13248 bl dvmBumpPunt; 13249#endif 13250 EXPORT_PC() 13251 mov r0, #0 13252 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land 13253 adrl rIBASE, dvmAsmInstructionStart 13254 FETCH_INST() 13255 GET_INST_OPCODE(ip) 13256 GOTO_OPCODE(ip) 13257 13258/* 13259 * Return to the interpreter to handle a single instruction. 13260 * On entry: 13261 * r0 <= PC 13262 * r1 <= PC of resume instruction 13263 * lr <= resume point in translation 13264 */ 13265 .global dvmJitToInterpSingleStep 13266dvmJitToInterpSingleStep: 13267 str lr,[rGLUE,#offGlue_jitResumeNPC] 13268 str r1,[rGLUE,#offGlue_jitResumeDPC] 13269 mov r1,#kInterpEntryInstr 13270 @ enum is 4 byte in aapcs-EABI 13271 str r1, [rGLUE, #offGlue_entryPoint] 13272 mov rPC,r0 13273 EXPORT_PC() 13274 13275 adrl rIBASE, dvmAsmInstructionStart 13276 mov r2,#kJitSingleStep @ Ask for single step and then revert 13277 str r2,[rGLUE,#offGlue_jitState] 13278 mov r1,#1 @ set changeInterp to bail to debug interp 13279 b common_gotoBail 13280 13281/* 13282 * Return from the translation cache and immediately request 13283 * a translation for the exit target. Commonly used for callees. 13284 */ 13285 .global dvmJitToInterpTraceSelectNoChain 13286dvmJitToInterpTraceSelectNoChain: 13287#if defined(WITH_JIT_TUNING) 13288 bl dvmBumpNoChain 13289#endif 13290 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13291 mov r0,rPC 13292 bl dvmJitGetTraceAddr @ Is there a translation? 13293 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 13294 mov r1, rPC @ arg1 of translation may need this 13295 mov lr, #0 @ in case target is HANDLER_INTERPRET 13296 cmp r0,#0 @ !0 means translation exists 13297 bxne r0 @ continue native execution if so 13298 b 2f @ branch over to use the interpreter 13299 13300/* 13301 * Return from the translation cache and immediately request 13302 * a translation for the exit target. Commonly used following 13303 * invokes. 13304 */ 13305 .global dvmJitToInterpTraceSelect 13306dvmJitToInterpTraceSelect: 13307 ldr rPC,[lr, #-1] @ get our target PC 13308 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13309 add rINST,lr,#-5 @ save start of chain branch 13310 add rINST, #-4 @ .. which is 9 bytes back 13311 mov r0,rPC 13312 bl dvmJitGetTraceAddr @ Is there a translation? 13313 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 13314 cmp r0,#0 13315 beq 2f 13316 mov r1,rINST 13317 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 13318 mov r1, rPC @ arg1 of translation may need this 13319 mov lr, #0 @ in case target is HANDLER_INTERPRET 13320 cmp r0,#0 @ successful chain? 13321 bxne r0 @ continue native execution 13322 b toInterpreter @ didn't chain - resume with interpreter 13323 13324/* No translation, so request one if profiling isn't disabled*/ 133252: 13326 adrl rIBASE, dvmAsmInstructionStart 13327 GET_JIT_PROF_TABLE(r0) 13328 FETCH_INST() 13329 cmp r0, #0 13330 movne r2,#kJitTSelectRequestHot @ ask for trace selection 13331 bne common_selectTrace 13332 GET_INST_OPCODE(ip) 13333 GOTO_OPCODE(ip) 13334 13335/* 13336 * Return from the translation cache to the interpreter. 13337 * The return was done with a BLX from thumb mode, and 13338 * the following 32-bit word contains the target rPC value. 13339 * Note that lr (r14) will have its low-order bit set to denote 13340 * its thumb-mode origin. 13341 * 13342 * We'll need to stash our lr origin away, recover the new 13343 * target and then check to see if there is a translation available 13344 * for our new target. If so, we do a translation chain and 13345 * go back to native execution. Otherwise, it's back to the 13346 * interpreter (after treating this entry as a potential 13347 * trace start). 13348 */ 13349 .global dvmJitToInterpNormal 13350dvmJitToInterpNormal: 13351 ldr rPC,[lr, #-1] @ get our target PC 13352 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13353 add rINST,lr,#-5 @ save start of chain branch 13354 add rINST,#-4 @ .. which is 9 bytes back 13355#if defined(WITH_JIT_TUNING) 13356 bl dvmBumpNormal 13357#endif 13358 mov r0,rPC 13359 bl dvmJitGetTraceAddr @ Is there a translation? 13360 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 13361 cmp r0,#0 13362 beq toInterpreter @ go if not, otherwise do chain 13363 mov r1,rINST 13364 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 13365 mov r1, rPC @ arg1 of translation may need this 13366 mov lr, #0 @ in case target is HANDLER_INTERPRET 13367 cmp r0,#0 @ successful chain? 13368 bxne r0 @ continue native execution 13369 b toInterpreter @ didn't chain - resume with interpreter 13370 13371/* 13372 * Return from the translation cache to the interpreter to do method invocation. 13373 * Check if translation exists for the callee, but don't chain to it. 13374 */ 13375 .global dvmJitToInterpNoChainNoProfile 13376dvmJitToInterpNoChainNoProfile: 13377#if defined(WITH_JIT_TUNING) 13378 bl dvmBumpNoChain 13379#endif 13380 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13381 mov r0,rPC 13382 bl dvmJitGetTraceAddr @ Is there a translation? 13383 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 13384 mov r1, rPC @ arg1 of translation may need this 13385 mov lr, #0 @ in case target is HANDLER_INTERPRET 13386 cmp r0,#0 13387 bxne r0 @ continue native execution if so 13388 EXPORT_PC() 13389 adrl rIBASE, dvmAsmInstructionStart 13390 FETCH_INST() 13391 GET_INST_OPCODE(ip) @ extract opcode from rINST 13392 GOTO_OPCODE(ip) @ jump to next instruction 13393 13394/* 13395 * Return from the translation cache to the interpreter to do method invocation. 13396 * Check if translation exists for the callee, but don't chain to it. 13397 */ 13398 .global dvmJitToInterpNoChain 13399dvmJitToInterpNoChain: 13400#if defined(WITH_JIT_TUNING) 13401 bl dvmBumpNoChain 13402#endif 13403 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13404 mov r0,rPC 13405 bl dvmJitGetTraceAddr @ Is there a translation? 13406 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 13407 mov r1, rPC @ arg1 of translation may need this 13408 mov lr, #0 @ in case target is HANDLER_INTERPRET 13409 cmp r0,#0 13410 bxne r0 @ continue native execution if so 13411#endif 13412 13413/* 13414 * No translation, restore interpreter regs and start interpreting. 13415 * rGLUE & rFP were preserved in the translated code, and rPC has 13416 * already been restored by the time we get here. We'll need to set 13417 * up rIBASE & rINST, and load the address of the JitTable into r0. 13418 */ 13419toInterpreter: 13420 EXPORT_PC() 13421 adrl rIBASE, dvmAsmInstructionStart 13422 FETCH_INST() 13423 GET_JIT_PROF_TABLE(r0) 13424 @ NOTE: intended fallthrough 13425 13426/* 13427 * Common code to update potential trace start counter, and initiate 13428 * a trace-build if appropriate. On entry, rPC should point to the 13429 * next instruction to execute, and rINST should be already loaded with 13430 * the next opcode word, and r0 holds a pointer to the jit profile 13431 * table (pJitProfTable). 13432 */ 13433common_testUpdateProfile: 13434 cmp r0,#0 13435 GET_INST_OPCODE(ip) 13436 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 13437 13438common_updateProfile: 13439 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 13440 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits 13441 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter 13442 GET_INST_OPCODE(ip) 13443 subs r1,r1,#1 @ decrement counter 13444 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it 13445 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 13446 13447/* 13448 * Here, we switch to the debug interpreter to request 13449 * trace selection. First, though, check to see if there 13450 * is already a native translation in place (and, if so, 13451 * jump to it now). 13452 */ 13453 GET_JIT_THRESHOLD(r1) 13454 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13455 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter 13456 EXPORT_PC() 13457 mov r0,rPC 13458 bl dvmJitGetTraceAddr @ r0<- dvmJitGetTraceAddr(rPC) 13459 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 13460 mov r1, rPC @ arg1 of translation may need this 13461 mov lr, #0 @ in case target is HANDLER_INTERPRET 13462 cmp r0,#0 13463#if !defined(WITH_SELF_VERIFICATION) 13464 bxne r0 @ jump to the translation 13465 mov r2,#kJitTSelectRequest @ ask for trace selection 13466 @ fall-through to common_selectTrace 13467#else 13468 moveq r2,#kJitTSelectRequest @ ask for trace selection 13469 beq common_selectTrace 13470 /* 13471 * At this point, we have a target translation. However, if 13472 * that translation is actually the interpret-only pseudo-translation 13473 * we want to treat it the same as no translation. 13474 */ 13475 mov r10, r0 @ save target 13476 bl dvmCompilerGetInterpretTemplate 13477 cmp r0, r10 @ special case? 13478 bne jitSVShadowRunStart @ set up self verification shadow space 13479 @ Need to clear the inJitCodeCache flag 13480 ldr r10, [rGLUE, #offGlue_self] @ r10 <- glue->self 13481 mov r3, #0 @ 0 means not in the JIT code cache 13482 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land 13483 GET_INST_OPCODE(ip) 13484 GOTO_OPCODE(ip) 13485 /* no return */ 13486#endif 13487 13488/* 13489 * On entry: 13490 * r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot 13491 */ 13492common_selectTrace: 13493 str r2,[rGLUE,#offGlue_jitState] 13494 mov r2,#kInterpEntryInstr @ normal entry reason 13495 str r2,[rGLUE,#offGlue_entryPoint] 13496 mov r1,#1 @ set changeInterp 13497 b common_gotoBail 13498 13499#if defined(WITH_SELF_VERIFICATION) 13500/* 13501 * Save PC and registers to shadow memory for self verification mode 13502 * before jumping to native translation. 13503 * On entry: 13504 * rPC, rFP, rGLUE: the values that they should contain 13505 * r10: the address of the target translation. 13506 */ 13507jitSVShadowRunStart: 13508 mov r0,rPC @ r0<- program counter 13509 mov r1,rFP @ r1<- frame pointer 13510 mov r2,rGLUE @ r2<- InterpState pointer 13511 mov r3,r10 @ r3<- target translation 13512 bl dvmSelfVerificationSaveState @ save registers to shadow space 13513 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 13514 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 13515 bx r10 @ jump to the translation 13516 13517/* 13518 * Restore PC, registers, and interpState to original values 13519 * before jumping back to the interpreter. 13520 */ 13521jitSVShadowRunEnd: 13522 mov r1,rFP @ pass ending fp 13523 bl dvmSelfVerificationRestoreState @ restore pc and fp values 13524 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 13525 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 13526 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 13527 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 13528 cmp r1,#0 @ check for punt condition 13529 beq 1f 13530 mov r2,#kJitSelfVerification @ ask for self verification 13531 str r2,[rGLUE,#offGlue_jitState] 13532 mov r2,#kInterpEntryInstr @ normal entry reason 13533 str r2,[rGLUE,#offGlue_entryPoint] 13534 mov r1,#1 @ set changeInterp 13535 b common_gotoBail 13536 135371: @ exit to interpreter without check 13538 EXPORT_PC() 13539 adrl rIBASE, dvmAsmInstructionStart 13540 FETCH_INST() 13541 GET_INST_OPCODE(ip) 13542 GOTO_OPCODE(ip) 13543#endif 13544 13545#endif 13546 13547/* 13548 * Common code when a backward branch is taken. 13549 * 13550 * TODO: we could avoid a branch by just setting r0 and falling through 13551 * into the common_periodicChecks code, and having a test on r0 at the 13552 * end determine if we should return to the caller or update & branch to 13553 * the next instr. 13554 * 13555 * On entry: 13556 * r9 is PC adjustment *in bytes* 13557 */ 13558common_backwardBranch: 13559 mov r0, #kInterpEntryInstr 13560 bl common_periodicChecks 13561#if defined(WITH_JIT) 13562 GET_JIT_PROF_TABLE(r0) 13563 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 13564 cmp r0,#0 13565 bne common_updateProfile 13566 GET_INST_OPCODE(ip) 13567 GOTO_OPCODE(ip) 13568#else 13569 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 13570 GET_INST_OPCODE(ip) @ extract opcode from rINST 13571 GOTO_OPCODE(ip) @ jump to next instruction 13572#endif 13573 13574 13575/* 13576 * Need to see if the thread needs to be suspended or debugger/profiler 13577 * activity has begun. If so, we suspend the thread or side-exit to 13578 * the debug interpreter as appropriate. 13579 * 13580 * The common case is no activity on any of these, so we want to figure 13581 * that out quickly. If something is up, we can then sort out what. 13582 * 13583 * We want to be fast if the VM was built without debugger or profiler 13584 * support, but we also need to recognize that the system is usually 13585 * shipped with both of these enabled. 13586 * 13587 * TODO: reduce this so we're just checking a single location. 13588 * 13589 * On entry: 13590 * r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling) 13591 * r9 is trampoline PC adjustment *in bytes* 13592 */ 13593common_periodicChecks: 13594 ldr r1, [rGLUE, #offGlue_pInterpBreak] @ r3<- &interpBreak 13595 /* speculatively load address of thread-specific suspend count */ 13596 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 13597 ldr r1, [r1] @ r1<- interpBreak 13598 /* speculatively load thread-specific suspend count */ 13599 ldr ip, [r3] @ ip<- suspendCount (int) 13600 cmp r1, #0 @ anything unusual? 13601 bxeq lr @ return if not 13602 /* 13603 * One or more interesting events have happened. Figure out what. 13604 * 13605 * r0 still holds the reentry type. 13606 */ 13607 cmp ip, #0 @ want suspend? 13608 beq 3f @ no, must be something else 13609 13610 stmfd sp!, {r0, lr} @ preserve r0 and lr 13611#if defined(WITH_JIT) 13612 /* 13613 * Refresh the Jit's cached copy of profile table pointer. This pointer 13614 * doubles as the Jit's on/off switch. 13615 */ 13616 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable 13617 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 13618 ldr r3, [r3] @ r3 <- pJitProfTable 13619 EXPORT_PC() @ need for precise GC 13620 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch 13621#else 13622 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 13623 EXPORT_PC() @ need for precise GC 13624#endif 13625 bl dvmCheckSuspendPending @ do full check, suspend if necessary 13626 ldmfd sp!, {r0, lr} @ restore r0 and lr 13627 13628 /* 13629 * Reload the interpBreak flags - they may have changed while we 13630 * were suspended. 13631 */ 13632 ldr r1, [rGLUE, #offGlue_pInterpBreak] @ r1<- &interpBreak 13633 ldr r1, [r1] @ r1<- interpBreak 136343: 13635 /* 13636 * TODO: this code is too fragile. Need a general mechanism 13637 * to identify what actions to take by submode. Some profiling modes 13638 * (instruction count) need to single-step, while method tracing 13639 * may not. Debugging with breakpoints can run unfettered, but 13640 * source-level single-stepping requires Dalvik singlestepping. 13641 * GC may require a one-shot action and then full-speed resumption. 13642 */ 13643 ands r1, #(kSubModeDebuggerActive | kSubModeEmulatorTrace | kSubModeInstCounting) 13644 bxeq lr @ nothing to do, return 13645 13646 @ debugger/profiler enabled, bail out; glue->entryPoint was set above 13647 str r0, [rGLUE, #offGlue_entryPoint] @ store r0, need for debug/prof 13648 add rPC, rPC, r9 @ update rPC 13649 mov r1, #1 @ "want switch" = true 13650 b common_gotoBail @ side exit 13651 13652 13653/* 13654 * The equivalent of "goto bail", this calls through the "bail handler". 13655 * 13656 * State registers will be saved to the "glue" area before bailing. 13657 * 13658 * On entry: 13659 * r1 is "bool changeInterp", indicating if we want to switch to the 13660 * other interpreter or just bail all the way out 13661 */ 13662common_gotoBail: 13663 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 13664 mov r0, rGLUE @ r0<- glue ptr 13665 b dvmMterpStdBail @ call(glue, changeInterp) 13666 13667 @add r1, r1, #1 @ using (boolean+1) 13668 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 13669 @bl _longjmp @ does not return 13670 @bl common_abort 13671 13672 13673/* 13674 * Common code for jumbo method invocation. 13675 * NOTE: this adjusts rPC to account for the difference in instruction width. 13676 * As a result, the savedPc in the stack frame will not be wholly accurate. So 13677 * long as that is only used for source file line number calculations, we're 13678 * okay. 13679 * 13680 * On entry: 13681 * r0 is "Method* methodToCall", the method we're trying to call 13682 */ 13683common_invokeMethodJumbo: 13684.LinvokeNewJumbo: 13685 @ prepare to copy args to "outs" area of current frame 13686 add rPC, rPC, #4 @ adjust pc to make return consistent 13687 FETCH(r2, 1) @ r2<- BBBB (arg count) 13688 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 13689 cmp r2, #0 @ no args? 13690 beq .LinvokeArgsDone @ if no args, skip the rest 13691 FETCH(r1, 2) @ r1<- CCCC 13692 b .LinvokeRangeArgs @ handle args like invoke range 13693 13694/* 13695 * Common code for method invocation with range. 13696 * 13697 * On entry: 13698 * r0 is "Method* methodToCall", the method we're trying to call 13699 */ 13700common_invokeMethodRange: 13701.LinvokeNewRange: 13702 @ prepare to copy args to "outs" area of current frame 13703 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 13704 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 13705 beq .LinvokeArgsDone @ if no args, skip the rest 13706 FETCH(r1, 2) @ r1<- CCCC 13707 13708.LinvokeRangeArgs: 13709 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 13710 @ (very few methods have > 10 args; could unroll for common cases) 13711 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 13712 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 137131: ldr r1, [r3], #4 @ val = *fp++ 13714 subs r2, r2, #1 @ count-- 13715 str r1, [r10], #4 @ *outs++ = val 13716 bne 1b @ ...while count != 0 13717 b .LinvokeArgsDone 13718 13719/* 13720 * Common code for method invocation without range. 13721 * 13722 * On entry: 13723 * r0 is "Method* methodToCall", the method we're trying to call 13724 */ 13725common_invokeMethodNoRange: 13726.LinvokeNewNoRange: 13727 @ prepare to copy args to "outs" area of current frame 13728 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 13729 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 13730 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 13731 beq .LinvokeArgsDone 13732 13733 @ r0=methodToCall, r1=GFED, r2=count, r10=outs 13734.LinvokeNonRange: 13735 rsb r2, r2, #5 @ r2<- 5-r2 13736 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 13737 bl common_abort @ (skipped due to ARM prefetch) 137385: and ip, rINST, #0x0f00 @ isolate A 13739 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 13740 mov r0, r0 @ nop 13741 str r2, [r10, #-4]! @ *--outs = vA 137424: and ip, r1, #0xf000 @ isolate G 13743 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 13744 mov r0, r0 @ nop 13745 str r2, [r10, #-4]! @ *--outs = vG 137463: and ip, r1, #0x0f00 @ isolate F 13747 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 13748 mov r0, r0 @ nop 13749 str r2, [r10, #-4]! @ *--outs = vF 137502: and ip, r1, #0x00f0 @ isolate E 13751 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 13752 mov r0, r0 @ nop 13753 str r2, [r10, #-4]! @ *--outs = vE 137541: and ip, r1, #0x000f @ isolate D 13755 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 13756 mov r0, r0 @ nop 13757 str r2, [r10, #-4]! @ *--outs = vD 137580: @ fall through to .LinvokeArgsDone 13759 13760.LinvokeArgsDone: @ r0=methodToCall 13761 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 13762 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 13763 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 13764 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 13765 @ find space for the new stack frame, check for overflow 13766 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 13767 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 13768 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 13769@ bl common_dumpRegs 13770 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 13771 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 13772 cmp r3, r9 @ bottom < interpStackEnd? 13773 ldr lr, [rGLUE, #offGlue_pInterpBreak] 13774 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 13775 blo .LstackOverflow @ yes, this frame will overflow stack 13776 13777 @ set up newSaveArea 13778 ldr lr, [lr] @ lr<- active submodes 13779#ifdef EASY_GDB 13780 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 13781 str ip, [r10, #offStackSaveArea_prevSave] 13782#endif 13783 str rFP, [r10, #offStackSaveArea_prevFrame] 13784 str rPC, [r10, #offStackSaveArea_savedPc] 13785#if defined(WITH_JIT) 13786 mov r9, #0 13787 str r9, [r10, #offStackSaveArea_returnAddr] 13788#endif 13789 ands lr, #kSubModeMethodTrace @ method tracing? 13790 beq 1f @ skip if not 13791 stmfd sp!, {r0-r3} @ preserve r0-r3 13792 mov r1, r6 13793 @ r0=methodToCall, r1=rGlue 13794 bl dvmFastMethodTraceEnter 13795 ldmfd sp!, {r0-r3} @ restore r0-r3 137961: 13797 str r0, [r10, #offStackSaveArea_method] 13798 tst r3, #ACC_NATIVE 13799 bne .LinvokeNative 13800 13801 /* 13802 stmfd sp!, {r0-r3} 13803 bl common_printNewline 13804 mov r0, rFP 13805 mov r1, #0 13806 bl dvmDumpFp 13807 ldmfd sp!, {r0-r3} 13808 stmfd sp!, {r0-r3} 13809 mov r0, r1 13810 mov r1, r10 13811 bl dvmDumpFp 13812 bl common_printNewline 13813 ldmfd sp!, {r0-r3} 13814 */ 13815 13816 ldrh r9, [r2] @ r9 <- load INST from new PC 13817 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 13818 mov rPC, r2 @ publish new rPC 13819 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 13820 13821 @ Update "glue" values for the new method 13822 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 13823 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 13824 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 13825#if defined(WITH_JIT) 13826 GET_JIT_PROF_TABLE(r0) 13827 mov rFP, r1 @ fp = newFp 13828 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 13829 mov rINST, r9 @ publish new rINST 13830 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 13831 cmp r0,#0 13832 bne common_updateProfile 13833 GOTO_OPCODE(ip) @ jump to next instruction 13834#else 13835 mov rFP, r1 @ fp = newFp 13836 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 13837 mov rINST, r9 @ publish new rINST 13838 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 13839 GOTO_OPCODE(ip) @ jump to next instruction 13840#endif 13841 13842.LinvokeNative: 13843 @ Prep for the native call 13844 @ r0=methodToCall, r1=newFp, r10=newSaveArea 13845 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 13846 ldr lr, [rGLUE, #offGlue_pInterpBreak] 13847 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 13848 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 13849 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 13850 ldr lr, [lr] @ lr<- active submodes 13851 mov r9, r3 @ r9<- glue->self (preserve) 13852 13853 mov r2, r0 @ r2<- methodToCall 13854 mov r0, r1 @ r0<- newFp (points to args) 13855 add r1, rGLUE, #offGlue_retval @ r1<- &retval 13856 13857#ifdef ASSIST_DEBUGGER 13858 /* insert fake function header to help gdb find the stack frame */ 13859 b .Lskip 13860 .type dalvik_mterp, %function 13861dalvik_mterp: 13862 .fnstart 13863 MTERP_ENTRY1 13864 MTERP_ENTRY2 13865.Lskip: 13866#endif 13867 13868 ands lr, #kSubModeMethodTrace @ method tracing? 13869 beq 110f @ hop if not 13870 @ r2=JNIMethod, r6=rGLUE 13871 stmfd sp!, {r2,r6} 13872 13873 mov lr, pc @ set return addr 13874 ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 13875 13876 @ r0=JNIMethod, r1=rGLUE 13877 ldmfd sp!, {r0-r1} 13878 bl dvmFastNativeMethodTraceExit 13879 @ r2=JNIMethod, r6=rGLUE 13880 stmfd sp!, {r2,r6} 13881 b 220f 13882110: 13883 mov lr, pc @ set return addr 13884 ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 13885220: 13886#if defined(WITH_JIT) 13887 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status 13888#endif 13889 13890 @ native return; r9=self, r10=newSaveArea 13891 @ equivalent to dvmPopJniLocals 13892 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 13893 ldr r1, [r9, #offThread_exception] @ check for exception 13894#if defined(WITH_JIT) 13895 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable 13896#endif 13897 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 13898 cmp r1, #0 @ null? 13899 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 13900#if defined(WITH_JIT) 13901 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch 13902#endif 13903 bne common_exceptionThrown @ no, handle exception 13904 13905 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 13906 GET_INST_OPCODE(ip) @ extract opcode from rINST 13907 GOTO_OPCODE(ip) @ jump to next instruction 13908 13909.LstackOverflow: @ r0=methodToCall 13910 mov r1, r0 @ r1<- methodToCall 13911 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 13912 bl dvmHandleStackOverflow 13913 b common_exceptionThrown 13914#ifdef ASSIST_DEBUGGER 13915 .fnend 13916 .size dalvik_mterp, .-dalvik_mterp 13917#endif 13918 13919 13920 /* 13921 * Common code for method invocation, calling through "glue code". 13922 * 13923 * TODO: now that we have range and non-range invoke handlers, this 13924 * needs to be split into two. Maybe just create entry points 13925 * that set r9 and jump here? 13926 * 13927 * On entry: 13928 * r0 is "Method* methodToCall", the method we're trying to call 13929 * r9 is "bool methodCallRange", indicating if this is a /range variant 13930 */ 13931 .if 0 13932.LinvokeOld: 13933 sub sp, sp, #8 @ space for args + pad 13934 FETCH(ip, 2) @ ip<- FEDC or CCCC 13935 mov r2, r0 @ A2<- methodToCall 13936 mov r0, rGLUE @ A0<- glue 13937 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 13938 mov r1, r9 @ A1<- methodCallRange 13939 mov r3, rINST, lsr #8 @ A3<- AA 13940 str ip, [sp, #0] @ A4<- ip 13941 bl dvmMterp_invokeMethod @ call the C invokeMethod 13942 add sp, sp, #8 @ remove arg area 13943 b common_resumeAfterGlueCall @ continue to next instruction 13944 .endif 13945 13946 13947 13948/* 13949 * Common code for handling a return instruction. 13950 * 13951 * This does not return. 13952 */ 13953common_returnFromMethod: 13954.LreturnNew: 13955 mov r0, #kInterpEntryReturn 13956 mov r9, #0 13957 bl common_periodicChecks 13958 13959 ldr lr, [rGLUE, #offGlue_pInterpBreak] 13960 SAVEAREA_FROM_FP(r0, rFP) 13961 ldr lr, [lr] @ lr<- active submodes 13962 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 13963 ands lr, #kSubModeMethodTrace @ method tracing? 13964 beq 333f 13965 stmfd sp!, {r0-r3} @ preserve r0-r3 13966 mov r0, r6 13967 @ r0=rGlue 13968 bl dvmFastJavaMethodTraceExit 13969 ldmfd sp!, {r0-r3} @ restore r0-r3 13970333: 13971 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 13972 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 13973 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 13974 @ r2<- method we're returning to 13975 cmp r2, #0 @ is this a break frame? 13976#if defined(WORKAROUND_CORTEX_A9_745320) 13977 /* Don't use conditional loads if the HW defect exists */ 13978 beq 101f 13979 ldr r10, [r2, #offMethod_clazz] @ r10<- method->clazz 13980101: 13981#else 13982 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 13983#endif 13984 mov r1, #0 @ "want switch" = false 13985 beq common_gotoBail @ break frame, bail out completely 13986 13987 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 13988 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 13989 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 13990 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 13991#if defined(WITH_JIT) 13992 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr 13993 mov rPC, r9 @ publish new rPC 13994 str r1, [rGLUE, #offGlue_methodClassDex] 13995 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land 13996 cmp r10, #0 @ caller is compiled code 13997 blxne r10 13998 GET_INST_OPCODE(ip) @ extract opcode from rINST 13999 GOTO_OPCODE(ip) @ jump to next instruction 14000#else 14001 GET_INST_OPCODE(ip) @ extract opcode from rINST 14002 mov rPC, r9 @ publish new rPC 14003 str r1, [rGLUE, #offGlue_methodClassDex] 14004 GOTO_OPCODE(ip) @ jump to next instruction 14005#endif 14006 14007 /* 14008 * Return handling, calls through "glue code". 14009 */ 14010 .if 0 14011.LreturnOld: 14012 SAVE_PC_FP_TO_GLUE() @ export state 14013 mov r0, rGLUE @ arg to function 14014 bl dvmMterp_returnFromMethod 14015 b common_resumeAfterGlueCall 14016 .endif 14017 14018 14019/* 14020 * Somebody has thrown an exception. Handle it. 14021 * 14022 * If the exception processing code returns to us (instead of falling 14023 * out of the interpreter), continue with whatever the next instruction 14024 * now happens to be. 14025 * 14026 * This does not return. 14027 */ 14028 .global dvmMterpCommonExceptionThrown 14029dvmMterpCommonExceptionThrown: 14030common_exceptionThrown: 14031.LexceptionNew: 14032 mov r0, #kInterpEntryThrow 14033 mov r9, #0 14034 bl common_periodicChecks 14035 14036 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 14037 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 14038 mov r1, r10 @ r1<- self 14039 mov r0, r9 @ r0<- exception 14040 bl dvmAddTrackedAlloc @ don't let the exception be GCed 14041 mov r3, #0 @ r3<- NULL 14042 str r3, [r10, #offThread_exception] @ self->exception = NULL 14043 14044 /* set up args and a local for "&fp" */ 14045 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 14046 str rFP, [sp, #-4]! @ *--sp = fp 14047 mov ip, sp @ ip<- &fp 14048 mov r3, #0 @ r3<- false 14049 str ip, [sp, #-4]! @ *--sp = &fp 14050 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 14051 mov r0, r10 @ r0<- self 14052 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 14053 mov r2, r9 @ r2<- exception 14054 sub r1, rPC, r1 @ r1<- pc - method->insns 14055 mov r1, r1, asr #1 @ r1<- offset in code units 14056 14057 /* call, r0 gets catchRelPc (a code-unit offset) */ 14058 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 14059 14060 /* fix earlier stack overflow if necessary; may trash rFP */ 14061 ldrb r1, [r10, #offThread_stackOverflowed] 14062 cmp r1, #0 @ did we overflow earlier? 14063 beq 1f @ no, skip ahead 14064 mov rFP, r0 @ save relPc result in rFP 14065 mov r0, r10 @ r0<- self 14066 mov r1, r9 @ r1<- exception 14067 bl dvmCleanupStackOverflow @ call(self) 14068 mov r0, rFP @ restore result 140691: 14070 14071 /* update frame pointer and check result from dvmFindCatchBlock */ 14072 ldr rFP, [sp, #4] @ retrieve the updated rFP 14073 cmp r0, #0 @ is catchRelPc < 0? 14074 add sp, sp, #8 @ restore stack 14075 bmi .LnotCaughtLocally 14076 14077 /* adjust locals to match self->curFrame and updated PC */ 14078 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 14079 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 14080 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 14081 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 14082 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 14083 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 14084 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 14085 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 14086 14087 /* release the tracked alloc on the exception */ 14088 mov r0, r9 @ r0<- exception 14089 mov r1, r10 @ r1<- self 14090 bl dvmReleaseTrackedAlloc @ release the exception 14091 14092 /* restore the exception if the handler wants it */ 14093 FETCH_INST() @ load rINST from rPC 14094 GET_INST_OPCODE(ip) @ extract opcode from rINST 14095 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 14096 streq r9, [r10, #offThread_exception] @ yes, restore the exception 14097 GOTO_OPCODE(ip) @ jump to next instruction 14098 14099.LnotCaughtLocally: @ r9=exception, r10=self 14100 /* fix stack overflow if necessary */ 14101 ldrb r1, [r10, #offThread_stackOverflowed] 14102 cmp r1, #0 @ did we overflow earlier? 14103 movne r0, r10 @ if yes: r0<- self 14104 movne r1, r9 @ if yes: r1<- exception 14105 blne dvmCleanupStackOverflow @ if yes: call(self) 14106 14107 @ may want to show "not caught locally" debug messages here 14108#if DVM_SHOW_EXCEPTION >= 2 14109 /* call __android_log_print(prio, tag, format, ...) */ 14110 /* "Exception %s from %s:%d not caught locally" */ 14111 @ dvmLineNumFromPC(method, pc - method->insns) 14112 ldr r0, [rGLUE, #offGlue_method] 14113 ldr r1, [r0, #offMethod_insns] 14114 sub r1, rPC, r1 14115 asr r1, r1, #1 14116 bl dvmLineNumFromPC 14117 str r0, [sp, #-4]! 14118 @ dvmGetMethodSourceFile(method) 14119 ldr r0, [rGLUE, #offGlue_method] 14120 bl dvmGetMethodSourceFile 14121 str r0, [sp, #-4]! 14122 @ exception->clazz->descriptor 14123 ldr r3, [r9, #offObject_clazz] 14124 ldr r3, [r3, #offClassObject_descriptor] 14125 @ 14126 ldr r2, strExceptionNotCaughtLocally 14127 ldr r1, strLogTag 14128 mov r0, #3 @ LOG_DEBUG 14129 bl __android_log_print 14130#endif 14131 str r9, [r10, #offThread_exception] @ restore exception 14132 mov r0, r9 @ r0<- exception 14133 mov r1, r10 @ r1<- self 14134 bl dvmReleaseTrackedAlloc @ release the exception 14135 mov r1, #0 @ "want switch" = false 14136 b common_gotoBail @ bail out 14137 14138 14139 /* 14140 * Exception handling, calls through "glue code". 14141 */ 14142 .if 0 14143.LexceptionOld: 14144 SAVE_PC_FP_TO_GLUE() @ export state 14145 mov r0, rGLUE @ arg to function 14146 bl dvmMterp_exceptionThrown 14147 b common_resumeAfterGlueCall 14148 .endif 14149 14150 14151/* 14152 * After returning from a "glued" function, pull out the updated 14153 * values and start executing at the next instruction. 14154 */ 14155common_resumeAfterGlueCall: 14156 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 14157 FETCH_INST() @ load rINST from rPC 14158 GET_INST_OPCODE(ip) @ extract opcode from rINST 14159 GOTO_OPCODE(ip) @ jump to next instruction 14160 14161/* 14162 * Invalid array index. Note that our calling convention is strange; we use r1 14163 * and r3 because those just happen to be the registers all our callers are 14164 * using. We shuffle them here before calling the C function. 14165 * r1: index 14166 * r3: size 14167 */ 14168common_errArrayIndex: 14169 EXPORT_PC() 14170 mov r0, r1 14171 mov r1, r3 14172 bl dvmThrowAIOOBE 14173 b common_exceptionThrown 14174 14175/* 14176 * Integer divide or mod by zero. 14177 */ 14178common_errDivideByZero: 14179 EXPORT_PC() 14180 ldr r0, strArithmeticException 14181 ldr r1, strDivideByZero 14182 bl dvmThrowException 14183 b common_exceptionThrown 14184 14185/* 14186 * Attempt to allocate an array with a negative size. 14187 */ 14188common_errNegativeArraySize: 14189 EXPORT_PC() 14190 ldr r0, strNegativeArraySizeException 14191 mov r1, #0 14192 bl dvmThrowException 14193 b common_exceptionThrown 14194 14195/* 14196 * Invocation of a non-existent method. 14197 */ 14198common_errNoSuchMethod: 14199 EXPORT_PC() 14200 ldr r0, strNoSuchMethodError 14201 mov r1, #0 14202 bl dvmThrowException 14203 b common_exceptionThrown 14204 14205/* 14206 * We encountered a null object when we weren't expecting one. We 14207 * export the PC, throw a NullPointerException, and goto the exception 14208 * processing code. 14209 */ 14210common_errNullObject: 14211 EXPORT_PC() 14212 ldr r0, strNullPointerException 14213 mov r1, #0 14214 bl dvmThrowException 14215 b common_exceptionThrown 14216 14217/* 14218 * For debugging, cause an immediate fault. The source address will 14219 * be in lr (use a bl instruction to jump here). 14220 */ 14221common_abort: 14222 ldr pc, .LdeadFood 14223.LdeadFood: 14224 .word 0xdeadf00d 14225 14226/* 14227 * Spit out a "we were here", preserving all registers. (The attempt 14228 * to save ip won't work, but we need to save an even number of 14229 * registers for EABI 64-bit stack alignment.) 14230 */ 14231 .macro SQUEAK num 14232common_squeak\num: 14233 stmfd sp!, {r0, r1, r2, r3, ip, lr} 14234 ldr r0, strSqueak 14235 mov r1, #\num 14236 bl printf 14237 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 14238 bx lr 14239 .endm 14240 14241 SQUEAK 0 14242 SQUEAK 1 14243 SQUEAK 2 14244 SQUEAK 3 14245 SQUEAK 4 14246 SQUEAK 5 14247 14248/* 14249 * Spit out the number in r0, preserving registers. 14250 */ 14251common_printNum: 14252 stmfd sp!, {r0, r1, r2, r3, ip, lr} 14253 mov r1, r0 14254 ldr r0, strSqueak 14255 bl printf 14256 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 14257 bx lr 14258 14259/* 14260 * Print a newline, preserving registers. 14261 */ 14262common_printNewline: 14263 stmfd sp!, {r0, r1, r2, r3, ip, lr} 14264 ldr r0, strNewline 14265 bl printf 14266 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 14267 bx lr 14268 14269 /* 14270 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 14271 */ 14272common_printHex: 14273 stmfd sp!, {r0, r1, r2, r3, ip, lr} 14274 mov r1, r0 14275 ldr r0, strPrintHex 14276 bl printf 14277 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 14278 bx lr 14279 14280/* 14281 * Print the 64-bit quantity in r0-r1, preserving registers. 14282 */ 14283common_printLong: 14284 stmfd sp!, {r0, r1, r2, r3, ip, lr} 14285 mov r3, r1 14286 mov r2, r0 14287 ldr r0, strPrintLong 14288 bl printf 14289 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 14290 bx lr 14291 14292/* 14293 * Print full method info. Pass the Method* in r0. Preserves regs. 14294 */ 14295common_printMethod: 14296 stmfd sp!, {r0, r1, r2, r3, ip, lr} 14297 bl dvmMterpPrintMethod 14298 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 14299 bx lr 14300 14301/* 14302 * Call a C helper function that dumps regs and possibly some 14303 * additional info. Requires the C function to be compiled in. 14304 */ 14305 .if 0 14306common_dumpRegs: 14307 stmfd sp!, {r0, r1, r2, r3, ip, lr} 14308 bl dvmMterpDumpArmRegs 14309 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 14310 bx lr 14311 .endif 14312 14313#if 0 14314/* 14315 * Experiment on VFP mode. 14316 * 14317 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 14318 * 14319 * Updates the bits specified by "mask", setting them to the values in "val". 14320 */ 14321setFPSCR: 14322 and r0, r0, r1 @ make sure no stray bits are set 14323 fmrx r2, fpscr @ get VFP reg 14324 mvn r1, r1 @ bit-invert mask 14325 and r2, r2, r1 @ clear masked bits 14326 orr r2, r2, r0 @ set specified bits 14327 fmxr fpscr, r2 @ set VFP reg 14328 mov r0, r2 @ return new value 14329 bx lr 14330 14331 .align 2 14332 .global dvmConfigureFP 14333 .type dvmConfigureFP, %function 14334dvmConfigureFP: 14335 stmfd sp!, {ip, lr} 14336 /* 0x03000000 sets DN/FZ */ 14337 /* 0x00009f00 clears the six exception enable flags */ 14338 bl common_squeak0 14339 mov r0, #0x03000000 @ r0<- 0x03000000 14340 add r1, r0, #0x9f00 @ r1<- 0x03009f00 14341 bl setFPSCR 14342 ldmfd sp!, {ip, pc} 14343#endif 14344 14345 14346/* 14347 * String references, must be close to the code that uses them. 14348 */ 14349 .align 2 14350strArithmeticException: 14351 .word .LstrArithmeticException 14352strDivideByZero: 14353 .word .LstrDivideByZero 14354strNegativeArraySizeException: 14355 .word .LstrNegativeArraySizeException 14356strNoSuchMethodError: 14357 .word .LstrNoSuchMethodError 14358strNullPointerException: 14359 .word .LstrNullPointerException 14360 14361strLogTag: 14362 .word .LstrLogTag 14363strExceptionNotCaughtLocally: 14364 .word .LstrExceptionNotCaughtLocally 14365 14366strNewline: 14367 .word .LstrNewline 14368strSqueak: 14369 .word .LstrSqueak 14370strPrintHex: 14371 .word .LstrPrintHex 14372strPrintLong: 14373 .word .LstrPrintLong 14374 14375/* 14376 * Zero-terminated ASCII string data. 14377 * 14378 * On ARM we have two choices: do like gcc does, and LDR from a .word 14379 * with the address, or use an ADR pseudo-op to get the address 14380 * directly. ADR saves 4 bytes and an indirection, but it's using a 14381 * PC-relative addressing mode and hence has a limited range, which 14382 * makes it not work well with mergeable string sections. 14383 */ 14384 .section .rodata.str1.4,"aMS",%progbits,1 14385 14386.LstrBadEntryPoint: 14387 .asciz "Bad entry point %d\n" 14388.LstrArithmeticException: 14389 .asciz "Ljava/lang/ArithmeticException;" 14390.LstrDivideByZero: 14391 .asciz "divide by zero" 14392.LstrFilledNewArrayNotImpl: 14393 .asciz "filled-new-array only implemented for objects and 'int'" 14394.LstrInternalError: 14395 .asciz "Ljava/lang/InternalError;" 14396.LstrInstantiationError: 14397 .asciz "Ljava/lang/InstantiationError;" 14398.LstrNegativeArraySizeException: 14399 .asciz "Ljava/lang/NegativeArraySizeException;" 14400.LstrNoSuchMethodError: 14401 .asciz "Ljava/lang/NoSuchMethodError;" 14402.LstrNullPointerException: 14403 .asciz "Ljava/lang/NullPointerException;" 14404 14405.LstrLogTag: 14406 .asciz "mterp" 14407.LstrExceptionNotCaughtLocally: 14408 .asciz "Exception %s from %s:%d not caught locally\n" 14409 14410.LstrNewline: 14411 .asciz "\n" 14412.LstrSqueak: 14413 .asciz "<%d>" 14414.LstrPrintHex: 14415 .asciz "<0x%x>" 14416.LstrPrintLong: 14417 .asciz "<%lld>" 14418 14419