InterpAsm-armv5te-vfp.S revision 6af2ddd107842c3737c04c37343cac9be17f4209
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> on an object. In practice we know that 7416 * Object's nullary constructor doesn't do anything, so we just 7417 * skip it (we know a debugger isn't active). 7418 */ 7419 FETCH(r0, 2) @ r0<- GFED 7420 and r1, r0, #15 @ r1<- D 7421 GET_VREG(r0, r1) @ r0<- "this" ptr 7422 cmp r0, #0 @ check for NULL 7423 beq common_errNullObject @ export PC and throw NPE 7424 ldr r1, [r0, #offObject_clazz] @ r1<- obj->clazz 7425 ldr r2, [r1, #offClassObject_accessFlags] @ r2<- clazz->accessFlags 7426 tst r2, #CLASS_ISFINALIZABLE @ is this class finalizable? 7427 beq 1f @ nope, done 7428 bl dvmSetFinalizable @ call dvmSetFinalizable(obj) 74291: FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7430 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7431 GOTO_OPCODE(ip) @ execute it 7432 7433/* ------------------------------ */ 7434 .balign 64 7435.L_OP_RETURN_VOID_BARRIER: /* 0xf1 */ 7436/* File: armv5te/OP_RETURN_VOID_BARRIER.S */ 7437 SMP_DMB_ST 7438 b common_returnFromMethod 7439 7440/* ------------------------------ */ 7441 .balign 64 7442.L_OP_IGET_QUICK: /* 0xf2 */ 7443/* File: armv5te/OP_IGET_QUICK.S */ 7444 /* For: iget-quick, iget-object-quick */ 7445 /* op vA, vB, offset@CCCC */ 7446 mov r2, rINST, lsr #12 @ r2<- B 7447 GET_VREG(r3, r2) @ r3<- object we're operating on 7448 FETCH(r1, 1) @ r1<- field byte offset 7449 cmp r3, #0 @ check object for null 7450 mov r2, rINST, lsr #8 @ r2<- A(+) 7451 beq common_errNullObject @ object was null 7452 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7453 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7454 and r2, r2, #15 7455 GET_INST_OPCODE(ip) @ extract opcode from rINST 7456 SET_VREG(r0, r2) @ fp[A]<- r0 7457 GOTO_OPCODE(ip) @ jump to next instruction 7458 7459/* ------------------------------ */ 7460 .balign 64 7461.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7462/* File: armv5te/OP_IGET_WIDE_QUICK.S */ 7463 /* iget-wide-quick vA, vB, offset@CCCC */ 7464 mov r2, rINST, lsr #12 @ r2<- B 7465 GET_VREG(r3, r2) @ r3<- object we're operating on 7466 FETCH(ip, 1) @ ip<- field byte offset 7467 cmp r3, #0 @ check object for null 7468 mov r2, rINST, lsr #8 @ r2<- A(+) 7469 beq common_errNullObject @ object was null 7470 ldrd r0, [r3, ip] @ r0<- obj.field (64 bits, aligned) 7471 and r2, r2, #15 7472 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7473 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7474 GET_INST_OPCODE(ip) @ extract opcode from rINST 7475 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7476 GOTO_OPCODE(ip) @ jump to next instruction 7477 7478/* ------------------------------ */ 7479 .balign 64 7480.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7481/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7482/* File: armv5te/OP_IGET_QUICK.S */ 7483 /* For: iget-quick, iget-object-quick */ 7484 /* op vA, vB, offset@CCCC */ 7485 mov r2, rINST, lsr #12 @ r2<- B 7486 GET_VREG(r3, r2) @ r3<- object we're operating on 7487 FETCH(r1, 1) @ r1<- field byte offset 7488 cmp r3, #0 @ check object for null 7489 mov r2, rINST, lsr #8 @ r2<- A(+) 7490 beq common_errNullObject @ object was null 7491 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7492 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7493 and r2, r2, #15 7494 GET_INST_OPCODE(ip) @ extract opcode from rINST 7495 SET_VREG(r0, r2) @ fp[A]<- r0 7496 GOTO_OPCODE(ip) @ jump to next instruction 7497 7498 7499/* ------------------------------ */ 7500 .balign 64 7501.L_OP_IPUT_QUICK: /* 0xf5 */ 7502/* File: armv5te/OP_IPUT_QUICK.S */ 7503 /* For: iput-quick */ 7504 /* op vA, vB, offset@CCCC */ 7505 mov r2, rINST, lsr #12 @ r2<- B 7506 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7507 FETCH(r1, 1) @ r1<- field byte offset 7508 cmp r3, #0 @ check object for null 7509 mov r2, rINST, lsr #8 @ r2<- A(+) 7510 beq common_errNullObject @ object was null 7511 and r2, r2, #15 7512 GET_VREG(r0, r2) @ r0<- fp[A] 7513 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7514 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7515 GET_INST_OPCODE(ip) @ extract opcode from rINST 7516 GOTO_OPCODE(ip) @ jump to next instruction 7517 7518/* ------------------------------ */ 7519 .balign 64 7520.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7521/* File: armv5te/OP_IPUT_WIDE_QUICK.S */ 7522 /* iput-wide-quick vA, vB, offset@CCCC */ 7523 mov r0, rINST, lsr #8 @ r0<- A(+) 7524 mov r1, rINST, lsr #12 @ r1<- B 7525 and r0, r0, #15 7526 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7527 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7528 cmp r2, #0 @ check object for null 7529 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7530 beq common_errNullObject @ object was null 7531 FETCH(r3, 1) @ r3<- field byte offset 7532 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7533 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7534 GET_INST_OPCODE(ip) @ extract opcode from rINST 7535 GOTO_OPCODE(ip) @ jump to next instruction 7536 7537/* ------------------------------ */ 7538 .balign 64 7539.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7540/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7541 /* For: iput-object-quick */ 7542 /* op vA, vB, offset@CCCC */ 7543 mov r2, rINST, lsr #12 @ r2<- B 7544 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7545 FETCH(r1, 1) @ r1<- field byte offset 7546 cmp r3, #0 @ check object for null 7547 mov r2, rINST, lsr #8 @ r2<- A(+) 7548 beq common_errNullObject @ object was null 7549 and r2, r2, #15 7550 GET_VREG(r0, r2) @ r0<- fp[A] 7551 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 7552 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7553 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7554 cmp r0, #0 7555 strneb r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head 7556 GET_INST_OPCODE(ip) @ extract opcode from rINST 7557 GOTO_OPCODE(ip) @ jump to next instruction 7558 7559/* ------------------------------ */ 7560 .balign 64 7561.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7562/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7563 /* 7564 * Handle an optimized virtual method call. 7565 * 7566 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7567 */ 7568 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7569 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7570 FETCH(r3, 2) @ r3<- FEDC or CCCC 7571 FETCH(r1, 1) @ r1<- BBBB 7572 .if (!0) 7573 and r3, r3, #15 @ r3<- C (or stays CCCC) 7574 .endif 7575 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7576 cmp r2, #0 @ is "this" null? 7577 beq common_errNullObject @ null "this", throw exception 7578 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7579 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7580 EXPORT_PC() @ invoke must export 7581 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7582 bl common_invokeMethodNoRange @ continue on 7583 7584/* ------------------------------ */ 7585 .balign 64 7586.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7587/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7588/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7589 /* 7590 * Handle an optimized virtual method call. 7591 * 7592 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7593 */ 7594 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7595 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7596 FETCH(r3, 2) @ r3<- FEDC or CCCC 7597 FETCH(r1, 1) @ r1<- BBBB 7598 .if (!1) 7599 and r3, r3, #15 @ r3<- C (or stays CCCC) 7600 .endif 7601 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7602 cmp r2, #0 @ is "this" null? 7603 beq common_errNullObject @ null "this", throw exception 7604 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7605 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7606 EXPORT_PC() @ invoke must export 7607 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7608 bl common_invokeMethodRange @ continue on 7609 7610 7611/* ------------------------------ */ 7612 .balign 64 7613.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7614/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7615 /* 7616 * Handle an optimized "super" method call. 7617 * 7618 * for: [opt] invoke-super-quick, invoke-super-quick/range 7619 */ 7620 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7621 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7622 FETCH(r10, 2) @ r10<- GFED or CCCC 7623 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7624 .if (!0) 7625 and r10, r10, #15 @ r10<- D (or stays CCCC) 7626 .endif 7627 FETCH(r1, 1) @ r1<- BBBB 7628 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7629 EXPORT_PC() @ must export for invoke 7630 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7631 GET_VREG(r3, r10) @ r3<- "this" 7632 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7633 cmp r3, #0 @ null "this" ref? 7634 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7635 beq common_errNullObject @ "this" is null, throw exception 7636 bl common_invokeMethodNoRange @ continue on 7637 7638/* ------------------------------ */ 7639 .balign 64 7640.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7641/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7642/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7643 /* 7644 * Handle an optimized "super" method call. 7645 * 7646 * for: [opt] invoke-super-quick, invoke-super-quick/range 7647 */ 7648 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7649 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7650 FETCH(r10, 2) @ r10<- GFED or CCCC 7651 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7652 .if (!1) 7653 and r10, r10, #15 @ r10<- D (or stays CCCC) 7654 .endif 7655 FETCH(r1, 1) @ r1<- BBBB 7656 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7657 EXPORT_PC() @ must export for invoke 7658 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7659 GET_VREG(r3, r10) @ r3<- "this" 7660 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7661 cmp r3, #0 @ null "this" ref? 7662 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7663 beq common_errNullObject @ "this" is null, throw exception 7664 bl common_invokeMethodRange @ continue on 7665 7666 7667/* ------------------------------ */ 7668 .balign 64 7669.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ 7670/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */ 7671/* File: armv5te/OP_IPUT_OBJECT.S */ 7672 /* 7673 * 32-bit instance field put. 7674 * 7675 * for: iput-object, iput-object-volatile 7676 */ 7677 /* op vA, vB, field@CCCC */ 7678 mov r0, rINST, lsr #12 @ r0<- B 7679 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7680 FETCH(r1, 1) @ r1<- field ref CCCC 7681 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7682 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7683 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7684 cmp r0, #0 @ is resolved entry null? 7685 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ no, already resolved 76868: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7687 EXPORT_PC() @ resolve() could throw 7688 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7689 bl dvmResolveInstField @ r0<- resolved InstField ptr 7690 cmp r0, #0 @ success? 7691 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ yes, finish up 7692 b common_exceptionThrown 7693 7694 7695/* ------------------------------ */ 7696 .balign 64 7697.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ 7698/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */ 7699/* File: armv5te/OP_SGET.S */ 7700 /* 7701 * General 32-bit SGET handler. 7702 * 7703 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7704 */ 7705 /* op vAA, field@BBBB */ 7706 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7707 FETCH(r1, 1) @ r1<- field ref BBBB 7708 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7709 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7710 cmp r0, #0 @ is resolved entry null? 7711 beq .LOP_SGET_OBJECT_VOLATILE_resolve @ yes, do resolve 7712.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0 7713 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7714 SMP_DMB @ acquiring load 7715 mov r2, rINST, lsr #8 @ r2<- AA 7716 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7717 SET_VREG(r1, r2) @ fp[AA]<- r1 7718 GET_INST_OPCODE(ip) @ extract opcode from rINST 7719 GOTO_OPCODE(ip) @ jump to next instruction 7720 7721 7722/* ------------------------------ */ 7723 .balign 64 7724.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ 7725/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */ 7726/* File: armv5te/OP_SPUT_OBJECT.S */ 7727 /* 7728 * 32-bit SPUT handler for objects 7729 * 7730 * for: sput-object, sput-object-volatile 7731 */ 7732 /* op vAA, field@BBBB */ 7733 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7734 FETCH(r1, 1) @ r1<- field ref BBBB 7735 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7736 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7737 cmp r0, #0 @ is resolved entry null? 7738 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ no, continue 7739 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 7740 EXPORT_PC() @ resolve() could throw, so export now 7741 ldr r0, [r9, #offMethod_clazz] @ r0<- method->clazz 7742 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 7743 cmp r0, #0 @ success? 7744 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish 7745 b common_exceptionThrown @ no, handle exception 7746 7747 7748 7749/* ------------------------------ */ 7750 .balign 64 7751.L_OP_DISPATCH_FF: /* 0xff */ 7752/* File: armv5te/OP_DISPATCH_FF.S */ 7753 mov ip, rINST, lsr #8 @ r9<- extended opcode 7754 add ip, ip, #256 @ add offset for extended opcodes 7755 GOTO_OPCODE(ip) @ go to proper extended handler 7756 7757 7758/* ------------------------------ */ 7759 .balign 64 7760.L_OP_CONST_CLASS_JUMBO: /* 0x100 */ 7761/* File: armv5te/OP_CONST_CLASS_JUMBO.S */ 7762 /* const-class/jumbo vBBBB, Class@AAAAAAAA */ 7763 FETCH(r0, 1) @ r0<- aaaa (lo) 7764 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 7765 FETCH(r1, 2) @ r1<- AAAA (hi) 7766 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 7767 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 7768 FETCH(r9, 3) @ r9<- BBBB 7769 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[AAAAaaaa] 7770 cmp r0, #0 @ not yet resolved? 7771 beq .LOP_CONST_CLASS_JUMBO_resolve 7772 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 7773 GET_INST_OPCODE(ip) @ extract opcode from rINST 7774 SET_VREG(r0, r9) @ vBBBB<- r0 7775 GOTO_OPCODE(ip) @ jump to next instruction 7776 7777/* ------------------------------ */ 7778 .balign 64 7779.L_OP_CHECK_CAST_JUMBO: /* 0x101 */ 7780/* File: armv5te/OP_CHECK_CAST_JUMBO.S */ 7781 /* 7782 * Check to see if a cast from one class to another is allowed. 7783 */ 7784 /* check-cast/jumbo vBBBB, class@AAAAAAAA */ 7785 FETCH(r0, 1) @ r0<- aaaa (lo) 7786 FETCH(r2, 2) @ r2<- AAAA (hi) 7787 FETCH(r3, 3) @ r3<- BBBB 7788 orr r2, r0, r2, lsl #16 @ r2<- AAAAaaaa 7789 GET_VREG(r9, r3) @ r9<- object 7790 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 7791 cmp r9, #0 @ is object null? 7792 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 7793 beq .LOP_CHECK_CAST_JUMBO_okay @ null obj, cast always succeeds 7794 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 7795 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7796 cmp r1, #0 @ have we resolved this before? 7797 beq .LOP_CHECK_CAST_JUMBO_resolve @ not resolved, do it now 7798.LOP_CHECK_CAST_JUMBO_resolved: 7799 cmp r0, r1 @ same class (trivial success)? 7800 bne .LOP_CHECK_CAST_JUMBO_fullcheck @ no, do full check 7801 b .LOP_CHECK_CAST_JUMBO_okay @ yes, finish up 7802 7803/* ------------------------------ */ 7804 .balign 64 7805.L_OP_INSTANCE_OF_JUMBO: /* 0x102 */ 7806/* File: armv5te/OP_INSTANCE_OF_JUMBO.S */ 7807 /* 7808 * Check to see if an object reference is an instance of a class. 7809 * 7810 * Most common situation is a non-null object, being compared against 7811 * an already-resolved class. 7812 * 7813 * TODO: convert most of this into a common subroutine, shared with 7814 * OP_INSTANCE_OF.S. 7815 */ 7816 /* instance-of/jumbo vBBBB, vCCCC, class@AAAAAAAA */ 7817 FETCH(r3, 4) @ r3<- vCCCC 7818 FETCH(r9, 3) @ r9<- vBBBB 7819 GET_VREG(r0, r3) @ r0<- vCCCC (object) 7820 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 7821 cmp r0, #0 @ is object null? 7822 beq .LOP_INSTANCE_OF_JUMBO_store @ null obj, not an instance, store r0 7823 FETCH(r1, 1) @ r1<- aaaa (lo) 7824 FETCH(r3, 2) @ r3<- AAAA (hi) 7825 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 7826 orr r3, r1, r3, lsl #16 @ r3<- AAAAaaaa 7827 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 7828 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7829 cmp r1, #0 @ have we resolved this before? 7830 beq .LOP_INSTANCE_OF_JUMBO_resolve @ not resolved, do it now 7831 b .LOP_INSTANCE_OF_JUMBO_resolved @ resolved, continue 7832 7833/* ------------------------------ */ 7834 .balign 64 7835.L_OP_NEW_INSTANCE_JUMBO: /* 0x103 */ 7836/* File: armv5te/OP_NEW_INSTANCE_JUMBO.S */ 7837 /* 7838 * Create a new instance of a class. 7839 */ 7840 /* new-instance/jumbo vBBBB, class@AAAAAAAA */ 7841 FETCH(r0, 1) @ r0<- aaaa (lo) 7842 FETCH(r1, 2) @ r1<- AAAA (hi) 7843 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 7844 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 7845 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 7846 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 7847 EXPORT_PC() @ req'd for init, resolve, alloc 7848 cmp r0, #0 @ already resolved? 7849 beq .LOP_NEW_INSTANCE_JUMBO_resolve @ no, resolve it now 7850.LOP_NEW_INSTANCE_JUMBO_resolved: @ r0=class 7851 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 7852 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 7853 bne .LOP_NEW_INSTANCE_JUMBO_needinit @ no, init class now 7854.LOP_NEW_INSTANCE_JUMBO_initialized: @ r0=class 7855 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 7856 bl dvmAllocObject @ r0<- new object 7857 b .LOP_NEW_INSTANCE_JUMBO_finish @ continue 7858 7859/* ------------------------------ */ 7860 .balign 64 7861.L_OP_NEW_ARRAY_JUMBO: /* 0x104 */ 7862/* File: armv5te/OP_NEW_ARRAY_JUMBO.S */ 7863 /* 7864 * Allocate an array of objects, specified with the array class 7865 * and a count. 7866 * 7867 * The verifier guarantees that this is an array class, so we don't 7868 * check for it here. 7869 */ 7870 /* new-array/jumbo vBBBB, vCCCC, class@AAAAAAAA */ 7871 FETCH(r2, 1) @ r2<- aaaa (lo) 7872 FETCH(r3, 2) @ r3<- AAAA (hi) 7873 FETCH(r0, 4) @ r0<- vCCCC 7874 orr r2, r2, r3, lsl #16 @ r2<- AAAAaaaa 7875 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 7876 GET_VREG(r1, r0) @ r1<- vCCCC (array length) 7877 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 7878 cmp r1, #0 @ check length 7879 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 7880 bmi common_errNegativeArraySize @ negative length, bail 7881 cmp r0, #0 @ already resolved? 7882 EXPORT_PC() @ req'd for resolve, alloc 7883 bne .LOP_NEW_ARRAY_JUMBO_finish @ resolved, continue 7884 b .LOP_NEW_ARRAY_JUMBO_resolve @ do resolve now 7885 7886/* ------------------------------ */ 7887 .balign 64 7888.L_OP_FILLED_NEW_ARRAY_JUMBO: /* 0x105 */ 7889/* File: armv5te/OP_FILLED_NEW_ARRAY_JUMBO.S */ 7890 /* 7891 * Create a new array with elements filled from registers. 7892 * 7893 * TODO: convert most of this into a common subroutine, shared with 7894 * OP_FILLED_NEW_ARRAY.S. 7895 */ 7896 /* filled-new-array/jumbo {vCCCC..v(CCCC+BBBB-1)}, type@AAAAAAAA */ 7897 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 7898 FETCH(r0, 1) @ r0<- aaaa (lo) 7899 FETCH(r1, 2) @ r1<- AAAA (hi) 7900 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 7901 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 7902 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 7903 EXPORT_PC() @ need for resolve and alloc 7904 cmp r0, #0 @ already resolved? 7905 bne .LOP_FILLED_NEW_ARRAY_JUMBO_continue @ yes, continue on 79068: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7907 mov r2, #0 @ r2<- false 7908 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7909 bl dvmResolveClass @ r0<- call(clazz, ref) 7910 cmp r0, #0 @ got null? 7911 beq common_exceptionThrown @ yes, handle exception 7912 b .LOP_FILLED_NEW_ARRAY_JUMBO_continue 7913 7914/* ------------------------------ */ 7915 .balign 64 7916.L_OP_IGET_JUMBO: /* 0x106 */ 7917/* File: armv5te/OP_IGET_JUMBO.S */ 7918 /* 7919 * Jumbo 32-bit instance field get. 7920 * 7921 * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo, 7922 * iget-char/jumbo, iget-short/jumbo 7923 */ 7924 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 7925 FETCH(r1, 1) @ r1<- aaaa (lo) 7926 FETCH(r2, 2) @ r2<- AAAA (hi) 7927 FETCH(r0, 4) @ r0<- CCCC 7928 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7929 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 7930 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7931 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 7932 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7933 cmp r0, #0 @ is resolved entry null? 7934 bne .LOP_IGET_JUMBO_finish @ no, already resolved 79358: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7936 EXPORT_PC() @ resolve() could throw 7937 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7938 bl dvmResolveInstField @ r0<- resolved InstField ptr 7939 b .LOP_IGET_JUMBO_resolved @ resolved, continue 7940 7941/* ------------------------------ */ 7942 .balign 64 7943.L_OP_IGET_WIDE_JUMBO: /* 0x107 */ 7944/* File: armv5te/OP_IGET_WIDE_JUMBO.S */ 7945 /* 7946 * Jumbo 64-bit instance field get. 7947 */ 7948 /* iget-wide/jumbo vBBBB, vCCCC, field@AAAAAAAA */ 7949 FETCH(r1, 1) @ r1<- aaaa (lo) 7950 FETCH(r2, 2) @ r2<- AAAA (hi) 7951 FETCH(r0, 4) @ r0<- CCCC 7952 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7953 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 7954 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7955 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 7956 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7957 cmp r0, #0 @ is resolved entry null? 7958 bne .LOP_IGET_WIDE_JUMBO_finish @ no, already resolved 79598: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7960 EXPORT_PC() @ resolve() could throw 7961 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7962 bl dvmResolveInstField @ r0<- resolved InstField ptr 7963 b .LOP_IGET_WIDE_JUMBO_resolved @ resolved, continue 7964 7965/* ------------------------------ */ 7966 .balign 64 7967.L_OP_IGET_OBJECT_JUMBO: /* 0x108 */ 7968/* File: armv5te/OP_IGET_OBJECT_JUMBO.S */ 7969/* File: armv5te/OP_IGET_JUMBO.S */ 7970 /* 7971 * Jumbo 32-bit instance field get. 7972 * 7973 * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo, 7974 * iget-char/jumbo, iget-short/jumbo 7975 */ 7976 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 7977 FETCH(r1, 1) @ r1<- aaaa (lo) 7978 FETCH(r2, 2) @ r2<- AAAA (hi) 7979 FETCH(r0, 4) @ r0<- CCCC 7980 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7981 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 7982 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7983 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 7984 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7985 cmp r0, #0 @ is resolved entry null? 7986 bne .LOP_IGET_OBJECT_JUMBO_finish @ no, already resolved 79878: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7988 EXPORT_PC() @ resolve() could throw 7989 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7990 bl dvmResolveInstField @ r0<- resolved InstField ptr 7991 b .LOP_IGET_OBJECT_JUMBO_resolved @ resolved, continue 7992 7993 7994/* ------------------------------ */ 7995 .balign 64 7996.L_OP_IGET_BOOLEAN_JUMBO: /* 0x109 */ 7997/* File: armv5te/OP_IGET_BOOLEAN_JUMBO.S */ 7998@include "armv5te/OP_IGET_JUMBO.S" { "load":"ldrb", "sqnum":"1" } 7999/* File: armv5te/OP_IGET_JUMBO.S */ 8000 /* 8001 * Jumbo 32-bit instance field get. 8002 * 8003 * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo, 8004 * iget-char/jumbo, iget-short/jumbo 8005 */ 8006 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8007 FETCH(r1, 1) @ r1<- aaaa (lo) 8008 FETCH(r2, 2) @ r2<- AAAA (hi) 8009 FETCH(r0, 4) @ r0<- CCCC 8010 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8011 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8012 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8013 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8014 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8015 cmp r0, #0 @ is resolved entry null? 8016 bne .LOP_IGET_BOOLEAN_JUMBO_finish @ no, already resolved 80178: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8018 EXPORT_PC() @ resolve() could throw 8019 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8020 bl dvmResolveInstField @ r0<- resolved InstField ptr 8021 b .LOP_IGET_BOOLEAN_JUMBO_resolved @ resolved, continue 8022 8023 8024/* ------------------------------ */ 8025 .balign 64 8026.L_OP_IGET_BYTE_JUMBO: /* 0x10a */ 8027/* File: armv5te/OP_IGET_BYTE_JUMBO.S */ 8028@include "armv5te/OP_IGET_JUMBO.S" { "load":"ldrsb", "sqnum":"2" } 8029/* File: armv5te/OP_IGET_JUMBO.S */ 8030 /* 8031 * Jumbo 32-bit instance field get. 8032 * 8033 * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo, 8034 * iget-char/jumbo, iget-short/jumbo 8035 */ 8036 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8037 FETCH(r1, 1) @ r1<- aaaa (lo) 8038 FETCH(r2, 2) @ r2<- AAAA (hi) 8039 FETCH(r0, 4) @ r0<- CCCC 8040 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8041 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8042 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8043 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8044 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8045 cmp r0, #0 @ is resolved entry null? 8046 bne .LOP_IGET_BYTE_JUMBO_finish @ no, already resolved 80478: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8048 EXPORT_PC() @ resolve() could throw 8049 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8050 bl dvmResolveInstField @ r0<- resolved InstField ptr 8051 b .LOP_IGET_BYTE_JUMBO_resolved @ resolved, continue 8052 8053 8054/* ------------------------------ */ 8055 .balign 64 8056.L_OP_IGET_CHAR_JUMBO: /* 0x10b */ 8057/* File: armv5te/OP_IGET_CHAR_JUMBO.S */ 8058@include "armv5te/OP_IGET_JUMBO.S" { "load":"ldrh", "sqnum":"3" } 8059/* File: armv5te/OP_IGET_JUMBO.S */ 8060 /* 8061 * Jumbo 32-bit instance field get. 8062 * 8063 * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo, 8064 * iget-char/jumbo, iget-short/jumbo 8065 */ 8066 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8067 FETCH(r1, 1) @ r1<- aaaa (lo) 8068 FETCH(r2, 2) @ r2<- AAAA (hi) 8069 FETCH(r0, 4) @ r0<- CCCC 8070 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8071 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8072 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8073 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8074 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8075 cmp r0, #0 @ is resolved entry null? 8076 bne .LOP_IGET_CHAR_JUMBO_finish @ no, already resolved 80778: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8078 EXPORT_PC() @ resolve() could throw 8079 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8080 bl dvmResolveInstField @ r0<- resolved InstField ptr 8081 b .LOP_IGET_CHAR_JUMBO_resolved @ resolved, continue 8082 8083 8084/* ------------------------------ */ 8085 .balign 64 8086.L_OP_IGET_SHORT_JUMBO: /* 0x10c */ 8087/* File: armv5te/OP_IGET_SHORT_JUMBO.S */ 8088@include "armv5te/OP_IGET_JUMBO.S" { "load":"ldrsh", "sqnum":"4" } 8089/* File: armv5te/OP_IGET_JUMBO.S */ 8090 /* 8091 * Jumbo 32-bit instance field get. 8092 * 8093 * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo, 8094 * iget-char/jumbo, iget-short/jumbo 8095 */ 8096 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8097 FETCH(r1, 1) @ r1<- aaaa (lo) 8098 FETCH(r2, 2) @ r2<- AAAA (hi) 8099 FETCH(r0, 4) @ r0<- CCCC 8100 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8101 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8102 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8103 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8104 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8105 cmp r0, #0 @ is resolved entry null? 8106 bne .LOP_IGET_SHORT_JUMBO_finish @ no, already resolved 81078: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8108 EXPORT_PC() @ resolve() could throw 8109 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8110 bl dvmResolveInstField @ r0<- resolved InstField ptr 8111 b .LOP_IGET_SHORT_JUMBO_resolved @ resolved, continue 8112 8113 8114/* ------------------------------ */ 8115 .balign 64 8116.L_OP_IPUT_JUMBO: /* 0x10d */ 8117/* File: armv5te/OP_IPUT_JUMBO.S */ 8118 /* 8119 * Jumbo 32-bit instance field put. 8120 * 8121 * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo, 8122 * iput-short/jumbo 8123 */ 8124 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8125 FETCH(r1, 1) @ r1<- aaaa (lo) 8126 FETCH(r2, 2) @ r2<- AAAA (hi) 8127 FETCH(r0, 4) @ r0<- CCCC 8128 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8129 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8130 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8131 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8132 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8133 cmp r0, #0 @ is resolved entry null? 8134 bne .LOP_IPUT_JUMBO_finish @ no, already resolved 81358: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8136 EXPORT_PC() @ resolve() could throw 8137 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8138 bl dvmResolveInstField @ r0<- resolved InstField ptr 8139 b .LOP_IPUT_JUMBO_resolved @ resolved, continue 8140 8141/* ------------------------------ */ 8142 .balign 64 8143.L_OP_IPUT_WIDE_JUMBO: /* 0x10e */ 8144/* File: armv5te/OP_IPUT_WIDE_JUMBO.S */ 8145 /* iput-wide/jumbo vBBBB, vCCCC, field@AAAAAAAA */ 8146 FETCH(r1, 1) @ r1<- aaaa (lo) 8147 FETCH(r2, 2) @ r2<- AAAA (hi) 8148 FETCH(r0, 4) @ r0<- CCCC 8149 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8150 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8151 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 8152 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 8153 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8154 cmp r0, #0 @ is resolved entry null? 8155 bne .LOP_IPUT_WIDE_JUMBO_finish @ no, already resolved 81568: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8157 EXPORT_PC() @ resolve() could throw 8158 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8159 bl dvmResolveInstField @ r0<- resolved InstField ptr 8160 b .LOP_IPUT_WIDE_JUMBO_resolved @ resolved, continue 8161 8162/* ------------------------------ */ 8163 .balign 64 8164.L_OP_IPUT_OBJECT_JUMBO: /* 0x10f */ 8165/* File: armv5te/OP_IPUT_OBJECT_JUMBO.S */ 8166 /* 8167 * Jumbo 32-bit instance field put. 8168 */ 8169 /* iput-object/jumbo vBBBB, vCCCC, field@AAAAAAAA */ 8170 FETCH(r1, 1) @ r1<- aaaa (lo) 8171 FETCH(r2, 2) @ r2<- AAAA (hi) 8172 FETCH(r0, 4) @ r0<- CCCC 8173 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8174 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8175 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8176 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8177 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8178 cmp r0, #0 @ is resolved entry null? 8179 bne .LOP_IPUT_OBJECT_JUMBO_finish @ no, already resolved 81808: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8181 EXPORT_PC() @ resolve() could throw 8182 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8183 bl dvmResolveInstField @ r0<- resolved InstField ptr 8184 b .LOP_IPUT_OBJECT_JUMBO_resolved @ resolved, continue 8185 8186/* ------------------------------ */ 8187 .balign 64 8188.L_OP_IPUT_BOOLEAN_JUMBO: /* 0x110 */ 8189/* File: armv5te/OP_IPUT_BOOLEAN_JUMBO.S */ 8190@include "armv5te/OP_IPUT_JUMBO.S" { "store":"strb", "sqnum":"1" } 8191/* File: armv5te/OP_IPUT_JUMBO.S */ 8192 /* 8193 * Jumbo 32-bit instance field put. 8194 * 8195 * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo, 8196 * iput-short/jumbo 8197 */ 8198 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8199 FETCH(r1, 1) @ r1<- aaaa (lo) 8200 FETCH(r2, 2) @ r2<- AAAA (hi) 8201 FETCH(r0, 4) @ r0<- CCCC 8202 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8203 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8204 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8205 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8206 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8207 cmp r0, #0 @ is resolved entry null? 8208 bne .LOP_IPUT_BOOLEAN_JUMBO_finish @ no, already resolved 82098: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8210 EXPORT_PC() @ resolve() could throw 8211 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8212 bl dvmResolveInstField @ r0<- resolved InstField ptr 8213 b .LOP_IPUT_BOOLEAN_JUMBO_resolved @ resolved, continue 8214 8215 8216/* ------------------------------ */ 8217 .balign 64 8218.L_OP_IPUT_BYTE_JUMBO: /* 0x111 */ 8219/* File: armv5te/OP_IPUT_BYTE_JUMBO.S */ 8220@include "armv5te/OP_IPUT_JUMBO.S" { "store":"strb", "sqnum":"2" } 8221/* File: armv5te/OP_IPUT_JUMBO.S */ 8222 /* 8223 * Jumbo 32-bit instance field put. 8224 * 8225 * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo, 8226 * iput-short/jumbo 8227 */ 8228 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8229 FETCH(r1, 1) @ r1<- aaaa (lo) 8230 FETCH(r2, 2) @ r2<- AAAA (hi) 8231 FETCH(r0, 4) @ r0<- CCCC 8232 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8233 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8234 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8235 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8236 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8237 cmp r0, #0 @ is resolved entry null? 8238 bne .LOP_IPUT_BYTE_JUMBO_finish @ no, already resolved 82398: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8240 EXPORT_PC() @ resolve() could throw 8241 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8242 bl dvmResolveInstField @ r0<- resolved InstField ptr 8243 b .LOP_IPUT_BYTE_JUMBO_resolved @ resolved, continue 8244 8245 8246/* ------------------------------ */ 8247 .balign 64 8248.L_OP_IPUT_CHAR_JUMBO: /* 0x112 */ 8249/* File: armv5te/OP_IPUT_CHAR_JUMBO.S */ 8250@include "armv5te/OP_IPUT_JUMBO.S" { "store":"strh", "sqnum":"3" } 8251/* File: armv5te/OP_IPUT_JUMBO.S */ 8252 /* 8253 * Jumbo 32-bit instance field put. 8254 * 8255 * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo, 8256 * iput-short/jumbo 8257 */ 8258 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8259 FETCH(r1, 1) @ r1<- aaaa (lo) 8260 FETCH(r2, 2) @ r2<- AAAA (hi) 8261 FETCH(r0, 4) @ r0<- CCCC 8262 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8263 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8264 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8265 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8266 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8267 cmp r0, #0 @ is resolved entry null? 8268 bne .LOP_IPUT_CHAR_JUMBO_finish @ no, already resolved 82698: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8270 EXPORT_PC() @ resolve() could throw 8271 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8272 bl dvmResolveInstField @ r0<- resolved InstField ptr 8273 b .LOP_IPUT_CHAR_JUMBO_resolved @ resolved, continue 8274 8275 8276/* ------------------------------ */ 8277 .balign 64 8278.L_OP_IPUT_SHORT_JUMBO: /* 0x113 */ 8279/* File: armv5te/OP_IPUT_SHORT_JUMBO.S */ 8280@include "armv5te/OP_IPUT_JUMBO.S" { "store":"strh", "sqnum":"4" } 8281/* File: armv5te/OP_IPUT_JUMBO.S */ 8282 /* 8283 * Jumbo 32-bit instance field put. 8284 * 8285 * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo, 8286 * iput-short/jumbo 8287 */ 8288 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8289 FETCH(r1, 1) @ r1<- aaaa (lo) 8290 FETCH(r2, 2) @ r2<- AAAA (hi) 8291 FETCH(r0, 4) @ r0<- CCCC 8292 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8293 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8294 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8295 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8296 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8297 cmp r0, #0 @ is resolved entry null? 8298 bne .LOP_IPUT_SHORT_JUMBO_finish @ no, already resolved 82998: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8300 EXPORT_PC() @ resolve() could throw 8301 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8302 bl dvmResolveInstField @ r0<- resolved InstField ptr 8303 b .LOP_IPUT_SHORT_JUMBO_resolved @ resolved, continue 8304 8305 8306/* ------------------------------ */ 8307 .balign 64 8308.L_OP_SGET_JUMBO: /* 0x114 */ 8309/* File: armv5te/OP_SGET_JUMBO.S */ 8310 /* 8311 * Jumbo 32-bit SGET handler. 8312 * 8313 * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo, 8314 * sget-char/jumbo, sget-short/jumbo 8315 */ 8316 /* exop vBBBB, field@AAAAAAAA */ 8317 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8318 FETCH(r0, 1) @ r0<- aaaa (lo) 8319 FETCH(r1, 2) @ r1<- AAAA (hi) 8320 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8321 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8322 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8323 cmp r0, #0 @ is resolved entry null? 8324 beq .LOP_SGET_JUMBO_resolve @ yes, do resolve 8325.LOP_SGET_JUMBO_finish: @ field ptr in r0 8326 ldr r1, [r0, #offStaticField_value] @ r1<- field value 8327 @ no-op @ acquiring load 8328 FETCH(r2, 3) @ r2<- BBBB 8329 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8330 SET_VREG(r1, r2) @ fp[BBBB]<- r1 8331 GET_INST_OPCODE(ip) @ extract opcode from rINST 8332 GOTO_OPCODE(ip) @ jump to next instruction 8333 8334/* ------------------------------ */ 8335 .balign 64 8336.L_OP_SGET_WIDE_JUMBO: /* 0x115 */ 8337/* File: armv5te/OP_SGET_WIDE_JUMBO.S */ 8338 /* 8339 * Jumbo 64-bit SGET handler. 8340 */ 8341 /* sget-wide/jumbo vBBBB, field@AAAAAAAA */ 8342 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8343 FETCH(r0, 1) @ r0<- aaaa (lo) 8344 FETCH(r1, 2) @ r1<- AAAA (hi) 8345 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8346 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8347 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8348 cmp r0, #0 @ is resolved entry null? 8349 beq .LOP_SGET_WIDE_JUMBO_resolve @ yes, do resolve 8350.LOP_SGET_WIDE_JUMBO_finish: 8351 FETCH(r9, 3) @ r9<- BBBB 8352 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 8353 add r9, rFP, r9, lsl #2 @ r9<- &fp[BBBB] 8354 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8355 stmia r9, {r0-r1} @ vBBBB/vBBBB+1<- r0/r1 8356 GET_INST_OPCODE(ip) @ extract opcode from rINST 8357 GOTO_OPCODE(ip) @ jump to next instruction 8358 8359/* ------------------------------ */ 8360 .balign 64 8361.L_OP_SGET_OBJECT_JUMBO: /* 0x116 */ 8362/* File: armv5te/OP_SGET_OBJECT_JUMBO.S */ 8363/* File: armv5te/OP_SGET_JUMBO.S */ 8364 /* 8365 * Jumbo 32-bit SGET handler. 8366 * 8367 * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo, 8368 * sget-char/jumbo, sget-short/jumbo 8369 */ 8370 /* exop vBBBB, field@AAAAAAAA */ 8371 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8372 FETCH(r0, 1) @ r0<- aaaa (lo) 8373 FETCH(r1, 2) @ r1<- AAAA (hi) 8374 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8375 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8376 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8377 cmp r0, #0 @ is resolved entry null? 8378 beq .LOP_SGET_OBJECT_JUMBO_resolve @ yes, do resolve 8379.LOP_SGET_OBJECT_JUMBO_finish: @ field ptr in r0 8380 ldr r1, [r0, #offStaticField_value] @ r1<- field value 8381 @ no-op @ acquiring load 8382 FETCH(r2, 3) @ r2<- BBBB 8383 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8384 SET_VREG(r1, r2) @ fp[BBBB]<- r1 8385 GET_INST_OPCODE(ip) @ extract opcode from rINST 8386 GOTO_OPCODE(ip) @ jump to next instruction 8387 8388 8389/* ------------------------------ */ 8390 .balign 64 8391.L_OP_SGET_BOOLEAN_JUMBO: /* 0x117 */ 8392/* File: armv5te/OP_SGET_BOOLEAN_JUMBO.S */ 8393/* File: armv5te/OP_SGET_JUMBO.S */ 8394 /* 8395 * Jumbo 32-bit SGET handler. 8396 * 8397 * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo, 8398 * sget-char/jumbo, sget-short/jumbo 8399 */ 8400 /* exop vBBBB, field@AAAAAAAA */ 8401 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8402 FETCH(r0, 1) @ r0<- aaaa (lo) 8403 FETCH(r1, 2) @ r1<- AAAA (hi) 8404 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8405 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8406 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8407 cmp r0, #0 @ is resolved entry null? 8408 beq .LOP_SGET_BOOLEAN_JUMBO_resolve @ yes, do resolve 8409.LOP_SGET_BOOLEAN_JUMBO_finish: @ field ptr in r0 8410 ldr r1, [r0, #offStaticField_value] @ r1<- field value 8411 @ no-op @ acquiring load 8412 FETCH(r2, 3) @ r2<- BBBB 8413 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8414 SET_VREG(r1, r2) @ fp[BBBB]<- r1 8415 GET_INST_OPCODE(ip) @ extract opcode from rINST 8416 GOTO_OPCODE(ip) @ jump to next instruction 8417 8418 8419/* ------------------------------ */ 8420 .balign 64 8421.L_OP_SGET_BYTE_JUMBO: /* 0x118 */ 8422/* File: armv5te/OP_SGET_BYTE_JUMBO.S */ 8423/* File: armv5te/OP_SGET_JUMBO.S */ 8424 /* 8425 * Jumbo 32-bit SGET handler. 8426 * 8427 * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo, 8428 * sget-char/jumbo, sget-short/jumbo 8429 */ 8430 /* exop vBBBB, field@AAAAAAAA */ 8431 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8432 FETCH(r0, 1) @ r0<- aaaa (lo) 8433 FETCH(r1, 2) @ r1<- AAAA (hi) 8434 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8435 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8436 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8437 cmp r0, #0 @ is resolved entry null? 8438 beq .LOP_SGET_BYTE_JUMBO_resolve @ yes, do resolve 8439.LOP_SGET_BYTE_JUMBO_finish: @ field ptr in r0 8440 ldr r1, [r0, #offStaticField_value] @ r1<- field value 8441 @ no-op @ acquiring load 8442 FETCH(r2, 3) @ r2<- BBBB 8443 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8444 SET_VREG(r1, r2) @ fp[BBBB]<- r1 8445 GET_INST_OPCODE(ip) @ extract opcode from rINST 8446 GOTO_OPCODE(ip) @ jump to next instruction 8447 8448 8449/* ------------------------------ */ 8450 .balign 64 8451.L_OP_SGET_CHAR_JUMBO: /* 0x119 */ 8452/* File: armv5te/OP_SGET_CHAR_JUMBO.S */ 8453/* File: armv5te/OP_SGET_JUMBO.S */ 8454 /* 8455 * Jumbo 32-bit SGET handler. 8456 * 8457 * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo, 8458 * sget-char/jumbo, sget-short/jumbo 8459 */ 8460 /* exop vBBBB, field@AAAAAAAA */ 8461 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8462 FETCH(r0, 1) @ r0<- aaaa (lo) 8463 FETCH(r1, 2) @ r1<- AAAA (hi) 8464 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8465 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8466 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8467 cmp r0, #0 @ is resolved entry null? 8468 beq .LOP_SGET_CHAR_JUMBO_resolve @ yes, do resolve 8469.LOP_SGET_CHAR_JUMBO_finish: @ field ptr in r0 8470 ldr r1, [r0, #offStaticField_value] @ r1<- field value 8471 @ no-op @ acquiring load 8472 FETCH(r2, 3) @ r2<- BBBB 8473 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8474 SET_VREG(r1, r2) @ fp[BBBB]<- r1 8475 GET_INST_OPCODE(ip) @ extract opcode from rINST 8476 GOTO_OPCODE(ip) @ jump to next instruction 8477 8478 8479/* ------------------------------ */ 8480 .balign 64 8481.L_OP_SGET_SHORT_JUMBO: /* 0x11a */ 8482/* File: armv5te/OP_SGET_SHORT_JUMBO.S */ 8483/* File: armv5te/OP_SGET_JUMBO.S */ 8484 /* 8485 * Jumbo 32-bit SGET handler. 8486 * 8487 * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo, 8488 * sget-char/jumbo, sget-short/jumbo 8489 */ 8490 /* exop vBBBB, field@AAAAAAAA */ 8491 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8492 FETCH(r0, 1) @ r0<- aaaa (lo) 8493 FETCH(r1, 2) @ r1<- AAAA (hi) 8494 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8495 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8496 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8497 cmp r0, #0 @ is resolved entry null? 8498 beq .LOP_SGET_SHORT_JUMBO_resolve @ yes, do resolve 8499.LOP_SGET_SHORT_JUMBO_finish: @ field ptr in r0 8500 ldr r1, [r0, #offStaticField_value] @ r1<- field value 8501 @ no-op @ acquiring load 8502 FETCH(r2, 3) @ r2<- BBBB 8503 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8504 SET_VREG(r1, r2) @ fp[BBBB]<- r1 8505 GET_INST_OPCODE(ip) @ extract opcode from rINST 8506 GOTO_OPCODE(ip) @ jump to next instruction 8507 8508 8509/* ------------------------------ */ 8510 .balign 64 8511.L_OP_SPUT_JUMBO: /* 0x11b */ 8512/* File: armv5te/OP_SPUT_JUMBO.S */ 8513 /* 8514 * Jumbo 32-bit SPUT handler. 8515 * 8516 * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo, 8517 * sput-short/jumbo 8518 */ 8519 /* exop vBBBB, field@AAAAAAAA */ 8520 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8521 FETCH(r0, 1) @ r0<- aaaa (lo) 8522 FETCH(r1, 2) @ r1<- AAAA (hi) 8523 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8524 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8525 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8526 cmp r0, #0 @ is resolved entry null? 8527 beq .LOP_SPUT_JUMBO_resolve @ yes, do resolve 8528.LOP_SPUT_JUMBO_finish: @ field ptr in r0 8529 FETCH(r2, 3) @ r2<- BBBB 8530 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8531 GET_VREG(r1, r2) @ r1<- fp[BBBB] 8532 GET_INST_OPCODE(ip) @ extract opcode from rINST 8533 @ no-op @ releasing store 8534 str r1, [r0, #offStaticField_value] @ field<- vBBBB 8535 GOTO_OPCODE(ip) @ jump to next instruction 8536 8537/* ------------------------------ */ 8538 .balign 64 8539.L_OP_SPUT_WIDE_JUMBO: /* 0x11c */ 8540/* File: armv5te/OP_SPUT_WIDE_JUMBO.S */ 8541 /* 8542 * Jumbo 64-bit SPUT handler. 8543 */ 8544 /* sput-wide/jumbo vBBBB, field@AAAAAAAA */ 8545 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 8546 FETCH(r1, 1) @ r1<- aaaa (lo) 8547 FETCH(r2, 2) @ r2<- AAAA (hi) 8548 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 8549 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8550 FETCH(r9, 3) @ r9<- BBBB 8551 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 8552 add r9, rFP, r9, lsl #2 @ r9<- &fp[BBBB] 8553 cmp r2, #0 @ is resolved entry null? 8554 beq .LOP_SPUT_WIDE_JUMBO_resolve @ yes, do resolve 8555.LOP_SPUT_WIDE_JUMBO_finish: @ field ptr in r2, BBBB in r9 8556 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8557 ldmia r9, {r0-r1} @ r0/r1<- vBBBB/vBBBB+1 8558 GET_INST_OPCODE(r10) @ extract opcode from rINST 8559 strd r0, [r2, #offStaticField_value] @ field<- vBBBB/vBBBB+1 8560 GOTO_OPCODE(r10) @ jump to next instruction 8561 8562/* ------------------------------ */ 8563 .balign 64 8564.L_OP_SPUT_OBJECT_JUMBO: /* 0x11d */ 8565/* File: armv5te/OP_SPUT_OBJECT_JUMBO.S */ 8566 /* 8567 * Jumbo 32-bit SPUT handler for objects 8568 */ 8569 /* sput-object/jumbo vBBBB, field@AAAAAAAA */ 8570 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8571 FETCH(r0, 1) @ r0<- aaaa (lo) 8572 FETCH(r1, 2) @ r1<- AAAA (hi) 8573 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8574 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8575 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8576 cmp r0, #0 @ is resolved entry null? 8577 bne .LOP_SPUT_OBJECT_JUMBO_finish @ no, continue 8578 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 8579 EXPORT_PC() @ resolve() could throw, so export now 8580 ldr r0, [r9, #offMethod_clazz] @ r0<- method->clazz 8581 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8582 cmp r0, #0 @ success? 8583 bne .LOP_SPUT_OBJECT_JUMBO_finish @ yes, finish 8584 b common_exceptionThrown @ no, handle exception 8585 8586/* ------------------------------ */ 8587 .balign 64 8588.L_OP_SPUT_BOOLEAN_JUMBO: /* 0x11e */ 8589/* File: armv5te/OP_SPUT_BOOLEAN_JUMBO.S */ 8590/* File: armv5te/OP_SPUT_JUMBO.S */ 8591 /* 8592 * Jumbo 32-bit SPUT handler. 8593 * 8594 * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo, 8595 * sput-short/jumbo 8596 */ 8597 /* exop vBBBB, field@AAAAAAAA */ 8598 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8599 FETCH(r0, 1) @ r0<- aaaa (lo) 8600 FETCH(r1, 2) @ r1<- AAAA (hi) 8601 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8602 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8603 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8604 cmp r0, #0 @ is resolved entry null? 8605 beq .LOP_SPUT_BOOLEAN_JUMBO_resolve @ yes, do resolve 8606.LOP_SPUT_BOOLEAN_JUMBO_finish: @ field ptr in r0 8607 FETCH(r2, 3) @ r2<- BBBB 8608 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8609 GET_VREG(r1, r2) @ r1<- fp[BBBB] 8610 GET_INST_OPCODE(ip) @ extract opcode from rINST 8611 @ no-op @ releasing store 8612 str r1, [r0, #offStaticField_value] @ field<- vBBBB 8613 GOTO_OPCODE(ip) @ jump to next instruction 8614 8615 8616/* ------------------------------ */ 8617 .balign 64 8618.L_OP_SPUT_BYTE_JUMBO: /* 0x11f */ 8619/* File: armv5te/OP_SPUT_BYTE_JUMBO.S */ 8620/* File: armv5te/OP_SPUT_JUMBO.S */ 8621 /* 8622 * Jumbo 32-bit SPUT handler. 8623 * 8624 * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo, 8625 * sput-short/jumbo 8626 */ 8627 /* exop vBBBB, field@AAAAAAAA */ 8628 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8629 FETCH(r0, 1) @ r0<- aaaa (lo) 8630 FETCH(r1, 2) @ r1<- AAAA (hi) 8631 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8632 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8633 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8634 cmp r0, #0 @ is resolved entry null? 8635 beq .LOP_SPUT_BYTE_JUMBO_resolve @ yes, do resolve 8636.LOP_SPUT_BYTE_JUMBO_finish: @ field ptr in r0 8637 FETCH(r2, 3) @ r2<- BBBB 8638 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8639 GET_VREG(r1, r2) @ r1<- fp[BBBB] 8640 GET_INST_OPCODE(ip) @ extract opcode from rINST 8641 @ no-op @ releasing store 8642 str r1, [r0, #offStaticField_value] @ field<- vBBBB 8643 GOTO_OPCODE(ip) @ jump to next instruction 8644 8645 8646/* ------------------------------ */ 8647 .balign 64 8648.L_OP_SPUT_CHAR_JUMBO: /* 0x120 */ 8649/* File: armv5te/OP_SPUT_CHAR_JUMBO.S */ 8650/* File: armv5te/OP_SPUT_JUMBO.S */ 8651 /* 8652 * Jumbo 32-bit SPUT handler. 8653 * 8654 * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo, 8655 * sput-short/jumbo 8656 */ 8657 /* exop vBBBB, field@AAAAAAAA */ 8658 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8659 FETCH(r0, 1) @ r0<- aaaa (lo) 8660 FETCH(r1, 2) @ r1<- AAAA (hi) 8661 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8662 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8663 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8664 cmp r0, #0 @ is resolved entry null? 8665 beq .LOP_SPUT_CHAR_JUMBO_resolve @ yes, do resolve 8666.LOP_SPUT_CHAR_JUMBO_finish: @ field ptr in r0 8667 FETCH(r2, 3) @ r2<- BBBB 8668 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8669 GET_VREG(r1, r2) @ r1<- fp[BBBB] 8670 GET_INST_OPCODE(ip) @ extract opcode from rINST 8671 @ no-op @ releasing store 8672 str r1, [r0, #offStaticField_value] @ field<- vBBBB 8673 GOTO_OPCODE(ip) @ jump to next instruction 8674 8675 8676/* ------------------------------ */ 8677 .balign 64 8678.L_OP_SPUT_SHORT_JUMBO: /* 0x121 */ 8679/* File: armv5te/OP_SPUT_SHORT_JUMBO.S */ 8680/* File: armv5te/OP_SPUT_JUMBO.S */ 8681 /* 8682 * Jumbo 32-bit SPUT handler. 8683 * 8684 * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo, 8685 * sput-short/jumbo 8686 */ 8687 /* exop vBBBB, field@AAAAAAAA */ 8688 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8689 FETCH(r0, 1) @ r0<- aaaa (lo) 8690 FETCH(r1, 2) @ r1<- AAAA (hi) 8691 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8692 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8693 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8694 cmp r0, #0 @ is resolved entry null? 8695 beq .LOP_SPUT_SHORT_JUMBO_resolve @ yes, do resolve 8696.LOP_SPUT_SHORT_JUMBO_finish: @ field ptr in r0 8697 FETCH(r2, 3) @ r2<- BBBB 8698 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8699 GET_VREG(r1, r2) @ r1<- fp[BBBB] 8700 GET_INST_OPCODE(ip) @ extract opcode from rINST 8701 @ no-op @ releasing store 8702 str r1, [r0, #offStaticField_value] @ field<- vBBBB 8703 GOTO_OPCODE(ip) @ jump to next instruction 8704 8705 8706/* ------------------------------ */ 8707 .balign 64 8708.L_OP_INVOKE_VIRTUAL_JUMBO: /* 0x122 */ 8709/* File: armv5te/OP_INVOKE_VIRTUAL_JUMBO.S */ 8710 /* 8711 * Handle a virtual method call. 8712 */ 8713 /* invoke-virtual/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */ 8714 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 8715 FETCH(r0, 1) @ r1<- aaaa (lo) 8716 FETCH(r1, 2) @ r1<- AAAA (hi) 8717 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 8718 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8719 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 8720 cmp r0, #0 @ already resolved? 8721 EXPORT_PC() @ must export for invoke 8722 bne .LOP_INVOKE_VIRTUAL_JUMBO_continue @ yes, continue on 8723 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8724 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8725 mov r2, #METHOD_VIRTUAL @ resolver method type 8726 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8727 cmp r0, #0 @ got null? 8728 bne .LOP_INVOKE_VIRTUAL_JUMBO_continue @ no, continue 8729 b common_exceptionThrown @ yes, handle exception 8730 8731/* ------------------------------ */ 8732 .balign 64 8733.L_OP_INVOKE_SUPER_JUMBO: /* 0x123 */ 8734/* File: armv5te/OP_INVOKE_SUPER_JUMBO.S */ 8735 /* 8736 * Handle a "super" method call. 8737 */ 8738 /* invoke-super/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */ 8739 FETCH(r10, 4) @ r10<- CCCC 8740 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 8741 FETCH(r0, 1) @ r1<- aaaa (lo) 8742 FETCH(r1, 2) @ r1<- AAAA (hi) 8743 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 8744 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8745 GET_VREG(r2, r10) @ r2<- "this" ptr 8746 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 8747 cmp r2, #0 @ null "this"? 8748 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 8749 beq common_errNullObject @ null "this", throw exception 8750 cmp r0, #0 @ already resolved? 8751 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 8752 EXPORT_PC() @ must export for invoke 8753 bne .LOP_INVOKE_SUPER_JUMBO_continue @ resolved, continue on 8754 b .LOP_INVOKE_SUPER_JUMBO_resolve @ do resolve now 8755 8756/* ------------------------------ */ 8757 .balign 64 8758.L_OP_INVOKE_DIRECT_JUMBO: /* 0x124 */ 8759/* File: armv5te/OP_INVOKE_DIRECT_JUMBO.S */ 8760 /* 8761 * Handle a direct method call. 8762 * 8763 * (We could defer the "is 'this' pointer null" test to the common 8764 * method invocation code, and use a flag to indicate that static 8765 * calls don't count. If we do this as part of copying the arguments 8766 * out we could avoiding loading the first arg twice.) 8767 * 8768 */ 8769 /* invoke-direct/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */ 8770 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 8771 FETCH(r0, 1) @ r1<- aaaa (lo) 8772 FETCH(r1, 2) @ r1<- AAAA (hi) 8773 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 8774 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8775 FETCH(r10, 4) @ r10<- CCCC 8776 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 8777 cmp r0, #0 @ already resolved? 8778 EXPORT_PC() @ must export for invoke 8779 GET_VREG(r2, r10) @ r2<- "this" ptr 8780 beq .LOP_INVOKE_DIRECT_JUMBO_resolve @ not resolved, do it now 8781.LOP_INVOKE_DIRECT_JUMBO_finish: 8782 cmp r2, #0 @ null "this" ref? 8783 bne common_invokeMethodJumbo @ no, continue on 8784 b common_errNullObject @ yes, throw exception 8785 8786/* ------------------------------ */ 8787 .balign 64 8788.L_OP_INVOKE_STATIC_JUMBO: /* 0x125 */ 8789/* File: armv5te/OP_INVOKE_STATIC_JUMBO.S */ 8790 /* 8791 * Handle a static method call. 8792 */ 8793 /* invoke-static/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */ 8794 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 8795 FETCH(r0, 1) @ r1<- aaaa (lo) 8796 FETCH(r1, 2) @ r1<- AAAA (hi) 8797 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 8798 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8799 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 8800 cmp r0, #0 @ already resolved? 8801 EXPORT_PC() @ must export for invoke 8802 bne common_invokeMethodJumbo @ yes, continue on 88030: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8804 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8805 mov r2, #METHOD_STATIC @ resolver method type 8806 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8807 cmp r0, #0 @ got null? 8808 bne common_invokeMethodJumbo @ no, continue 8809 b common_exceptionThrown @ yes, handle exception 8810 8811/* ------------------------------ */ 8812 .balign 64 8813.L_OP_INVOKE_INTERFACE_JUMBO: /* 0x126 */ 8814/* File: armv5te/OP_INVOKE_INTERFACE_JUMBO.S */ 8815 /* 8816 * Handle an interface method call. 8817 */ 8818 /* invoke-interface/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */ 8819 FETCH(r2, 4) @ r2<- CCCC 8820 FETCH(r0, 1) @ r0<- aaaa (lo) 8821 FETCH(r1, 2) @ r1<- AAAA (hi) 8822 EXPORT_PC() @ must export for invoke 8823 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8824 GET_VREG(r0, r2) @ r0<- first arg ("this") 8825 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 8826 cmp r0, #0 @ null obj? 8827 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 8828 beq common_errNullObject @ yes, fail 8829 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 8830 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 8831 cmp r0, #0 @ failed? 8832 beq common_exceptionThrown @ yes, handle exception 8833 b common_invokeMethodJumbo @ jump to common handler 8834 8835/* ------------------------------ */ 8836 .balign 64 8837.L_OP_UNUSED_27FF: /* 0x127 */ 8838/* File: armv5te/OP_UNUSED_27FF.S */ 8839/* File: armv5te/unused.S */ 8840 bl common_abort 8841 8842 8843/* ------------------------------ */ 8844 .balign 64 8845.L_OP_UNUSED_28FF: /* 0x128 */ 8846/* File: armv5te/OP_UNUSED_28FF.S */ 8847/* File: armv5te/unused.S */ 8848 bl common_abort 8849 8850 8851/* ------------------------------ */ 8852 .balign 64 8853.L_OP_UNUSED_29FF: /* 0x129 */ 8854/* File: armv5te/OP_UNUSED_29FF.S */ 8855/* File: armv5te/unused.S */ 8856 bl common_abort 8857 8858 8859/* ------------------------------ */ 8860 .balign 64 8861.L_OP_UNUSED_2AFF: /* 0x12a */ 8862/* File: armv5te/OP_UNUSED_2AFF.S */ 8863/* File: armv5te/unused.S */ 8864 bl common_abort 8865 8866 8867/* ------------------------------ */ 8868 .balign 64 8869.L_OP_UNUSED_2BFF: /* 0x12b */ 8870/* File: armv5te/OP_UNUSED_2BFF.S */ 8871/* File: armv5te/unused.S */ 8872 bl common_abort 8873 8874 8875/* ------------------------------ */ 8876 .balign 64 8877.L_OP_UNUSED_2CFF: /* 0x12c */ 8878/* File: armv5te/OP_UNUSED_2CFF.S */ 8879/* File: armv5te/unused.S */ 8880 bl common_abort 8881 8882 8883/* ------------------------------ */ 8884 .balign 64 8885.L_OP_UNUSED_2DFF: /* 0x12d */ 8886/* File: armv5te/OP_UNUSED_2DFF.S */ 8887/* File: armv5te/unused.S */ 8888 bl common_abort 8889 8890 8891/* ------------------------------ */ 8892 .balign 64 8893.L_OP_UNUSED_2EFF: /* 0x12e */ 8894/* File: armv5te/OP_UNUSED_2EFF.S */ 8895/* File: armv5te/unused.S */ 8896 bl common_abort 8897 8898 8899/* ------------------------------ */ 8900 .balign 64 8901.L_OP_UNUSED_2FFF: /* 0x12f */ 8902/* File: armv5te/OP_UNUSED_2FFF.S */ 8903/* File: armv5te/unused.S */ 8904 bl common_abort 8905 8906 8907/* ------------------------------ */ 8908 .balign 64 8909.L_OP_UNUSED_30FF: /* 0x130 */ 8910/* File: armv5te/OP_UNUSED_30FF.S */ 8911/* File: armv5te/unused.S */ 8912 bl common_abort 8913 8914 8915/* ------------------------------ */ 8916 .balign 64 8917.L_OP_UNUSED_31FF: /* 0x131 */ 8918/* File: armv5te/OP_UNUSED_31FF.S */ 8919/* File: armv5te/unused.S */ 8920 bl common_abort 8921 8922 8923/* ------------------------------ */ 8924 .balign 64 8925.L_OP_UNUSED_32FF: /* 0x132 */ 8926/* File: armv5te/OP_UNUSED_32FF.S */ 8927/* File: armv5te/unused.S */ 8928 bl common_abort 8929 8930 8931/* ------------------------------ */ 8932 .balign 64 8933.L_OP_UNUSED_33FF: /* 0x133 */ 8934/* File: armv5te/OP_UNUSED_33FF.S */ 8935/* File: armv5te/unused.S */ 8936 bl common_abort 8937 8938 8939/* ------------------------------ */ 8940 .balign 64 8941.L_OP_UNUSED_34FF: /* 0x134 */ 8942/* File: armv5te/OP_UNUSED_34FF.S */ 8943/* File: armv5te/unused.S */ 8944 bl common_abort 8945 8946 8947/* ------------------------------ */ 8948 .balign 64 8949.L_OP_UNUSED_35FF: /* 0x135 */ 8950/* File: armv5te/OP_UNUSED_35FF.S */ 8951/* File: armv5te/unused.S */ 8952 bl common_abort 8953 8954 8955/* ------------------------------ */ 8956 .balign 64 8957.L_OP_UNUSED_36FF: /* 0x136 */ 8958/* File: armv5te/OP_UNUSED_36FF.S */ 8959/* File: armv5te/unused.S */ 8960 bl common_abort 8961 8962 8963/* ------------------------------ */ 8964 .balign 64 8965.L_OP_UNUSED_37FF: /* 0x137 */ 8966/* File: armv5te/OP_UNUSED_37FF.S */ 8967/* File: armv5te/unused.S */ 8968 bl common_abort 8969 8970 8971/* ------------------------------ */ 8972 .balign 64 8973.L_OP_UNUSED_38FF: /* 0x138 */ 8974/* File: armv5te/OP_UNUSED_38FF.S */ 8975/* File: armv5te/unused.S */ 8976 bl common_abort 8977 8978 8979/* ------------------------------ */ 8980 .balign 64 8981.L_OP_UNUSED_39FF: /* 0x139 */ 8982/* File: armv5te/OP_UNUSED_39FF.S */ 8983/* File: armv5te/unused.S */ 8984 bl common_abort 8985 8986 8987/* ------------------------------ */ 8988 .balign 64 8989.L_OP_UNUSED_3AFF: /* 0x13a */ 8990/* File: armv5te/OP_UNUSED_3AFF.S */ 8991/* File: armv5te/unused.S */ 8992 bl common_abort 8993 8994 8995/* ------------------------------ */ 8996 .balign 64 8997.L_OP_UNUSED_3BFF: /* 0x13b */ 8998/* File: armv5te/OP_UNUSED_3BFF.S */ 8999/* File: armv5te/unused.S */ 9000 bl common_abort 9001 9002 9003/* ------------------------------ */ 9004 .balign 64 9005.L_OP_UNUSED_3CFF: /* 0x13c */ 9006/* File: armv5te/OP_UNUSED_3CFF.S */ 9007/* File: armv5te/unused.S */ 9008 bl common_abort 9009 9010 9011/* ------------------------------ */ 9012 .balign 64 9013.L_OP_UNUSED_3DFF: /* 0x13d */ 9014/* File: armv5te/OP_UNUSED_3DFF.S */ 9015/* File: armv5te/unused.S */ 9016 bl common_abort 9017 9018 9019/* ------------------------------ */ 9020 .balign 64 9021.L_OP_UNUSED_3EFF: /* 0x13e */ 9022/* File: armv5te/OP_UNUSED_3EFF.S */ 9023/* File: armv5te/unused.S */ 9024 bl common_abort 9025 9026 9027/* ------------------------------ */ 9028 .balign 64 9029.L_OP_UNUSED_3FFF: /* 0x13f */ 9030/* File: armv5te/OP_UNUSED_3FFF.S */ 9031/* File: armv5te/unused.S */ 9032 bl common_abort 9033 9034 9035/* ------------------------------ */ 9036 .balign 64 9037.L_OP_UNUSED_40FF: /* 0x140 */ 9038/* File: armv5te/OP_UNUSED_40FF.S */ 9039/* File: armv5te/unused.S */ 9040 bl common_abort 9041 9042 9043/* ------------------------------ */ 9044 .balign 64 9045.L_OP_UNUSED_41FF: /* 0x141 */ 9046/* File: armv5te/OP_UNUSED_41FF.S */ 9047/* File: armv5te/unused.S */ 9048 bl common_abort 9049 9050 9051/* ------------------------------ */ 9052 .balign 64 9053.L_OP_UNUSED_42FF: /* 0x142 */ 9054/* File: armv5te/OP_UNUSED_42FF.S */ 9055/* File: armv5te/unused.S */ 9056 bl common_abort 9057 9058 9059/* ------------------------------ */ 9060 .balign 64 9061.L_OP_UNUSED_43FF: /* 0x143 */ 9062/* File: armv5te/OP_UNUSED_43FF.S */ 9063/* File: armv5te/unused.S */ 9064 bl common_abort 9065 9066 9067/* ------------------------------ */ 9068 .balign 64 9069.L_OP_UNUSED_44FF: /* 0x144 */ 9070/* File: armv5te/OP_UNUSED_44FF.S */ 9071/* File: armv5te/unused.S */ 9072 bl common_abort 9073 9074 9075/* ------------------------------ */ 9076 .balign 64 9077.L_OP_UNUSED_45FF: /* 0x145 */ 9078/* File: armv5te/OP_UNUSED_45FF.S */ 9079/* File: armv5te/unused.S */ 9080 bl common_abort 9081 9082 9083/* ------------------------------ */ 9084 .balign 64 9085.L_OP_UNUSED_46FF: /* 0x146 */ 9086/* File: armv5te/OP_UNUSED_46FF.S */ 9087/* File: armv5te/unused.S */ 9088 bl common_abort 9089 9090 9091/* ------------------------------ */ 9092 .balign 64 9093.L_OP_UNUSED_47FF: /* 0x147 */ 9094/* File: armv5te/OP_UNUSED_47FF.S */ 9095/* File: armv5te/unused.S */ 9096 bl common_abort 9097 9098 9099/* ------------------------------ */ 9100 .balign 64 9101.L_OP_UNUSED_48FF: /* 0x148 */ 9102/* File: armv5te/OP_UNUSED_48FF.S */ 9103/* File: armv5te/unused.S */ 9104 bl common_abort 9105 9106 9107/* ------------------------------ */ 9108 .balign 64 9109.L_OP_UNUSED_49FF: /* 0x149 */ 9110/* File: armv5te/OP_UNUSED_49FF.S */ 9111/* File: armv5te/unused.S */ 9112 bl common_abort 9113 9114 9115/* ------------------------------ */ 9116 .balign 64 9117.L_OP_UNUSED_4AFF: /* 0x14a */ 9118/* File: armv5te/OP_UNUSED_4AFF.S */ 9119/* File: armv5te/unused.S */ 9120 bl common_abort 9121 9122 9123/* ------------------------------ */ 9124 .balign 64 9125.L_OP_UNUSED_4BFF: /* 0x14b */ 9126/* File: armv5te/OP_UNUSED_4BFF.S */ 9127/* File: armv5te/unused.S */ 9128 bl common_abort 9129 9130 9131/* ------------------------------ */ 9132 .balign 64 9133.L_OP_UNUSED_4CFF: /* 0x14c */ 9134/* File: armv5te/OP_UNUSED_4CFF.S */ 9135/* File: armv5te/unused.S */ 9136 bl common_abort 9137 9138 9139/* ------------------------------ */ 9140 .balign 64 9141.L_OP_UNUSED_4DFF: /* 0x14d */ 9142/* File: armv5te/OP_UNUSED_4DFF.S */ 9143/* File: armv5te/unused.S */ 9144 bl common_abort 9145 9146 9147/* ------------------------------ */ 9148 .balign 64 9149.L_OP_UNUSED_4EFF: /* 0x14e */ 9150/* File: armv5te/OP_UNUSED_4EFF.S */ 9151/* File: armv5te/unused.S */ 9152 bl common_abort 9153 9154 9155/* ------------------------------ */ 9156 .balign 64 9157.L_OP_UNUSED_4FFF: /* 0x14f */ 9158/* File: armv5te/OP_UNUSED_4FFF.S */ 9159/* File: armv5te/unused.S */ 9160 bl common_abort 9161 9162 9163/* ------------------------------ */ 9164 .balign 64 9165.L_OP_UNUSED_50FF: /* 0x150 */ 9166/* File: armv5te/OP_UNUSED_50FF.S */ 9167/* File: armv5te/unused.S */ 9168 bl common_abort 9169 9170 9171/* ------------------------------ */ 9172 .balign 64 9173.L_OP_UNUSED_51FF: /* 0x151 */ 9174/* File: armv5te/OP_UNUSED_51FF.S */ 9175/* File: armv5te/unused.S */ 9176 bl common_abort 9177 9178 9179/* ------------------------------ */ 9180 .balign 64 9181.L_OP_UNUSED_52FF: /* 0x152 */ 9182/* File: armv5te/OP_UNUSED_52FF.S */ 9183/* File: armv5te/unused.S */ 9184 bl common_abort 9185 9186 9187/* ------------------------------ */ 9188 .balign 64 9189.L_OP_UNUSED_53FF: /* 0x153 */ 9190/* File: armv5te/OP_UNUSED_53FF.S */ 9191/* File: armv5te/unused.S */ 9192 bl common_abort 9193 9194 9195/* ------------------------------ */ 9196 .balign 64 9197.L_OP_UNUSED_54FF: /* 0x154 */ 9198/* File: armv5te/OP_UNUSED_54FF.S */ 9199/* File: armv5te/unused.S */ 9200 bl common_abort 9201 9202 9203/* ------------------------------ */ 9204 .balign 64 9205.L_OP_UNUSED_55FF: /* 0x155 */ 9206/* File: armv5te/OP_UNUSED_55FF.S */ 9207/* File: armv5te/unused.S */ 9208 bl common_abort 9209 9210 9211/* ------------------------------ */ 9212 .balign 64 9213.L_OP_UNUSED_56FF: /* 0x156 */ 9214/* File: armv5te/OP_UNUSED_56FF.S */ 9215/* File: armv5te/unused.S */ 9216 bl common_abort 9217 9218 9219/* ------------------------------ */ 9220 .balign 64 9221.L_OP_UNUSED_57FF: /* 0x157 */ 9222/* File: armv5te/OP_UNUSED_57FF.S */ 9223/* File: armv5te/unused.S */ 9224 bl common_abort 9225 9226 9227/* ------------------------------ */ 9228 .balign 64 9229.L_OP_UNUSED_58FF: /* 0x158 */ 9230/* File: armv5te/OP_UNUSED_58FF.S */ 9231/* File: armv5te/unused.S */ 9232 bl common_abort 9233 9234 9235/* ------------------------------ */ 9236 .balign 64 9237.L_OP_UNUSED_59FF: /* 0x159 */ 9238/* File: armv5te/OP_UNUSED_59FF.S */ 9239/* File: armv5te/unused.S */ 9240 bl common_abort 9241 9242 9243/* ------------------------------ */ 9244 .balign 64 9245.L_OP_UNUSED_5AFF: /* 0x15a */ 9246/* File: armv5te/OP_UNUSED_5AFF.S */ 9247/* File: armv5te/unused.S */ 9248 bl common_abort 9249 9250 9251/* ------------------------------ */ 9252 .balign 64 9253.L_OP_UNUSED_5BFF: /* 0x15b */ 9254/* File: armv5te/OP_UNUSED_5BFF.S */ 9255/* File: armv5te/unused.S */ 9256 bl common_abort 9257 9258 9259/* ------------------------------ */ 9260 .balign 64 9261.L_OP_UNUSED_5CFF: /* 0x15c */ 9262/* File: armv5te/OP_UNUSED_5CFF.S */ 9263/* File: armv5te/unused.S */ 9264 bl common_abort 9265 9266 9267/* ------------------------------ */ 9268 .balign 64 9269.L_OP_UNUSED_5DFF: /* 0x15d */ 9270/* File: armv5te/OP_UNUSED_5DFF.S */ 9271/* File: armv5te/unused.S */ 9272 bl common_abort 9273 9274 9275/* ------------------------------ */ 9276 .balign 64 9277.L_OP_UNUSED_5EFF: /* 0x15e */ 9278/* File: armv5te/OP_UNUSED_5EFF.S */ 9279/* File: armv5te/unused.S */ 9280 bl common_abort 9281 9282 9283/* ------------------------------ */ 9284 .balign 64 9285.L_OP_UNUSED_5FFF: /* 0x15f */ 9286/* File: armv5te/OP_UNUSED_5FFF.S */ 9287/* File: armv5te/unused.S */ 9288 bl common_abort 9289 9290 9291/* ------------------------------ */ 9292 .balign 64 9293.L_OP_UNUSED_60FF: /* 0x160 */ 9294/* File: armv5te/OP_UNUSED_60FF.S */ 9295/* File: armv5te/unused.S */ 9296 bl common_abort 9297 9298 9299/* ------------------------------ */ 9300 .balign 64 9301.L_OP_UNUSED_61FF: /* 0x161 */ 9302/* File: armv5te/OP_UNUSED_61FF.S */ 9303/* File: armv5te/unused.S */ 9304 bl common_abort 9305 9306 9307/* ------------------------------ */ 9308 .balign 64 9309.L_OP_UNUSED_62FF: /* 0x162 */ 9310/* File: armv5te/OP_UNUSED_62FF.S */ 9311/* File: armv5te/unused.S */ 9312 bl common_abort 9313 9314 9315/* ------------------------------ */ 9316 .balign 64 9317.L_OP_UNUSED_63FF: /* 0x163 */ 9318/* File: armv5te/OP_UNUSED_63FF.S */ 9319/* File: armv5te/unused.S */ 9320 bl common_abort 9321 9322 9323/* ------------------------------ */ 9324 .balign 64 9325.L_OP_UNUSED_64FF: /* 0x164 */ 9326/* File: armv5te/OP_UNUSED_64FF.S */ 9327/* File: armv5te/unused.S */ 9328 bl common_abort 9329 9330 9331/* ------------------------------ */ 9332 .balign 64 9333.L_OP_UNUSED_65FF: /* 0x165 */ 9334/* File: armv5te/OP_UNUSED_65FF.S */ 9335/* File: armv5te/unused.S */ 9336 bl common_abort 9337 9338 9339/* ------------------------------ */ 9340 .balign 64 9341.L_OP_UNUSED_66FF: /* 0x166 */ 9342/* File: armv5te/OP_UNUSED_66FF.S */ 9343/* File: armv5te/unused.S */ 9344 bl common_abort 9345 9346 9347/* ------------------------------ */ 9348 .balign 64 9349.L_OP_UNUSED_67FF: /* 0x167 */ 9350/* File: armv5te/OP_UNUSED_67FF.S */ 9351/* File: armv5te/unused.S */ 9352 bl common_abort 9353 9354 9355/* ------------------------------ */ 9356 .balign 64 9357.L_OP_UNUSED_68FF: /* 0x168 */ 9358/* File: armv5te/OP_UNUSED_68FF.S */ 9359/* File: armv5te/unused.S */ 9360 bl common_abort 9361 9362 9363/* ------------------------------ */ 9364 .balign 64 9365.L_OP_UNUSED_69FF: /* 0x169 */ 9366/* File: armv5te/OP_UNUSED_69FF.S */ 9367/* File: armv5te/unused.S */ 9368 bl common_abort 9369 9370 9371/* ------------------------------ */ 9372 .balign 64 9373.L_OP_UNUSED_6AFF: /* 0x16a */ 9374/* File: armv5te/OP_UNUSED_6AFF.S */ 9375/* File: armv5te/unused.S */ 9376 bl common_abort 9377 9378 9379/* ------------------------------ */ 9380 .balign 64 9381.L_OP_UNUSED_6BFF: /* 0x16b */ 9382/* File: armv5te/OP_UNUSED_6BFF.S */ 9383/* File: armv5te/unused.S */ 9384 bl common_abort 9385 9386 9387/* ------------------------------ */ 9388 .balign 64 9389.L_OP_UNUSED_6CFF: /* 0x16c */ 9390/* File: armv5te/OP_UNUSED_6CFF.S */ 9391/* File: armv5te/unused.S */ 9392 bl common_abort 9393 9394 9395/* ------------------------------ */ 9396 .balign 64 9397.L_OP_UNUSED_6DFF: /* 0x16d */ 9398/* File: armv5te/OP_UNUSED_6DFF.S */ 9399/* File: armv5te/unused.S */ 9400 bl common_abort 9401 9402 9403/* ------------------------------ */ 9404 .balign 64 9405.L_OP_UNUSED_6EFF: /* 0x16e */ 9406/* File: armv5te/OP_UNUSED_6EFF.S */ 9407/* File: armv5te/unused.S */ 9408 bl common_abort 9409 9410 9411/* ------------------------------ */ 9412 .balign 64 9413.L_OP_UNUSED_6FFF: /* 0x16f */ 9414/* File: armv5te/OP_UNUSED_6FFF.S */ 9415/* File: armv5te/unused.S */ 9416 bl common_abort 9417 9418 9419/* ------------------------------ */ 9420 .balign 64 9421.L_OP_UNUSED_70FF: /* 0x170 */ 9422/* File: armv5te/OP_UNUSED_70FF.S */ 9423/* File: armv5te/unused.S */ 9424 bl common_abort 9425 9426 9427/* ------------------------------ */ 9428 .balign 64 9429.L_OP_UNUSED_71FF: /* 0x171 */ 9430/* File: armv5te/OP_UNUSED_71FF.S */ 9431/* File: armv5te/unused.S */ 9432 bl common_abort 9433 9434 9435/* ------------------------------ */ 9436 .balign 64 9437.L_OP_UNUSED_72FF: /* 0x172 */ 9438/* File: armv5te/OP_UNUSED_72FF.S */ 9439/* File: armv5te/unused.S */ 9440 bl common_abort 9441 9442 9443/* ------------------------------ */ 9444 .balign 64 9445.L_OP_UNUSED_73FF: /* 0x173 */ 9446/* File: armv5te/OP_UNUSED_73FF.S */ 9447/* File: armv5te/unused.S */ 9448 bl common_abort 9449 9450 9451/* ------------------------------ */ 9452 .balign 64 9453.L_OP_UNUSED_74FF: /* 0x174 */ 9454/* File: armv5te/OP_UNUSED_74FF.S */ 9455/* File: armv5te/unused.S */ 9456 bl common_abort 9457 9458 9459/* ------------------------------ */ 9460 .balign 64 9461.L_OP_UNUSED_75FF: /* 0x175 */ 9462/* File: armv5te/OP_UNUSED_75FF.S */ 9463/* File: armv5te/unused.S */ 9464 bl common_abort 9465 9466 9467/* ------------------------------ */ 9468 .balign 64 9469.L_OP_UNUSED_76FF: /* 0x176 */ 9470/* File: armv5te/OP_UNUSED_76FF.S */ 9471/* File: armv5te/unused.S */ 9472 bl common_abort 9473 9474 9475/* ------------------------------ */ 9476 .balign 64 9477.L_OP_UNUSED_77FF: /* 0x177 */ 9478/* File: armv5te/OP_UNUSED_77FF.S */ 9479/* File: armv5te/unused.S */ 9480 bl common_abort 9481 9482 9483/* ------------------------------ */ 9484 .balign 64 9485.L_OP_UNUSED_78FF: /* 0x178 */ 9486/* File: armv5te/OP_UNUSED_78FF.S */ 9487/* File: armv5te/unused.S */ 9488 bl common_abort 9489 9490 9491/* ------------------------------ */ 9492 .balign 64 9493.L_OP_UNUSED_79FF: /* 0x179 */ 9494/* File: armv5te/OP_UNUSED_79FF.S */ 9495/* File: armv5te/unused.S */ 9496 bl common_abort 9497 9498 9499/* ------------------------------ */ 9500 .balign 64 9501.L_OP_UNUSED_7AFF: /* 0x17a */ 9502/* File: armv5te/OP_UNUSED_7AFF.S */ 9503/* File: armv5te/unused.S */ 9504 bl common_abort 9505 9506 9507/* ------------------------------ */ 9508 .balign 64 9509.L_OP_UNUSED_7BFF: /* 0x17b */ 9510/* File: armv5te/OP_UNUSED_7BFF.S */ 9511/* File: armv5te/unused.S */ 9512 bl common_abort 9513 9514 9515/* ------------------------------ */ 9516 .balign 64 9517.L_OP_UNUSED_7CFF: /* 0x17c */ 9518/* File: armv5te/OP_UNUSED_7CFF.S */ 9519/* File: armv5te/unused.S */ 9520 bl common_abort 9521 9522 9523/* ------------------------------ */ 9524 .balign 64 9525.L_OP_UNUSED_7DFF: /* 0x17d */ 9526/* File: armv5te/OP_UNUSED_7DFF.S */ 9527/* File: armv5te/unused.S */ 9528 bl common_abort 9529 9530 9531/* ------------------------------ */ 9532 .balign 64 9533.L_OP_UNUSED_7EFF: /* 0x17e */ 9534/* File: armv5te/OP_UNUSED_7EFF.S */ 9535/* File: armv5te/unused.S */ 9536 bl common_abort 9537 9538 9539/* ------------------------------ */ 9540 .balign 64 9541.L_OP_UNUSED_7FFF: /* 0x17f */ 9542/* File: armv5te/OP_UNUSED_7FFF.S */ 9543/* File: armv5te/unused.S */ 9544 bl common_abort 9545 9546 9547/* ------------------------------ */ 9548 .balign 64 9549.L_OP_UNUSED_80FF: /* 0x180 */ 9550/* File: armv5te/OP_UNUSED_80FF.S */ 9551/* File: armv5te/unused.S */ 9552 bl common_abort 9553 9554 9555/* ------------------------------ */ 9556 .balign 64 9557.L_OP_UNUSED_81FF: /* 0x181 */ 9558/* File: armv5te/OP_UNUSED_81FF.S */ 9559/* File: armv5te/unused.S */ 9560 bl common_abort 9561 9562 9563/* ------------------------------ */ 9564 .balign 64 9565.L_OP_UNUSED_82FF: /* 0x182 */ 9566/* File: armv5te/OP_UNUSED_82FF.S */ 9567/* File: armv5te/unused.S */ 9568 bl common_abort 9569 9570 9571/* ------------------------------ */ 9572 .balign 64 9573.L_OP_UNUSED_83FF: /* 0x183 */ 9574/* File: armv5te/OP_UNUSED_83FF.S */ 9575/* File: armv5te/unused.S */ 9576 bl common_abort 9577 9578 9579/* ------------------------------ */ 9580 .balign 64 9581.L_OP_UNUSED_84FF: /* 0x184 */ 9582/* File: armv5te/OP_UNUSED_84FF.S */ 9583/* File: armv5te/unused.S */ 9584 bl common_abort 9585 9586 9587/* ------------------------------ */ 9588 .balign 64 9589.L_OP_UNUSED_85FF: /* 0x185 */ 9590/* File: armv5te/OP_UNUSED_85FF.S */ 9591/* File: armv5te/unused.S */ 9592 bl common_abort 9593 9594 9595/* ------------------------------ */ 9596 .balign 64 9597.L_OP_UNUSED_86FF: /* 0x186 */ 9598/* File: armv5te/OP_UNUSED_86FF.S */ 9599/* File: armv5te/unused.S */ 9600 bl common_abort 9601 9602 9603/* ------------------------------ */ 9604 .balign 64 9605.L_OP_UNUSED_87FF: /* 0x187 */ 9606/* File: armv5te/OP_UNUSED_87FF.S */ 9607/* File: armv5te/unused.S */ 9608 bl common_abort 9609 9610 9611/* ------------------------------ */ 9612 .balign 64 9613.L_OP_UNUSED_88FF: /* 0x188 */ 9614/* File: armv5te/OP_UNUSED_88FF.S */ 9615/* File: armv5te/unused.S */ 9616 bl common_abort 9617 9618 9619/* ------------------------------ */ 9620 .balign 64 9621.L_OP_UNUSED_89FF: /* 0x189 */ 9622/* File: armv5te/OP_UNUSED_89FF.S */ 9623/* File: armv5te/unused.S */ 9624 bl common_abort 9625 9626 9627/* ------------------------------ */ 9628 .balign 64 9629.L_OP_UNUSED_8AFF: /* 0x18a */ 9630/* File: armv5te/OP_UNUSED_8AFF.S */ 9631/* File: armv5te/unused.S */ 9632 bl common_abort 9633 9634 9635/* ------------------------------ */ 9636 .balign 64 9637.L_OP_UNUSED_8BFF: /* 0x18b */ 9638/* File: armv5te/OP_UNUSED_8BFF.S */ 9639/* File: armv5te/unused.S */ 9640 bl common_abort 9641 9642 9643/* ------------------------------ */ 9644 .balign 64 9645.L_OP_UNUSED_8CFF: /* 0x18c */ 9646/* File: armv5te/OP_UNUSED_8CFF.S */ 9647/* File: armv5te/unused.S */ 9648 bl common_abort 9649 9650 9651/* ------------------------------ */ 9652 .balign 64 9653.L_OP_UNUSED_8DFF: /* 0x18d */ 9654/* File: armv5te/OP_UNUSED_8DFF.S */ 9655/* File: armv5te/unused.S */ 9656 bl common_abort 9657 9658 9659/* ------------------------------ */ 9660 .balign 64 9661.L_OP_UNUSED_8EFF: /* 0x18e */ 9662/* File: armv5te/OP_UNUSED_8EFF.S */ 9663/* File: armv5te/unused.S */ 9664 bl common_abort 9665 9666 9667/* ------------------------------ */ 9668 .balign 64 9669.L_OP_UNUSED_8FFF: /* 0x18f */ 9670/* File: armv5te/OP_UNUSED_8FFF.S */ 9671/* File: armv5te/unused.S */ 9672 bl common_abort 9673 9674 9675/* ------------------------------ */ 9676 .balign 64 9677.L_OP_UNUSED_90FF: /* 0x190 */ 9678/* File: armv5te/OP_UNUSED_90FF.S */ 9679/* File: armv5te/unused.S */ 9680 bl common_abort 9681 9682 9683/* ------------------------------ */ 9684 .balign 64 9685.L_OP_UNUSED_91FF: /* 0x191 */ 9686/* File: armv5te/OP_UNUSED_91FF.S */ 9687/* File: armv5te/unused.S */ 9688 bl common_abort 9689 9690 9691/* ------------------------------ */ 9692 .balign 64 9693.L_OP_UNUSED_92FF: /* 0x192 */ 9694/* File: armv5te/OP_UNUSED_92FF.S */ 9695/* File: armv5te/unused.S */ 9696 bl common_abort 9697 9698 9699/* ------------------------------ */ 9700 .balign 64 9701.L_OP_UNUSED_93FF: /* 0x193 */ 9702/* File: armv5te/OP_UNUSED_93FF.S */ 9703/* File: armv5te/unused.S */ 9704 bl common_abort 9705 9706 9707/* ------------------------------ */ 9708 .balign 64 9709.L_OP_UNUSED_94FF: /* 0x194 */ 9710/* File: armv5te/OP_UNUSED_94FF.S */ 9711/* File: armv5te/unused.S */ 9712 bl common_abort 9713 9714 9715/* ------------------------------ */ 9716 .balign 64 9717.L_OP_UNUSED_95FF: /* 0x195 */ 9718/* File: armv5te/OP_UNUSED_95FF.S */ 9719/* File: armv5te/unused.S */ 9720 bl common_abort 9721 9722 9723/* ------------------------------ */ 9724 .balign 64 9725.L_OP_UNUSED_96FF: /* 0x196 */ 9726/* File: armv5te/OP_UNUSED_96FF.S */ 9727/* File: armv5te/unused.S */ 9728 bl common_abort 9729 9730 9731/* ------------------------------ */ 9732 .balign 64 9733.L_OP_UNUSED_97FF: /* 0x197 */ 9734/* File: armv5te/OP_UNUSED_97FF.S */ 9735/* File: armv5te/unused.S */ 9736 bl common_abort 9737 9738 9739/* ------------------------------ */ 9740 .balign 64 9741.L_OP_UNUSED_98FF: /* 0x198 */ 9742/* File: armv5te/OP_UNUSED_98FF.S */ 9743/* File: armv5te/unused.S */ 9744 bl common_abort 9745 9746 9747/* ------------------------------ */ 9748 .balign 64 9749.L_OP_UNUSED_99FF: /* 0x199 */ 9750/* File: armv5te/OP_UNUSED_99FF.S */ 9751/* File: armv5te/unused.S */ 9752 bl common_abort 9753 9754 9755/* ------------------------------ */ 9756 .balign 64 9757.L_OP_UNUSED_9AFF: /* 0x19a */ 9758/* File: armv5te/OP_UNUSED_9AFF.S */ 9759/* File: armv5te/unused.S */ 9760 bl common_abort 9761 9762 9763/* ------------------------------ */ 9764 .balign 64 9765.L_OP_UNUSED_9BFF: /* 0x19b */ 9766/* File: armv5te/OP_UNUSED_9BFF.S */ 9767/* File: armv5te/unused.S */ 9768 bl common_abort 9769 9770 9771/* ------------------------------ */ 9772 .balign 64 9773.L_OP_UNUSED_9CFF: /* 0x19c */ 9774/* File: armv5te/OP_UNUSED_9CFF.S */ 9775/* File: armv5te/unused.S */ 9776 bl common_abort 9777 9778 9779/* ------------------------------ */ 9780 .balign 64 9781.L_OP_UNUSED_9DFF: /* 0x19d */ 9782/* File: armv5te/OP_UNUSED_9DFF.S */ 9783/* File: armv5te/unused.S */ 9784 bl common_abort 9785 9786 9787/* ------------------------------ */ 9788 .balign 64 9789.L_OP_UNUSED_9EFF: /* 0x19e */ 9790/* File: armv5te/OP_UNUSED_9EFF.S */ 9791/* File: armv5te/unused.S */ 9792 bl common_abort 9793 9794 9795/* ------------------------------ */ 9796 .balign 64 9797.L_OP_UNUSED_9FFF: /* 0x19f */ 9798/* File: armv5te/OP_UNUSED_9FFF.S */ 9799/* File: armv5te/unused.S */ 9800 bl common_abort 9801 9802 9803/* ------------------------------ */ 9804 .balign 64 9805.L_OP_UNUSED_A0FF: /* 0x1a0 */ 9806/* File: armv5te/OP_UNUSED_A0FF.S */ 9807/* File: armv5te/unused.S */ 9808 bl common_abort 9809 9810 9811/* ------------------------------ */ 9812 .balign 64 9813.L_OP_UNUSED_A1FF: /* 0x1a1 */ 9814/* File: armv5te/OP_UNUSED_A1FF.S */ 9815/* File: armv5te/unused.S */ 9816 bl common_abort 9817 9818 9819/* ------------------------------ */ 9820 .balign 64 9821.L_OP_UNUSED_A2FF: /* 0x1a2 */ 9822/* File: armv5te/OP_UNUSED_A2FF.S */ 9823/* File: armv5te/unused.S */ 9824 bl common_abort 9825 9826 9827/* ------------------------------ */ 9828 .balign 64 9829.L_OP_UNUSED_A3FF: /* 0x1a3 */ 9830/* File: armv5te/OP_UNUSED_A3FF.S */ 9831/* File: armv5te/unused.S */ 9832 bl common_abort 9833 9834 9835/* ------------------------------ */ 9836 .balign 64 9837.L_OP_UNUSED_A4FF: /* 0x1a4 */ 9838/* File: armv5te/OP_UNUSED_A4FF.S */ 9839/* File: armv5te/unused.S */ 9840 bl common_abort 9841 9842 9843/* ------------------------------ */ 9844 .balign 64 9845.L_OP_UNUSED_A5FF: /* 0x1a5 */ 9846/* File: armv5te/OP_UNUSED_A5FF.S */ 9847/* File: armv5te/unused.S */ 9848 bl common_abort 9849 9850 9851/* ------------------------------ */ 9852 .balign 64 9853.L_OP_UNUSED_A6FF: /* 0x1a6 */ 9854/* File: armv5te/OP_UNUSED_A6FF.S */ 9855/* File: armv5te/unused.S */ 9856 bl common_abort 9857 9858 9859/* ------------------------------ */ 9860 .balign 64 9861.L_OP_UNUSED_A7FF: /* 0x1a7 */ 9862/* File: armv5te/OP_UNUSED_A7FF.S */ 9863/* File: armv5te/unused.S */ 9864 bl common_abort 9865 9866 9867/* ------------------------------ */ 9868 .balign 64 9869.L_OP_UNUSED_A8FF: /* 0x1a8 */ 9870/* File: armv5te/OP_UNUSED_A8FF.S */ 9871/* File: armv5te/unused.S */ 9872 bl common_abort 9873 9874 9875/* ------------------------------ */ 9876 .balign 64 9877.L_OP_UNUSED_A9FF: /* 0x1a9 */ 9878/* File: armv5te/OP_UNUSED_A9FF.S */ 9879/* File: armv5te/unused.S */ 9880 bl common_abort 9881 9882 9883/* ------------------------------ */ 9884 .balign 64 9885.L_OP_UNUSED_AAFF: /* 0x1aa */ 9886/* File: armv5te/OP_UNUSED_AAFF.S */ 9887/* File: armv5te/unused.S */ 9888 bl common_abort 9889 9890 9891/* ------------------------------ */ 9892 .balign 64 9893.L_OP_UNUSED_ABFF: /* 0x1ab */ 9894/* File: armv5te/OP_UNUSED_ABFF.S */ 9895/* File: armv5te/unused.S */ 9896 bl common_abort 9897 9898 9899/* ------------------------------ */ 9900 .balign 64 9901.L_OP_UNUSED_ACFF: /* 0x1ac */ 9902/* File: armv5te/OP_UNUSED_ACFF.S */ 9903/* File: armv5te/unused.S */ 9904 bl common_abort 9905 9906 9907/* ------------------------------ */ 9908 .balign 64 9909.L_OP_UNUSED_ADFF: /* 0x1ad */ 9910/* File: armv5te/OP_UNUSED_ADFF.S */ 9911/* File: armv5te/unused.S */ 9912 bl common_abort 9913 9914 9915/* ------------------------------ */ 9916 .balign 64 9917.L_OP_UNUSED_AEFF: /* 0x1ae */ 9918/* File: armv5te/OP_UNUSED_AEFF.S */ 9919/* File: armv5te/unused.S */ 9920 bl common_abort 9921 9922 9923/* ------------------------------ */ 9924 .balign 64 9925.L_OP_UNUSED_AFFF: /* 0x1af */ 9926/* File: armv5te/OP_UNUSED_AFFF.S */ 9927/* File: armv5te/unused.S */ 9928 bl common_abort 9929 9930 9931/* ------------------------------ */ 9932 .balign 64 9933.L_OP_UNUSED_B0FF: /* 0x1b0 */ 9934/* File: armv5te/OP_UNUSED_B0FF.S */ 9935/* File: armv5te/unused.S */ 9936 bl common_abort 9937 9938 9939/* ------------------------------ */ 9940 .balign 64 9941.L_OP_UNUSED_B1FF: /* 0x1b1 */ 9942/* File: armv5te/OP_UNUSED_B1FF.S */ 9943/* File: armv5te/unused.S */ 9944 bl common_abort 9945 9946 9947/* ------------------------------ */ 9948 .balign 64 9949.L_OP_UNUSED_B2FF: /* 0x1b2 */ 9950/* File: armv5te/OP_UNUSED_B2FF.S */ 9951/* File: armv5te/unused.S */ 9952 bl common_abort 9953 9954 9955/* ------------------------------ */ 9956 .balign 64 9957.L_OP_UNUSED_B3FF: /* 0x1b3 */ 9958/* File: armv5te/OP_UNUSED_B3FF.S */ 9959/* File: armv5te/unused.S */ 9960 bl common_abort 9961 9962 9963/* ------------------------------ */ 9964 .balign 64 9965.L_OP_UNUSED_B4FF: /* 0x1b4 */ 9966/* File: armv5te/OP_UNUSED_B4FF.S */ 9967/* File: armv5te/unused.S */ 9968 bl common_abort 9969 9970 9971/* ------------------------------ */ 9972 .balign 64 9973.L_OP_UNUSED_B5FF: /* 0x1b5 */ 9974/* File: armv5te/OP_UNUSED_B5FF.S */ 9975/* File: armv5te/unused.S */ 9976 bl common_abort 9977 9978 9979/* ------------------------------ */ 9980 .balign 64 9981.L_OP_UNUSED_B6FF: /* 0x1b6 */ 9982/* File: armv5te/OP_UNUSED_B6FF.S */ 9983/* File: armv5te/unused.S */ 9984 bl common_abort 9985 9986 9987/* ------------------------------ */ 9988 .balign 64 9989.L_OP_UNUSED_B7FF: /* 0x1b7 */ 9990/* File: armv5te/OP_UNUSED_B7FF.S */ 9991/* File: armv5te/unused.S */ 9992 bl common_abort 9993 9994 9995/* ------------------------------ */ 9996 .balign 64 9997.L_OP_UNUSED_B8FF: /* 0x1b8 */ 9998/* File: armv5te/OP_UNUSED_B8FF.S */ 9999/* File: armv5te/unused.S */ 10000 bl common_abort 10001 10002 10003/* ------------------------------ */ 10004 .balign 64 10005.L_OP_UNUSED_B9FF: /* 0x1b9 */ 10006/* File: armv5te/OP_UNUSED_B9FF.S */ 10007/* File: armv5te/unused.S */ 10008 bl common_abort 10009 10010 10011/* ------------------------------ */ 10012 .balign 64 10013.L_OP_UNUSED_BAFF: /* 0x1ba */ 10014/* File: armv5te/OP_UNUSED_BAFF.S */ 10015/* File: armv5te/unused.S */ 10016 bl common_abort 10017 10018 10019/* ------------------------------ */ 10020 .balign 64 10021.L_OP_UNUSED_BBFF: /* 0x1bb */ 10022/* File: armv5te/OP_UNUSED_BBFF.S */ 10023/* File: armv5te/unused.S */ 10024 bl common_abort 10025 10026 10027/* ------------------------------ */ 10028 .balign 64 10029.L_OP_UNUSED_BCFF: /* 0x1bc */ 10030/* File: armv5te/OP_UNUSED_BCFF.S */ 10031/* File: armv5te/unused.S */ 10032 bl common_abort 10033 10034 10035/* ------------------------------ */ 10036 .balign 64 10037.L_OP_UNUSED_BDFF: /* 0x1bd */ 10038/* File: armv5te/OP_UNUSED_BDFF.S */ 10039/* File: armv5te/unused.S */ 10040 bl common_abort 10041 10042 10043/* ------------------------------ */ 10044 .balign 64 10045.L_OP_UNUSED_BEFF: /* 0x1be */ 10046/* File: armv5te/OP_UNUSED_BEFF.S */ 10047/* File: armv5te/unused.S */ 10048 bl common_abort 10049 10050 10051/* ------------------------------ */ 10052 .balign 64 10053.L_OP_UNUSED_BFFF: /* 0x1bf */ 10054/* File: armv5te/OP_UNUSED_BFFF.S */ 10055/* File: armv5te/unused.S */ 10056 bl common_abort 10057 10058 10059/* ------------------------------ */ 10060 .balign 64 10061.L_OP_UNUSED_C0FF: /* 0x1c0 */ 10062/* File: armv5te/OP_UNUSED_C0FF.S */ 10063/* File: armv5te/unused.S */ 10064 bl common_abort 10065 10066 10067/* ------------------------------ */ 10068 .balign 64 10069.L_OP_UNUSED_C1FF: /* 0x1c1 */ 10070/* File: armv5te/OP_UNUSED_C1FF.S */ 10071/* File: armv5te/unused.S */ 10072 bl common_abort 10073 10074 10075/* ------------------------------ */ 10076 .balign 64 10077.L_OP_UNUSED_C2FF: /* 0x1c2 */ 10078/* File: armv5te/OP_UNUSED_C2FF.S */ 10079/* File: armv5te/unused.S */ 10080 bl common_abort 10081 10082 10083/* ------------------------------ */ 10084 .balign 64 10085.L_OP_UNUSED_C3FF: /* 0x1c3 */ 10086/* File: armv5te/OP_UNUSED_C3FF.S */ 10087/* File: armv5te/unused.S */ 10088 bl common_abort 10089 10090 10091/* ------------------------------ */ 10092 .balign 64 10093.L_OP_UNUSED_C4FF: /* 0x1c4 */ 10094/* File: armv5te/OP_UNUSED_C4FF.S */ 10095/* File: armv5te/unused.S */ 10096 bl common_abort 10097 10098 10099/* ------------------------------ */ 10100 .balign 64 10101.L_OP_UNUSED_C5FF: /* 0x1c5 */ 10102/* File: armv5te/OP_UNUSED_C5FF.S */ 10103/* File: armv5te/unused.S */ 10104 bl common_abort 10105 10106 10107/* ------------------------------ */ 10108 .balign 64 10109.L_OP_UNUSED_C6FF: /* 0x1c6 */ 10110/* File: armv5te/OP_UNUSED_C6FF.S */ 10111/* File: armv5te/unused.S */ 10112 bl common_abort 10113 10114 10115/* ------------------------------ */ 10116 .balign 64 10117.L_OP_UNUSED_C7FF: /* 0x1c7 */ 10118/* File: armv5te/OP_UNUSED_C7FF.S */ 10119/* File: armv5te/unused.S */ 10120 bl common_abort 10121 10122 10123/* ------------------------------ */ 10124 .balign 64 10125.L_OP_UNUSED_C8FF: /* 0x1c8 */ 10126/* File: armv5te/OP_UNUSED_C8FF.S */ 10127/* File: armv5te/unused.S */ 10128 bl common_abort 10129 10130 10131/* ------------------------------ */ 10132 .balign 64 10133.L_OP_UNUSED_C9FF: /* 0x1c9 */ 10134/* File: armv5te/OP_UNUSED_C9FF.S */ 10135/* File: armv5te/unused.S */ 10136 bl common_abort 10137 10138 10139/* ------------------------------ */ 10140 .balign 64 10141.L_OP_UNUSED_CAFF: /* 0x1ca */ 10142/* File: armv5te/OP_UNUSED_CAFF.S */ 10143/* File: armv5te/unused.S */ 10144 bl common_abort 10145 10146 10147/* ------------------------------ */ 10148 .balign 64 10149.L_OP_UNUSED_CBFF: /* 0x1cb */ 10150/* File: armv5te/OP_UNUSED_CBFF.S */ 10151/* File: armv5te/unused.S */ 10152 bl common_abort 10153 10154 10155/* ------------------------------ */ 10156 .balign 64 10157.L_OP_UNUSED_CCFF: /* 0x1cc */ 10158/* File: armv5te/OP_UNUSED_CCFF.S */ 10159/* File: armv5te/unused.S */ 10160 bl common_abort 10161 10162 10163/* ------------------------------ */ 10164 .balign 64 10165.L_OP_UNUSED_CDFF: /* 0x1cd */ 10166/* File: armv5te/OP_UNUSED_CDFF.S */ 10167/* File: armv5te/unused.S */ 10168 bl common_abort 10169 10170 10171/* ------------------------------ */ 10172 .balign 64 10173.L_OP_UNUSED_CEFF: /* 0x1ce */ 10174/* File: armv5te/OP_UNUSED_CEFF.S */ 10175/* File: armv5te/unused.S */ 10176 bl common_abort 10177 10178 10179/* ------------------------------ */ 10180 .balign 64 10181.L_OP_UNUSED_CFFF: /* 0x1cf */ 10182/* File: armv5te/OP_UNUSED_CFFF.S */ 10183/* File: armv5te/unused.S */ 10184 bl common_abort 10185 10186 10187/* ------------------------------ */ 10188 .balign 64 10189.L_OP_UNUSED_D0FF: /* 0x1d0 */ 10190/* File: armv5te/OP_UNUSED_D0FF.S */ 10191/* File: armv5te/unused.S */ 10192 bl common_abort 10193 10194 10195/* ------------------------------ */ 10196 .balign 64 10197.L_OP_UNUSED_D1FF: /* 0x1d1 */ 10198/* File: armv5te/OP_UNUSED_D1FF.S */ 10199/* File: armv5te/unused.S */ 10200 bl common_abort 10201 10202 10203/* ------------------------------ */ 10204 .balign 64 10205.L_OP_UNUSED_D2FF: /* 0x1d2 */ 10206/* File: armv5te/OP_UNUSED_D2FF.S */ 10207/* File: armv5te/unused.S */ 10208 bl common_abort 10209 10210 10211/* ------------------------------ */ 10212 .balign 64 10213.L_OP_UNUSED_D3FF: /* 0x1d3 */ 10214/* File: armv5te/OP_UNUSED_D3FF.S */ 10215/* File: armv5te/unused.S */ 10216 bl common_abort 10217 10218 10219/* ------------------------------ */ 10220 .balign 64 10221.L_OP_UNUSED_D4FF: /* 0x1d4 */ 10222/* File: armv5te/OP_UNUSED_D4FF.S */ 10223/* File: armv5te/unused.S */ 10224 bl common_abort 10225 10226 10227/* ------------------------------ */ 10228 .balign 64 10229.L_OP_UNUSED_D5FF: /* 0x1d5 */ 10230/* File: armv5te/OP_UNUSED_D5FF.S */ 10231/* File: armv5te/unused.S */ 10232 bl common_abort 10233 10234 10235/* ------------------------------ */ 10236 .balign 64 10237.L_OP_UNUSED_D6FF: /* 0x1d6 */ 10238/* File: armv5te/OP_UNUSED_D6FF.S */ 10239/* File: armv5te/unused.S */ 10240 bl common_abort 10241 10242 10243/* ------------------------------ */ 10244 .balign 64 10245.L_OP_UNUSED_D7FF: /* 0x1d7 */ 10246/* File: armv5te/OP_UNUSED_D7FF.S */ 10247/* File: armv5te/unused.S */ 10248 bl common_abort 10249 10250 10251/* ------------------------------ */ 10252 .balign 64 10253.L_OP_UNUSED_D8FF: /* 0x1d8 */ 10254/* File: armv5te/OP_UNUSED_D8FF.S */ 10255/* File: armv5te/unused.S */ 10256 bl common_abort 10257 10258 10259/* ------------------------------ */ 10260 .balign 64 10261.L_OP_UNUSED_D9FF: /* 0x1d9 */ 10262/* File: armv5te/OP_UNUSED_D9FF.S */ 10263/* File: armv5te/unused.S */ 10264 bl common_abort 10265 10266 10267/* ------------------------------ */ 10268 .balign 64 10269.L_OP_UNUSED_DAFF: /* 0x1da */ 10270/* File: armv5te/OP_UNUSED_DAFF.S */ 10271/* File: armv5te/unused.S */ 10272 bl common_abort 10273 10274 10275/* ------------------------------ */ 10276 .balign 64 10277.L_OP_UNUSED_DBFF: /* 0x1db */ 10278/* File: armv5te/OP_UNUSED_DBFF.S */ 10279/* File: armv5te/unused.S */ 10280 bl common_abort 10281 10282 10283/* ------------------------------ */ 10284 .balign 64 10285.L_OP_UNUSED_DCFF: /* 0x1dc */ 10286/* File: armv5te/OP_UNUSED_DCFF.S */ 10287/* File: armv5te/unused.S */ 10288 bl common_abort 10289 10290 10291/* ------------------------------ */ 10292 .balign 64 10293.L_OP_UNUSED_DDFF: /* 0x1dd */ 10294/* File: armv5te/OP_UNUSED_DDFF.S */ 10295/* File: armv5te/unused.S */ 10296 bl common_abort 10297 10298 10299/* ------------------------------ */ 10300 .balign 64 10301.L_OP_UNUSED_DEFF: /* 0x1de */ 10302/* File: armv5te/OP_UNUSED_DEFF.S */ 10303/* File: armv5te/unused.S */ 10304 bl common_abort 10305 10306 10307/* ------------------------------ */ 10308 .balign 64 10309.L_OP_UNUSED_DFFF: /* 0x1df */ 10310/* File: armv5te/OP_UNUSED_DFFF.S */ 10311/* File: armv5te/unused.S */ 10312 bl common_abort 10313 10314 10315/* ------------------------------ */ 10316 .balign 64 10317.L_OP_UNUSED_E0FF: /* 0x1e0 */ 10318/* File: armv5te/OP_UNUSED_E0FF.S */ 10319/* File: armv5te/unused.S */ 10320 bl common_abort 10321 10322 10323/* ------------------------------ */ 10324 .balign 64 10325.L_OP_UNUSED_E1FF: /* 0x1e1 */ 10326/* File: armv5te/OP_UNUSED_E1FF.S */ 10327/* File: armv5te/unused.S */ 10328 bl common_abort 10329 10330 10331/* ------------------------------ */ 10332 .balign 64 10333.L_OP_UNUSED_E2FF: /* 0x1e2 */ 10334/* File: armv5te/OP_UNUSED_E2FF.S */ 10335/* File: armv5te/unused.S */ 10336 bl common_abort 10337 10338 10339/* ------------------------------ */ 10340 .balign 64 10341.L_OP_UNUSED_E3FF: /* 0x1e3 */ 10342/* File: armv5te/OP_UNUSED_E3FF.S */ 10343/* File: armv5te/unused.S */ 10344 bl common_abort 10345 10346 10347/* ------------------------------ */ 10348 .balign 64 10349.L_OP_UNUSED_E4FF: /* 0x1e4 */ 10350/* File: armv5te/OP_UNUSED_E4FF.S */ 10351/* File: armv5te/unused.S */ 10352 bl common_abort 10353 10354 10355/* ------------------------------ */ 10356 .balign 64 10357.L_OP_UNUSED_E5FF: /* 0x1e5 */ 10358/* File: armv5te/OP_UNUSED_E5FF.S */ 10359/* File: armv5te/unused.S */ 10360 bl common_abort 10361 10362 10363/* ------------------------------ */ 10364 .balign 64 10365.L_OP_UNUSED_E6FF: /* 0x1e6 */ 10366/* File: armv5te/OP_UNUSED_E6FF.S */ 10367/* File: armv5te/unused.S */ 10368 bl common_abort 10369 10370 10371/* ------------------------------ */ 10372 .balign 64 10373.L_OP_UNUSED_E7FF: /* 0x1e7 */ 10374/* File: armv5te/OP_UNUSED_E7FF.S */ 10375/* File: armv5te/unused.S */ 10376 bl common_abort 10377 10378 10379/* ------------------------------ */ 10380 .balign 64 10381.L_OP_UNUSED_E8FF: /* 0x1e8 */ 10382/* File: armv5te/OP_UNUSED_E8FF.S */ 10383/* File: armv5te/unused.S */ 10384 bl common_abort 10385 10386 10387/* ------------------------------ */ 10388 .balign 64 10389.L_OP_UNUSED_E9FF: /* 0x1e9 */ 10390/* File: armv5te/OP_UNUSED_E9FF.S */ 10391/* File: armv5te/unused.S */ 10392 bl common_abort 10393 10394 10395/* ------------------------------ */ 10396 .balign 64 10397.L_OP_UNUSED_EAFF: /* 0x1ea */ 10398/* File: armv5te/OP_UNUSED_EAFF.S */ 10399/* File: armv5te/unused.S */ 10400 bl common_abort 10401 10402 10403/* ------------------------------ */ 10404 .balign 64 10405.L_OP_UNUSED_EBFF: /* 0x1eb */ 10406/* File: armv5te/OP_UNUSED_EBFF.S */ 10407/* File: armv5te/unused.S */ 10408 bl common_abort 10409 10410 10411/* ------------------------------ */ 10412 .balign 64 10413.L_OP_UNUSED_ECFF: /* 0x1ec */ 10414/* File: armv5te/OP_UNUSED_ECFF.S */ 10415/* File: armv5te/unused.S */ 10416 bl common_abort 10417 10418 10419/* ------------------------------ */ 10420 .balign 64 10421.L_OP_UNUSED_EDFF: /* 0x1ed */ 10422/* File: armv5te/OP_UNUSED_EDFF.S */ 10423/* File: armv5te/unused.S */ 10424 bl common_abort 10425 10426 10427/* ------------------------------ */ 10428 .balign 64 10429.L_OP_UNUSED_EEFF: /* 0x1ee */ 10430/* File: armv5te/OP_UNUSED_EEFF.S */ 10431/* File: armv5te/unused.S */ 10432 bl common_abort 10433 10434 10435/* ------------------------------ */ 10436 .balign 64 10437.L_OP_UNUSED_EFFF: /* 0x1ef */ 10438/* File: armv5te/OP_UNUSED_EFFF.S */ 10439/* File: armv5te/unused.S */ 10440 bl common_abort 10441 10442 10443/* ------------------------------ */ 10444 .balign 64 10445.L_OP_UNUSED_F0FF: /* 0x1f0 */ 10446/* File: armv5te/OP_UNUSED_F0FF.S */ 10447/* File: armv5te/unused.S */ 10448 bl common_abort 10449 10450 10451/* ------------------------------ */ 10452 .balign 64 10453.L_OP_UNUSED_F1FF: /* 0x1f1 */ 10454/* File: armv5te/OP_UNUSED_F1FF.S */ 10455/* File: armv5te/unused.S */ 10456 bl common_abort 10457 10458 10459/* ------------------------------ */ 10460 .balign 64 10461.L_OP_UNUSED_F2FF: /* 0x1f2 */ 10462/* File: armv5te/OP_UNUSED_F2FF.S */ 10463/* File: armv5te/unused.S */ 10464 bl common_abort 10465 10466 10467/* ------------------------------ */ 10468 .balign 64 10469.L_OP_UNUSED_F3FF: /* 0x1f3 */ 10470/* File: armv5te/OP_UNUSED_F3FF.S */ 10471/* File: armv5te/unused.S */ 10472 bl common_abort 10473 10474 10475/* ------------------------------ */ 10476 .balign 64 10477.L_OP_UNUSED_F4FF: /* 0x1f4 */ 10478/* File: armv5te/OP_UNUSED_F4FF.S */ 10479/* File: armv5te/unused.S */ 10480 bl common_abort 10481 10482 10483/* ------------------------------ */ 10484 .balign 64 10485.L_OP_UNUSED_F5FF: /* 0x1f5 */ 10486/* File: armv5te/OP_UNUSED_F5FF.S */ 10487/* File: armv5te/unused.S */ 10488 bl common_abort 10489 10490 10491/* ------------------------------ */ 10492 .balign 64 10493.L_OP_UNUSED_F6FF: /* 0x1f6 */ 10494/* File: armv5te/OP_UNUSED_F6FF.S */ 10495/* File: armv5te/unused.S */ 10496 bl common_abort 10497 10498 10499/* ------------------------------ */ 10500 .balign 64 10501.L_OP_UNUSED_F7FF: /* 0x1f7 */ 10502/* File: armv5te/OP_UNUSED_F7FF.S */ 10503/* File: armv5te/unused.S */ 10504 bl common_abort 10505 10506 10507/* ------------------------------ */ 10508 .balign 64 10509.L_OP_UNUSED_F8FF: /* 0x1f8 */ 10510/* File: armv5te/OP_UNUSED_F8FF.S */ 10511/* File: armv5te/unused.S */ 10512 bl common_abort 10513 10514 10515/* ------------------------------ */ 10516 .balign 64 10517.L_OP_UNUSED_F9FF: /* 0x1f9 */ 10518/* File: armv5te/OP_UNUSED_F9FF.S */ 10519/* File: armv5te/unused.S */ 10520 bl common_abort 10521 10522 10523/* ------------------------------ */ 10524 .balign 64 10525.L_OP_UNUSED_FAFF: /* 0x1fa */ 10526/* File: armv5te/OP_UNUSED_FAFF.S */ 10527/* File: armv5te/unused.S */ 10528 bl common_abort 10529 10530 10531/* ------------------------------ */ 10532 .balign 64 10533.L_OP_UNUSED_FBFF: /* 0x1fb */ 10534/* File: armv5te/OP_UNUSED_FBFF.S */ 10535/* File: armv5te/unused.S */ 10536 bl common_abort 10537 10538 10539/* ------------------------------ */ 10540 .balign 64 10541.L_OP_UNUSED_FCFF: /* 0x1fc */ 10542/* File: armv5te/OP_UNUSED_FCFF.S */ 10543/* File: armv5te/unused.S */ 10544 bl common_abort 10545 10546 10547/* ------------------------------ */ 10548 .balign 64 10549.L_OP_UNUSED_FDFF: /* 0x1fd */ 10550/* File: armv5te/OP_UNUSED_FDFF.S */ 10551/* File: armv5te/unused.S */ 10552 bl common_abort 10553 10554 10555/* ------------------------------ */ 10556 .balign 64 10557.L_OP_UNUSED_FEFF: /* 0x1fe */ 10558/* File: armv5te/OP_UNUSED_FEFF.S */ 10559/* File: armv5te/unused.S */ 10560 bl common_abort 10561 10562 10563/* ------------------------------ */ 10564 .balign 64 10565.L_OP_THROW_VERIFICATION_ERROR_JUMBO: /* 0x1ff */ 10566/* File: armv5te/OP_THROW_VERIFICATION_ERROR_JUMBO.S */ 10567 /* 10568 * Handle a jumbo throw-verification-error instruction. This throws an 10569 * exception for an error discovered during verification. The 10570 * exception is indicated by BBBB, with some detail provided by AAAAAAAA. 10571 */ 10572 /* exop BBBB, Class@AAAAAAAA */ 10573 FETCH(r1, 1) @ r1<- aaaa (lo) 10574 FETCH(r2, 2) @ r2<- AAAA (hi) 10575 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 10576 orr r2, r1, r2, lsl #16 @ r2<- AAAAaaaa 10577 EXPORT_PC() @ export the PC 10578 FETCH(r1, 3) @ r1<- BBBB 10579 bl dvmThrowVerificationError @ always throws 10580 b common_exceptionThrown @ handle exception 10581 10582 10583 .balign 64 10584 .size .L_OP_NOP, .-.L_OP_NOP 10585 .global dvmAsmInstructionEnd 10586dvmAsmInstructionEnd: 10587 10588/* 10589 * =========================================================================== 10590 * Sister implementations 10591 * =========================================================================== 10592 */ 10593 .global dvmAsmSisterStart 10594 .type dvmAsmSisterStart, %function 10595 .text 10596 .balign 4 10597dvmAsmSisterStart: 10598 10599/* continuation for OP_CONST_STRING */ 10600 10601 /* 10602 * Continuation if the String has not yet been resolved. 10603 * r1: BBBB (String ref) 10604 * r9: target register 10605 */ 10606.LOP_CONST_STRING_resolve: 10607 EXPORT_PC() 10608 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 10609 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 10610 bl dvmResolveString @ r0<- String reference 10611 cmp r0, #0 @ failed? 10612 beq common_exceptionThrown @ yup, handle the exception 10613 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 10614 GET_INST_OPCODE(ip) @ extract opcode from rINST 10615 SET_VREG(r0, r9) @ vAA<- r0 10616 GOTO_OPCODE(ip) @ jump to next instruction 10617 10618/* continuation for OP_CONST_STRING_JUMBO */ 10619 10620 /* 10621 * Continuation if the String has not yet been resolved. 10622 * r1: BBBBBBBB (String ref) 10623 * r9: target register 10624 */ 10625.LOP_CONST_STRING_JUMBO_resolve: 10626 EXPORT_PC() 10627 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 10628 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 10629 bl dvmResolveString @ r0<- String reference 10630 cmp r0, #0 @ failed? 10631 beq common_exceptionThrown @ yup, handle the exception 10632 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 10633 GET_INST_OPCODE(ip) @ extract opcode from rINST 10634 SET_VREG(r0, r9) @ vAA<- r0 10635 GOTO_OPCODE(ip) @ jump to next instruction 10636 10637/* continuation for OP_CONST_CLASS */ 10638 10639 /* 10640 * Continuation if the Class has not yet been resolved. 10641 * r1: BBBB (Class ref) 10642 * r9: target register 10643 */ 10644.LOP_CONST_CLASS_resolve: 10645 EXPORT_PC() 10646 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 10647 mov r2, #1 @ r2<- true 10648 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 10649 bl dvmResolveClass @ r0<- Class reference 10650 cmp r0, #0 @ failed? 10651 beq common_exceptionThrown @ yup, handle the exception 10652 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 10653 GET_INST_OPCODE(ip) @ extract opcode from rINST 10654 SET_VREG(r0, r9) @ vAA<- r0 10655 GOTO_OPCODE(ip) @ jump to next instruction 10656 10657/* continuation for OP_CHECK_CAST */ 10658 10659 /* 10660 * Trivial test failed, need to perform full check. This is common. 10661 * r0 holds obj->clazz 10662 * r1 holds desired class resolved from BBBB 10663 * r9 holds object 10664 */ 10665.LOP_CHECK_CAST_fullcheck: 10666 mov r10, r1 @ avoid ClassObject getting clobbered 10667 bl dvmInstanceofNonTrivial @ r0<- boolean result 10668 cmp r0, #0 @ failed? 10669 bne .LOP_CHECK_CAST_okay @ no, success 10670 10671 @ A cast has failed. We need to throw a ClassCastException. 10672 EXPORT_PC() @ about to throw 10673 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz (actual class) 10674 mov r1, r10 @ r1<- desired class 10675 bl dvmThrowClassCastException 10676 b common_exceptionThrown 10677 10678 /* 10679 * Resolution required. This is the least-likely path. 10680 * 10681 * r2 holds BBBB 10682 * r9 holds object 10683 */ 10684.LOP_CHECK_CAST_resolve: 10685 EXPORT_PC() @ resolve() could throw 10686 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 10687 mov r1, r2 @ r1<- BBBB 10688 mov r2, #0 @ r2<- false 10689 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 10690 bl dvmResolveClass @ r0<- resolved ClassObject ptr 10691 cmp r0, #0 @ got null? 10692 beq common_exceptionThrown @ yes, handle exception 10693 mov r1, r0 @ r1<- class resolved from BBB 10694 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 10695 b .LOP_CHECK_CAST_resolved @ pick up where we left off 10696 10697/* continuation for OP_INSTANCE_OF */ 10698 10699 /* 10700 * Trivial test failed, need to perform full check. This is common. 10701 * r0 holds obj->clazz 10702 * r1 holds class resolved from BBBB 10703 * r9 holds A 10704 */ 10705.LOP_INSTANCE_OF_fullcheck: 10706 bl dvmInstanceofNonTrivial @ r0<- boolean result 10707 @ fall through to OP_INSTANCE_OF_store 10708 10709 /* 10710 * r0 holds boolean result 10711 * r9 holds A 10712 */ 10713.LOP_INSTANCE_OF_store: 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 * Trivial test succeeded, save and bail. 10721 * r9 holds A 10722 */ 10723.LOP_INSTANCE_OF_trivial: 10724 mov r0, #1 @ indicate success 10725 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 10726 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 10727 SET_VREG(r0, r9) @ vA<- r0 10728 GET_INST_OPCODE(ip) @ extract opcode from rINST 10729 GOTO_OPCODE(ip) @ jump to next instruction 10730 10731 /* 10732 * Resolution required. This is the least-likely path. 10733 * 10734 * r3 holds BBBB 10735 * r9 holds A 10736 */ 10737.LOP_INSTANCE_OF_resolve: 10738 EXPORT_PC() @ resolve() could throw 10739 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 10740 mov r1, r3 @ r1<- BBBB 10741 mov r2, #1 @ r2<- true 10742 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 10743 bl dvmResolveClass @ r0<- resolved ClassObject ptr 10744 cmp r0, #0 @ got null? 10745 beq common_exceptionThrown @ yes, handle exception 10746 mov r1, r0 @ r1<- class resolved from BBB 10747 mov r3, rINST, lsr #12 @ r3<- B 10748 GET_VREG(r0, r3) @ r0<- vB (object) 10749 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 10750 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 10751 10752/* continuation for OP_NEW_INSTANCE */ 10753 10754 .balign 32 @ minimize cache lines 10755.LOP_NEW_INSTANCE_finish: @ r0=new object 10756 mov r3, rINST, lsr #8 @ r3<- AA 10757 cmp r0, #0 @ failed? 10758 beq common_exceptionThrown @ yes, handle the exception 10759 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 10760 GET_INST_OPCODE(ip) @ extract opcode from rINST 10761 SET_VREG(r0, r3) @ vAA<- r0 10762 GOTO_OPCODE(ip) @ jump to next instruction 10763 10764 /* 10765 * Class initialization required. 10766 * 10767 * r0 holds class object 10768 */ 10769.LOP_NEW_INSTANCE_needinit: 10770 mov r9, r0 @ save r0 10771 bl dvmInitClass @ initialize class 10772 cmp r0, #0 @ check boolean result 10773 mov r0, r9 @ restore r0 10774 bne .LOP_NEW_INSTANCE_initialized @ success, continue 10775 b common_exceptionThrown @ failed, deal with init exception 10776 10777 /* 10778 * Resolution required. This is the least-likely path. 10779 * 10780 * r1 holds BBBB 10781 */ 10782.LOP_NEW_INSTANCE_resolve: 10783 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 10784 mov r2, #0 @ r2<- false 10785 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 10786 bl dvmResolveClass @ r0<- resolved ClassObject ptr 10787 cmp r0, #0 @ got null? 10788 bne .LOP_NEW_INSTANCE_resolved @ no, continue 10789 b common_exceptionThrown @ yes, handle exception 10790 10791.LstrInstantiationErrorPtr: 10792 .word .LstrInstantiationError 10793 10794/* continuation for OP_NEW_ARRAY */ 10795 10796 10797 /* 10798 * Resolve class. (This is an uncommon case.) 10799 * 10800 * r1 holds array length 10801 * r2 holds class ref CCCC 10802 */ 10803.LOP_NEW_ARRAY_resolve: 10804 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 10805 mov r9, r1 @ r9<- length (save) 10806 mov r1, r2 @ r1<- CCCC 10807 mov r2, #0 @ r2<- false 10808 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 10809 bl dvmResolveClass @ r0<- call(clazz, ref) 10810 cmp r0, #0 @ got null? 10811 mov r1, r9 @ r1<- length (restore) 10812 beq common_exceptionThrown @ yes, handle exception 10813 @ fall through to OP_NEW_ARRAY_finish 10814 10815 /* 10816 * Finish allocation. 10817 * 10818 * r0 holds class 10819 * r1 holds array length 10820 */ 10821.LOP_NEW_ARRAY_finish: 10822 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 10823 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 10824 cmp r0, #0 @ failed? 10825 mov r2, rINST, lsr #8 @ r2<- A+ 10826 beq common_exceptionThrown @ yes, handle the exception 10827 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 10828 and r2, r2, #15 @ r2<- A 10829 GET_INST_OPCODE(ip) @ extract opcode from rINST 10830 SET_VREG(r0, r2) @ vA<- r0 10831 GOTO_OPCODE(ip) @ jump to next instruction 10832 10833/* continuation for OP_FILLED_NEW_ARRAY */ 10834 10835 /* 10836 * On entry: 10837 * r0 holds array class 10838 * r10 holds AA or BA 10839 */ 10840.LOP_FILLED_NEW_ARRAY_continue: 10841 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 10842 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 10843 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 10844 .if 0 10845 mov r1, r10 @ r1<- AA (length) 10846 .else 10847 mov r1, r10, lsr #4 @ r1<- B (length) 10848 .endif 10849 cmp rINST, #'I' @ array of ints? 10850 cmpne rINST, #'L' @ array of objects? 10851 cmpne rINST, #'[' @ array of arrays? 10852 mov r9, r1 @ save length in r9 10853 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 10854 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 10855 cmp r0, #0 @ null return? 10856 beq common_exceptionThrown @ alloc failed, handle exception 10857 10858 FETCH(r1, 2) @ r1<- FEDC or CCCC 10859 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 10860 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 10861 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 10862 subs r9, r9, #1 @ length--, check for neg 10863 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 10864 bmi 2f @ was zero, bail 10865 10866 @ copy values from registers into the array 10867 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 10868 .if 0 10869 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 108701: ldr r3, [r2], #4 @ r3<- *r2++ 10871 subs r9, r9, #1 @ count-- 10872 str r3, [r0], #4 @ *contents++ = vX 10873 bpl 1b 10874 @ continue at 2 10875 .else 10876 cmp r9, #4 @ length was initially 5? 10877 and r2, r10, #15 @ r2<- A 10878 bne 1f @ <= 4 args, branch 10879 GET_VREG(r3, r2) @ r3<- vA 10880 sub r9, r9, #1 @ count-- 10881 str r3, [r0, #16] @ contents[4] = vA 108821: and r2, r1, #15 @ r2<- F/E/D/C 10883 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 10884 mov r1, r1, lsr #4 @ r1<- next reg in low 4 10885 subs r9, r9, #1 @ count-- 10886 str r3, [r0], #4 @ *contents++ = vX 10887 bpl 1b 10888 @ continue at 2 10889 .endif 10890 108912: 10892 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 10893 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 10894 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 10895 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 10896 cmp r1, #'I' @ Is int array? 10897 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 10898 GOTO_OPCODE(ip) @ execute it 10899 10900 /* 10901 * Throw an exception indicating that we have not implemented this 10902 * mode of filled-new-array. 10903 */ 10904.LOP_FILLED_NEW_ARRAY_notimpl: 10905 ldr r0, .L_strInternalError 10906 ldr r1, .L_strFilledNewArrayNotImpl 10907 bl dvmThrowException 10908 b common_exceptionThrown 10909 10910 .if (!0) @ define in one or the other, not both 10911.L_strFilledNewArrayNotImpl: 10912 .word .LstrFilledNewArrayNotImpl 10913.L_strInternalError: 10914 .word .LstrInternalError 10915 .endif 10916 10917/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 10918 10919 /* 10920 * On entry: 10921 * r0 holds array class 10922 * r10 holds AA or BA 10923 */ 10924.LOP_FILLED_NEW_ARRAY_RANGE_continue: 10925 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 10926 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 10927 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 10928 .if 1 10929 mov r1, r10 @ r1<- AA (length) 10930 .else 10931 mov r1, r10, lsr #4 @ r1<- B (length) 10932 .endif 10933 cmp rINST, #'I' @ array of ints? 10934 cmpne rINST, #'L' @ array of objects? 10935 cmpne rINST, #'[' @ array of arrays? 10936 mov r9, r1 @ save length in r9 10937 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 10938 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 10939 cmp r0, #0 @ null return? 10940 beq common_exceptionThrown @ alloc failed, handle exception 10941 10942 FETCH(r1, 2) @ r1<- FEDC or CCCC 10943 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 10944 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 10945 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 10946 subs r9, r9, #1 @ length--, check for neg 10947 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 10948 bmi 2f @ was zero, bail 10949 10950 @ copy values from registers into the array 10951 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 10952 .if 1 10953 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 109541: ldr r3, [r2], #4 @ r3<- *r2++ 10955 subs r9, r9, #1 @ count-- 10956 str r3, [r0], #4 @ *contents++ = vX 10957 bpl 1b 10958 @ continue at 2 10959 .else 10960 cmp r9, #4 @ length was initially 5? 10961 and r2, r10, #15 @ r2<- A 10962 bne 1f @ <= 4 args, branch 10963 GET_VREG(r3, r2) @ r3<- vA 10964 sub r9, r9, #1 @ count-- 10965 str r3, [r0, #16] @ contents[4] = vA 109661: and r2, r1, #15 @ r2<- F/E/D/C 10967 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 10968 mov r1, r1, lsr #4 @ r1<- next reg in low 4 10969 subs r9, r9, #1 @ count-- 10970 str r3, [r0], #4 @ *contents++ = vX 10971 bpl 1b 10972 @ continue at 2 10973 .endif 10974 109752: 10976 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 10977 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 10978 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 10979 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 10980 cmp r1, #'I' @ Is int array? 10981 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 10982 GOTO_OPCODE(ip) @ execute it 10983 10984 /* 10985 * Throw an exception indicating that we have not implemented this 10986 * mode of filled-new-array. 10987 */ 10988.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 10989 ldr r0, .L_strInternalError 10990 ldr r1, .L_strFilledNewArrayNotImpl 10991 bl dvmThrowException 10992 b common_exceptionThrown 10993 10994 .if (!1) @ define in one or the other, not both 10995.L_strFilledNewArrayNotImpl: 10996 .word .LstrFilledNewArrayNotImpl 10997.L_strInternalError: 10998 .word .LstrInternalError 10999 .endif 11000 11001/* continuation for OP_CMPL_FLOAT */ 11002.LOP_CMPL_FLOAT_finish: 11003 SET_VREG(r0, r9) @ vAA<- r0 11004 GOTO_OPCODE(ip) @ jump to next instruction 11005 11006/* continuation for OP_CMPG_FLOAT */ 11007.LOP_CMPG_FLOAT_finish: 11008 SET_VREG(r0, r9) @ vAA<- r0 11009 GOTO_OPCODE(ip) @ jump to next instruction 11010 11011/* continuation for OP_CMPL_DOUBLE */ 11012.LOP_CMPL_DOUBLE_finish: 11013 SET_VREG(r0, r9) @ vAA<- r0 11014 GOTO_OPCODE(ip) @ jump to next instruction 11015 11016/* continuation for OP_CMPG_DOUBLE */ 11017.LOP_CMPG_DOUBLE_finish: 11018 SET_VREG(r0, r9) @ vAA<- r0 11019 GOTO_OPCODE(ip) @ jump to next instruction 11020 11021/* continuation for OP_CMP_LONG */ 11022 11023.LOP_CMP_LONG_less: 11024 mvn r1, #0 @ r1<- -1 11025 @ Want to cond code the next mov so we can avoid branch, but don't see it; 11026 @ instead, we just replicate the tail end. 11027 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11028 SET_VREG(r1, r9) @ vAA<- r1 11029 GET_INST_OPCODE(ip) @ extract opcode from rINST 11030 GOTO_OPCODE(ip) @ jump to next instruction 11031 11032.LOP_CMP_LONG_greater: 11033 mov r1, #1 @ r1<- 1 11034 @ fall through to _finish 11035 11036.LOP_CMP_LONG_finish: 11037 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11038 SET_VREG(r1, r9) @ vAA<- r1 11039 GET_INST_OPCODE(ip) @ extract opcode from rINST 11040 GOTO_OPCODE(ip) @ jump to next instruction 11041 11042/* continuation for OP_AGET_WIDE */ 11043 11044.LOP_AGET_WIDE_finish: 11045 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11046 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 11047 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 11048 GET_INST_OPCODE(ip) @ extract opcode from rINST 11049 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 11050 GOTO_OPCODE(ip) @ jump to next instruction 11051 11052/* continuation for OP_APUT_WIDE */ 11053 11054.LOP_APUT_WIDE_finish: 11055 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11056 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 11057 GET_INST_OPCODE(ip) @ extract opcode from rINST 11058 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 11059 GOTO_OPCODE(ip) @ jump to next instruction 11060 11061/* continuation for OP_APUT_OBJECT */ 11062 /* 11063 * On entry: 11064 * rINST = vBB (arrayObj) 11065 * r9 = vAA (obj) 11066 * r10 = offset into array (vBB + vCC * width) 11067 */ 11068.LOP_APUT_OBJECT_finish: 11069 cmp r9, #0 @ storing null reference? 11070 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 11071 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 11072 ldr r1, [rINST, #offObject_clazz] @ r1<- arrayObj->clazz 11073 bl dvmCanPutArrayElement @ test object type vs. array type 11074 cmp r0, #0 @ okay? 11075 beq .LOP_APUT_OBJECT_throw @ no 11076 mov r1, rINST @ r1<- arrayObj 11077 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11078 ldr r2, [rGLUE, #offGlue_cardTable] @ get biased CT base 11079 add r10, #offArrayObject_contents @ r0<- pointer to slot 11080 GET_INST_OPCODE(ip) @ extract opcode from rINST 11081 str r9, [r10] @ vBB[vCC]<- vAA 11082 strb r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head 11083 GOTO_OPCODE(ip) @ jump to next instruction 11084.LOP_APUT_OBJECT_skip_check: 11085 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11086 GET_INST_OPCODE(ip) @ extract opcode from rINST 11087 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 11088 GOTO_OPCODE(ip) @ jump to next instruction 11089.LOP_APUT_OBJECT_throw: 11090 @ The types don't match. We need to throw an ArrayStoreException. 11091 ldr r0, [r9, #offObject_clazz] 11092 ldr r1, [rINST, #offObject_clazz] 11093 EXPORT_PC() 11094 bl dvmThrowArrayStoreException 11095 b common_exceptionThrown 11096 11097/* continuation for OP_IGET */ 11098 11099 /* 11100 * Currently: 11101 * r0 holds resolved field 11102 * r9 holds object 11103 */ 11104.LOP_IGET_finish: 11105 @bl common_squeak0 11106 cmp r9, #0 @ check object for null 11107 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11108 beq common_errNullObject @ object was null 11109 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11110 @ no-op @ acquiring load 11111 mov r2, rINST, lsr #8 @ r2<- A+ 11112 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11113 and r2, r2, #15 @ r2<- A 11114 GET_INST_OPCODE(ip) @ extract opcode from rINST 11115 SET_VREG(r0, r2) @ fp[A]<- r0 11116 GOTO_OPCODE(ip) @ jump to next instruction 11117 11118/* continuation for OP_IGET_WIDE */ 11119 11120 /* 11121 * Currently: 11122 * r0 holds resolved field 11123 * r9 holds object 11124 */ 11125.LOP_IGET_WIDE_finish: 11126 cmp r9, #0 @ check object for null 11127 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11128 beq common_errNullObject @ object was null 11129 .if 0 11130 add r0, r9, r3 @ r0<- address of field 11131 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 11132 .else 11133 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 11134 .endif 11135 mov r2, rINST, lsr #8 @ r2<- A+ 11136 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11137 and r2, r2, #15 @ r2<- A 11138 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 11139 GET_INST_OPCODE(ip) @ extract opcode from rINST 11140 stmia r3, {r0-r1} @ fp[A]<- r0/r1 11141 GOTO_OPCODE(ip) @ jump to next instruction 11142 11143/* continuation for OP_IGET_OBJECT */ 11144 11145 /* 11146 * Currently: 11147 * r0 holds resolved field 11148 * r9 holds object 11149 */ 11150.LOP_IGET_OBJECT_finish: 11151 @bl common_squeak0 11152 cmp r9, #0 @ check object for null 11153 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11154 beq common_errNullObject @ object was null 11155 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11156 @ no-op @ acquiring load 11157 mov r2, rINST, lsr #8 @ r2<- A+ 11158 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11159 and r2, r2, #15 @ r2<- A 11160 GET_INST_OPCODE(ip) @ extract opcode from rINST 11161 SET_VREG(r0, r2) @ fp[A]<- r0 11162 GOTO_OPCODE(ip) @ jump to next instruction 11163 11164/* continuation for OP_IGET_BOOLEAN */ 11165 11166 /* 11167 * Currently: 11168 * r0 holds resolved field 11169 * r9 holds object 11170 */ 11171.LOP_IGET_BOOLEAN_finish: 11172 @bl common_squeak1 11173 cmp r9, #0 @ check object for null 11174 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11175 beq common_errNullObject @ object was null 11176 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11177 @ no-op @ acquiring load 11178 mov r2, rINST, lsr #8 @ r2<- A+ 11179 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11180 and r2, r2, #15 @ r2<- A 11181 GET_INST_OPCODE(ip) @ extract opcode from rINST 11182 SET_VREG(r0, r2) @ fp[A]<- r0 11183 GOTO_OPCODE(ip) @ jump to next instruction 11184 11185/* continuation for OP_IGET_BYTE */ 11186 11187 /* 11188 * Currently: 11189 * r0 holds resolved field 11190 * r9 holds object 11191 */ 11192.LOP_IGET_BYTE_finish: 11193 @bl common_squeak2 11194 cmp r9, #0 @ check object for null 11195 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11196 beq common_errNullObject @ object was null 11197 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11198 @ no-op @ acquiring load 11199 mov r2, rINST, lsr #8 @ r2<- A+ 11200 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11201 and r2, r2, #15 @ r2<- A 11202 GET_INST_OPCODE(ip) @ extract opcode from rINST 11203 SET_VREG(r0, r2) @ fp[A]<- r0 11204 GOTO_OPCODE(ip) @ jump to next instruction 11205 11206/* continuation for OP_IGET_CHAR */ 11207 11208 /* 11209 * Currently: 11210 * r0 holds resolved field 11211 * r9 holds object 11212 */ 11213.LOP_IGET_CHAR_finish: 11214 @bl common_squeak3 11215 cmp r9, #0 @ check object for null 11216 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11217 beq common_errNullObject @ object was null 11218 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11219 @ no-op @ acquiring load 11220 mov r2, rINST, lsr #8 @ r2<- A+ 11221 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11222 and r2, r2, #15 @ r2<- A 11223 GET_INST_OPCODE(ip) @ extract opcode from rINST 11224 SET_VREG(r0, r2) @ fp[A]<- r0 11225 GOTO_OPCODE(ip) @ jump to next instruction 11226 11227/* continuation for OP_IGET_SHORT */ 11228 11229 /* 11230 * Currently: 11231 * r0 holds resolved field 11232 * r9 holds object 11233 */ 11234.LOP_IGET_SHORT_finish: 11235 @bl common_squeak4 11236 cmp r9, #0 @ check object for null 11237 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11238 beq common_errNullObject @ object was null 11239 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11240 @ no-op @ acquiring load 11241 mov r2, rINST, lsr #8 @ r2<- A+ 11242 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11243 and r2, r2, #15 @ r2<- A 11244 GET_INST_OPCODE(ip) @ extract opcode from rINST 11245 SET_VREG(r0, r2) @ fp[A]<- r0 11246 GOTO_OPCODE(ip) @ jump to next instruction 11247 11248/* continuation for OP_IPUT */ 11249 11250 /* 11251 * Currently: 11252 * r0 holds resolved field 11253 * r9 holds object 11254 */ 11255.LOP_IPUT_finish: 11256 @bl common_squeak0 11257 mov r1, rINST, lsr #8 @ r1<- A+ 11258 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11259 and r1, r1, #15 @ r1<- A 11260 cmp r9, #0 @ check object for null 11261 GET_VREG(r0, r1) @ r0<- fp[A] 11262 beq common_errNullObject @ object was null 11263 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11264 GET_INST_OPCODE(ip) @ extract opcode from rINST 11265 @ no-op @ releasing store 11266 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 11267 GOTO_OPCODE(ip) @ jump to next instruction 11268 11269/* continuation for OP_IPUT_WIDE */ 11270 11271 /* 11272 * Currently: 11273 * r0 holds resolved field 11274 * r9 holds object 11275 */ 11276.LOP_IPUT_WIDE_finish: 11277 mov r2, rINST, lsr #8 @ r2<- A+ 11278 cmp r9, #0 @ check object for null 11279 and r2, r2, #15 @ r2<- A 11280 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11281 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 11282 beq common_errNullObject @ object was null 11283 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11284 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 11285 GET_INST_OPCODE(r10) @ extract opcode from rINST 11286 .if 0 11287 add r2, r9, r3 @ r2<- target address 11288 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 11289 .else 11290 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 11291 .endif 11292 GOTO_OPCODE(r10) @ jump to next instruction 11293 11294/* continuation for OP_IPUT_OBJECT */ 11295 11296 /* 11297 * Currently: 11298 * r0 holds resolved field 11299 * r9 holds object 11300 */ 11301.LOP_IPUT_OBJECT_finish: 11302 @bl common_squeak0 11303 mov r1, rINST, lsr #8 @ r1<- A+ 11304 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11305 and r1, r1, #15 @ r1<- A 11306 cmp r9, #0 @ check object for null 11307 GET_VREG(r0, r1) @ r0<- fp[A] 11308 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 11309 beq common_errNullObject @ object was null 11310 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11311 GET_INST_OPCODE(ip) @ extract opcode from rINST 11312 @ no-op @ releasing store 11313 str r0, [r9, r3] @ obj.field (32 bits)<- r0 11314 cmp r0, #0 @ stored a null reference? 11315 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 11316 GOTO_OPCODE(ip) @ jump to next instruction 11317 11318/* continuation for OP_IPUT_BOOLEAN */ 11319 11320 /* 11321 * Currently: 11322 * r0 holds resolved field 11323 * r9 holds object 11324 */ 11325.LOP_IPUT_BOOLEAN_finish: 11326 @bl common_squeak1 11327 mov r1, rINST, lsr #8 @ r1<- A+ 11328 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11329 and r1, r1, #15 @ r1<- A 11330 cmp r9, #0 @ check object for null 11331 GET_VREG(r0, r1) @ r0<- fp[A] 11332 beq common_errNullObject @ object was null 11333 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11334 GET_INST_OPCODE(ip) @ extract opcode from rINST 11335 @ no-op @ releasing store 11336 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 11337 GOTO_OPCODE(ip) @ jump to next instruction 11338 11339/* continuation for OP_IPUT_BYTE */ 11340 11341 /* 11342 * Currently: 11343 * r0 holds resolved field 11344 * r9 holds object 11345 */ 11346.LOP_IPUT_BYTE_finish: 11347 @bl common_squeak2 11348 mov r1, rINST, lsr #8 @ r1<- A+ 11349 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11350 and r1, r1, #15 @ r1<- A 11351 cmp r9, #0 @ check object for null 11352 GET_VREG(r0, r1) @ r0<- fp[A] 11353 beq common_errNullObject @ object was null 11354 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11355 GET_INST_OPCODE(ip) @ extract opcode from rINST 11356 @ no-op @ releasing store 11357 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 11358 GOTO_OPCODE(ip) @ jump to next instruction 11359 11360/* continuation for OP_IPUT_CHAR */ 11361 11362 /* 11363 * Currently: 11364 * r0 holds resolved field 11365 * r9 holds object 11366 */ 11367.LOP_IPUT_CHAR_finish: 11368 @bl common_squeak3 11369 mov r1, rINST, lsr #8 @ r1<- A+ 11370 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11371 and r1, r1, #15 @ r1<- A 11372 cmp r9, #0 @ check object for null 11373 GET_VREG(r0, r1) @ r0<- fp[A] 11374 beq common_errNullObject @ object was null 11375 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11376 GET_INST_OPCODE(ip) @ extract opcode from rINST 11377 @ no-op @ releasing store 11378 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 11379 GOTO_OPCODE(ip) @ jump to next instruction 11380 11381/* continuation for OP_IPUT_SHORT */ 11382 11383 /* 11384 * Currently: 11385 * r0 holds resolved field 11386 * r9 holds object 11387 */ 11388.LOP_IPUT_SHORT_finish: 11389 @bl common_squeak4 11390 mov r1, rINST, lsr #8 @ r1<- A+ 11391 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11392 and r1, r1, #15 @ r1<- A 11393 cmp r9, #0 @ check object for null 11394 GET_VREG(r0, r1) @ r0<- fp[A] 11395 beq common_errNullObject @ object was null 11396 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11397 GET_INST_OPCODE(ip) @ extract opcode from rINST 11398 @ no-op @ releasing store 11399 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 11400 GOTO_OPCODE(ip) @ jump to next instruction 11401 11402/* continuation for OP_SGET */ 11403 11404 /* 11405 * Continuation if the field has not yet been resolved. 11406 * r1: BBBB field ref 11407 */ 11408.LOP_SGET_resolve: 11409 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11410 EXPORT_PC() @ resolve() could throw, so export now 11411 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11412 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11413 cmp r0, #0 @ success? 11414 bne .LOP_SGET_finish @ yes, finish 11415 b common_exceptionThrown @ no, handle exception 11416 11417/* continuation for OP_SGET_WIDE */ 11418 11419 /* 11420 * Continuation if the field has not yet been resolved. 11421 * r1: BBBB field ref 11422 * 11423 * Returns StaticField pointer in r0. 11424 */ 11425.LOP_SGET_WIDE_resolve: 11426 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11427 EXPORT_PC() @ resolve() could throw, so export now 11428 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11429 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11430 cmp r0, #0 @ success? 11431 bne .LOP_SGET_WIDE_finish @ yes, finish 11432 b common_exceptionThrown @ no, handle exception 11433 11434/* continuation for OP_SGET_OBJECT */ 11435 11436 /* 11437 * Continuation if the field has not yet been resolved. 11438 * r1: BBBB field ref 11439 */ 11440.LOP_SGET_OBJECT_resolve: 11441 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11442 EXPORT_PC() @ resolve() could throw, so export now 11443 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11444 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11445 cmp r0, #0 @ success? 11446 bne .LOP_SGET_OBJECT_finish @ yes, finish 11447 b common_exceptionThrown @ no, handle exception 11448 11449/* continuation for OP_SGET_BOOLEAN */ 11450 11451 /* 11452 * Continuation if the field has not yet been resolved. 11453 * r1: BBBB field ref 11454 */ 11455.LOP_SGET_BOOLEAN_resolve: 11456 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11457 EXPORT_PC() @ resolve() could throw, so export now 11458 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11459 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11460 cmp r0, #0 @ success? 11461 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 11462 b common_exceptionThrown @ no, handle exception 11463 11464/* continuation for OP_SGET_BYTE */ 11465 11466 /* 11467 * Continuation if the field has not yet been resolved. 11468 * r1: BBBB field ref 11469 */ 11470.LOP_SGET_BYTE_resolve: 11471 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11472 EXPORT_PC() @ resolve() could throw, so export now 11473 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11474 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11475 cmp r0, #0 @ success? 11476 bne .LOP_SGET_BYTE_finish @ yes, finish 11477 b common_exceptionThrown @ no, handle exception 11478 11479/* continuation for OP_SGET_CHAR */ 11480 11481 /* 11482 * Continuation if the field has not yet been resolved. 11483 * r1: BBBB field ref 11484 */ 11485.LOP_SGET_CHAR_resolve: 11486 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11487 EXPORT_PC() @ resolve() could throw, so export now 11488 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11489 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11490 cmp r0, #0 @ success? 11491 bne .LOP_SGET_CHAR_finish @ yes, finish 11492 b common_exceptionThrown @ no, handle exception 11493 11494/* continuation for OP_SGET_SHORT */ 11495 11496 /* 11497 * Continuation if the field has not yet been resolved. 11498 * r1: BBBB field ref 11499 */ 11500.LOP_SGET_SHORT_resolve: 11501 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11502 EXPORT_PC() @ resolve() could throw, so export now 11503 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11504 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11505 cmp r0, #0 @ success? 11506 bne .LOP_SGET_SHORT_finish @ yes, finish 11507 b common_exceptionThrown @ no, handle exception 11508 11509/* continuation for OP_SPUT */ 11510 11511 /* 11512 * Continuation if the field has not yet been resolved. 11513 * r1: BBBB field ref 11514 */ 11515.LOP_SPUT_resolve: 11516 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11517 EXPORT_PC() @ resolve() could throw, so export now 11518 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11519 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11520 cmp r0, #0 @ success? 11521 bne .LOP_SPUT_finish @ yes, finish 11522 b common_exceptionThrown @ no, handle exception 11523 11524/* continuation for OP_SPUT_WIDE */ 11525 11526 /* 11527 * Continuation if the field has not yet been resolved. 11528 * r1: BBBB field ref 11529 * r9: &fp[AA] 11530 * 11531 * Returns StaticField pointer in r2. 11532 */ 11533.LOP_SPUT_WIDE_resolve: 11534 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11535 EXPORT_PC() @ resolve() could throw, so export now 11536 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11537 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11538 cmp r0, #0 @ success? 11539 mov r2, r0 @ copy to r2 11540 bne .LOP_SPUT_WIDE_finish @ yes, finish 11541 b common_exceptionThrown @ no, handle exception 11542 11543/* continuation for OP_SPUT_OBJECT */ 11544.LOP_SPUT_OBJECT_finish: @ field ptr in r0 11545 mov r2, rINST, lsr #8 @ r2<- AA 11546 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11547 GET_VREG(r1, r2) @ r1<- fp[AA] 11548 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 11549 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz 11550 GET_INST_OPCODE(ip) @ extract opcode from rINST 11551 @ no-op @ releasing store 11552 str r1, [r0, #offStaticField_value] @ field<- vAA 11553 cmp r1, #0 @ stored a null object? 11554 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 11555 GOTO_OPCODE(ip) @ jump to next instruction 11556 11557/* continuation for OP_SPUT_BOOLEAN */ 11558 11559 /* 11560 * Continuation if the field has not yet been resolved. 11561 * r1: BBBB field ref 11562 */ 11563.LOP_SPUT_BOOLEAN_resolve: 11564 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11565 EXPORT_PC() @ resolve() could throw, so export now 11566 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11567 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11568 cmp r0, #0 @ success? 11569 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 11570 b common_exceptionThrown @ no, handle exception 11571 11572/* continuation for OP_SPUT_BYTE */ 11573 11574 /* 11575 * Continuation if the field has not yet been resolved. 11576 * r1: BBBB field ref 11577 */ 11578.LOP_SPUT_BYTE_resolve: 11579 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11580 EXPORT_PC() @ resolve() could throw, so export now 11581 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11582 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11583 cmp r0, #0 @ success? 11584 bne .LOP_SPUT_BYTE_finish @ yes, finish 11585 b common_exceptionThrown @ no, handle exception 11586 11587/* continuation for OP_SPUT_CHAR */ 11588 11589 /* 11590 * Continuation if the field has not yet been resolved. 11591 * r1: BBBB field ref 11592 */ 11593.LOP_SPUT_CHAR_resolve: 11594 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11595 EXPORT_PC() @ resolve() could throw, so export now 11596 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11597 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11598 cmp r0, #0 @ success? 11599 bne .LOP_SPUT_CHAR_finish @ yes, finish 11600 b common_exceptionThrown @ no, handle exception 11601 11602/* continuation for OP_SPUT_SHORT */ 11603 11604 /* 11605 * Continuation if the field has not yet been resolved. 11606 * r1: BBBB field ref 11607 */ 11608.LOP_SPUT_SHORT_resolve: 11609 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11610 EXPORT_PC() @ resolve() could throw, so export now 11611 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11612 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11613 cmp r0, #0 @ success? 11614 bne .LOP_SPUT_SHORT_finish @ yes, finish 11615 b common_exceptionThrown @ no, handle exception 11616 11617/* continuation for OP_INVOKE_VIRTUAL */ 11618 11619 /* 11620 * At this point: 11621 * r0 = resolved base method 11622 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 11623 */ 11624.LOP_INVOKE_VIRTUAL_continue: 11625 GET_VREG(r1, r10) @ r1<- "this" ptr 11626 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 11627 cmp r1, #0 @ is "this" null? 11628 beq common_errNullObject @ null "this", throw exception 11629 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 11630 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 11631 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 11632 bl common_invokeMethodNoRange @ continue on 11633 11634/* continuation for OP_INVOKE_SUPER */ 11635 11636 /* 11637 * At this point: 11638 * r0 = resolved base method 11639 * r9 = method->clazz 11640 */ 11641.LOP_INVOKE_SUPER_continue: 11642 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 11643 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 11644 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 11645 EXPORT_PC() @ must export for invoke 11646 cmp r2, r3 @ compare (methodIndex, vtableCount) 11647 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 11648 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 11649 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 11650 bl common_invokeMethodNoRange @ continue on 11651 11652.LOP_INVOKE_SUPER_resolve: 11653 mov r0, r9 @ r0<- method->clazz 11654 mov r2, #METHOD_VIRTUAL @ resolver method type 11655 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 11656 cmp r0, #0 @ got null? 11657 bne .LOP_INVOKE_SUPER_continue @ no, continue 11658 b common_exceptionThrown @ yes, handle exception 11659 11660 /* 11661 * Throw a NoSuchMethodError with the method name as the message. 11662 * r0 = resolved base method 11663 */ 11664.LOP_INVOKE_SUPER_nsm: 11665 ldr r1, [r0, #offMethod_name] @ r1<- method name 11666 b common_errNoSuchMethod 11667 11668/* continuation for OP_INVOKE_DIRECT */ 11669 11670 /* 11671 * On entry: 11672 * r1 = reference (BBBB or CCCC) 11673 * r10 = "this" register 11674 */ 11675.LOP_INVOKE_DIRECT_resolve: 11676 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 11677 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 11678 mov r2, #METHOD_DIRECT @ resolver method type 11679 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 11680 cmp r0, #0 @ got null? 11681 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 11682 bne .LOP_INVOKE_DIRECT_finish @ no, continue 11683 b common_exceptionThrown @ yes, handle exception 11684 11685/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 11686 11687 /* 11688 * At this point: 11689 * r0 = resolved base method 11690 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 11691 */ 11692.LOP_INVOKE_VIRTUAL_RANGE_continue: 11693 GET_VREG(r1, r10) @ r1<- "this" ptr 11694 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 11695 cmp r1, #0 @ is "this" null? 11696 beq common_errNullObject @ null "this", throw exception 11697 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 11698 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 11699 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 11700 bl common_invokeMethodRange @ continue on 11701 11702/* continuation for OP_INVOKE_SUPER_RANGE */ 11703 11704 /* 11705 * At this point: 11706 * r0 = resolved base method 11707 * r9 = method->clazz 11708 */ 11709.LOP_INVOKE_SUPER_RANGE_continue: 11710 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 11711 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 11712 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 11713 EXPORT_PC() @ must export for invoke 11714 cmp r2, r3 @ compare (methodIndex, vtableCount) 11715 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 11716 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 11717 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 11718 bl common_invokeMethodRange @ continue on 11719 11720.LOP_INVOKE_SUPER_RANGE_resolve: 11721 mov r0, r9 @ r0<- method->clazz 11722 mov r2, #METHOD_VIRTUAL @ resolver method type 11723 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 11724 cmp r0, #0 @ got null? 11725 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 11726 b common_exceptionThrown @ yes, handle exception 11727 11728 /* 11729 * Throw a NoSuchMethodError with the method name as the message. 11730 * r0 = resolved base method 11731 */ 11732.LOP_INVOKE_SUPER_RANGE_nsm: 11733 ldr r1, [r0, #offMethod_name] @ r1<- method name 11734 b common_errNoSuchMethod 11735 11736/* continuation for OP_INVOKE_DIRECT_RANGE */ 11737 11738 /* 11739 * On entry: 11740 * r1 = reference (BBBB or CCCC) 11741 * r10 = "this" register 11742 */ 11743.LOP_INVOKE_DIRECT_RANGE_resolve: 11744 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 11745 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 11746 mov r2, #METHOD_DIRECT @ resolver method type 11747 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 11748 cmp r0, #0 @ got null? 11749 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 11750 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 11751 b common_exceptionThrown @ yes, handle exception 11752 11753/* continuation for OP_FLOAT_TO_LONG */ 11754/* 11755 * Convert the float in r0 to a long in r0/r1. 11756 * 11757 * We have to clip values to long min/max per the specification. The 11758 * expected common case is a "reasonable" value that converts directly 11759 * to modest integer. The EABI convert function isn't doing this for us. 11760 */ 11761f2l_doconv: 11762 stmfd sp!, {r4, lr} 11763 mov r1, #0x5f000000 @ (float)maxlong 11764 mov r4, r0 11765 bl __aeabi_fcmpge @ is arg >= maxlong? 11766 cmp r0, #0 @ nonzero == yes 11767 mvnne r0, #0 @ return maxlong (7fffffff) 11768 mvnne r1, #0x80000000 11769 ldmnefd sp!, {r4, pc} 11770 11771 mov r0, r4 @ recover arg 11772 mov r1, #0xdf000000 @ (float)minlong 11773 bl __aeabi_fcmple @ is arg <= minlong? 11774 cmp r0, #0 @ nonzero == yes 11775 movne r0, #0 @ return minlong (80000000) 11776 movne r1, #0x80000000 11777 ldmnefd sp!, {r4, pc} 11778 11779 mov r0, r4 @ recover arg 11780 mov r1, r4 11781 bl __aeabi_fcmpeq @ is arg == self? 11782 cmp r0, #0 @ zero == no 11783 moveq r1, #0 @ return zero for NaN 11784 ldmeqfd sp!, {r4, pc} 11785 11786 mov r0, r4 @ recover arg 11787 bl __aeabi_f2lz @ convert float to long 11788 ldmfd sp!, {r4, pc} 11789 11790/* continuation for OP_DOUBLE_TO_LONG */ 11791/* 11792 * Convert the double in r0/r1 to a long in r0/r1. 11793 * 11794 * We have to clip values to long min/max per the specification. The 11795 * expected common case is a "reasonable" value that converts directly 11796 * to modest integer. The EABI convert function isn't doing this for us. 11797 */ 11798d2l_doconv: 11799 stmfd sp!, {r4, r5, lr} @ save regs 11800 mov r3, #0x43000000 @ maxlong, as a double (high word) 11801 add r3, #0x00e00000 @ 0x43e00000 11802 mov r2, #0 @ maxlong, as a double (low word) 11803 sub sp, sp, #4 @ align for EABI 11804 mov r4, r0 @ save a copy of r0 11805 mov r5, r1 @ and r1 11806 bl __aeabi_dcmpge @ is arg >= maxlong? 11807 cmp r0, #0 @ nonzero == yes 11808 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 11809 mvnne r1, #0x80000000 11810 bne 1f 11811 11812 mov r0, r4 @ recover arg 11813 mov r1, r5 11814 mov r3, #0xc3000000 @ minlong, as a double (high word) 11815 add r3, #0x00e00000 @ 0xc3e00000 11816 mov r2, #0 @ minlong, as a double (low word) 11817 bl __aeabi_dcmple @ is arg <= minlong? 11818 cmp r0, #0 @ nonzero == yes 11819 movne r0, #0 @ return minlong (8000000000000000) 11820 movne r1, #0x80000000 11821 bne 1f 11822 11823 mov r0, r4 @ recover arg 11824 mov r1, r5 11825 mov r2, r4 @ compare against self 11826 mov r3, r5 11827 bl __aeabi_dcmpeq @ is arg == self? 11828 cmp r0, #0 @ zero == no 11829 moveq r1, #0 @ return zero for NaN 11830 beq 1f 11831 11832 mov r0, r4 @ recover arg 11833 mov r1, r5 11834 bl __aeabi_d2lz @ convert double to long 11835 118361: 11837 add sp, sp, #4 11838 ldmfd sp!, {r4, r5, pc} 11839 11840/* continuation for OP_MUL_LONG */ 11841 11842.LOP_MUL_LONG_finish: 11843 GET_INST_OPCODE(ip) @ extract opcode from rINST 11844 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 11845 GOTO_OPCODE(ip) @ jump to next instruction 11846 11847/* continuation for OP_SHL_LONG */ 11848 11849.LOP_SHL_LONG_finish: 11850 mov r0, r0, asl r2 @ r0<- r0 << r2 11851 GET_INST_OPCODE(ip) @ extract opcode from rINST 11852 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 11853 GOTO_OPCODE(ip) @ jump to next instruction 11854 11855/* continuation for OP_SHR_LONG */ 11856 11857.LOP_SHR_LONG_finish: 11858 mov r1, r1, asr r2 @ r1<- r1 >> r2 11859 GET_INST_OPCODE(ip) @ extract opcode from rINST 11860 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 11861 GOTO_OPCODE(ip) @ jump to next instruction 11862 11863/* continuation for OP_USHR_LONG */ 11864 11865.LOP_USHR_LONG_finish: 11866 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 11867 GET_INST_OPCODE(ip) @ extract opcode from rINST 11868 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 11869 GOTO_OPCODE(ip) @ jump to next instruction 11870 11871/* continuation for OP_SHL_LONG_2ADDR */ 11872 11873.LOP_SHL_LONG_2ADDR_finish: 11874 GET_INST_OPCODE(ip) @ extract opcode from rINST 11875 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 11876 GOTO_OPCODE(ip) @ jump to next instruction 11877 11878/* continuation for OP_SHR_LONG_2ADDR */ 11879 11880.LOP_SHR_LONG_2ADDR_finish: 11881 GET_INST_OPCODE(ip) @ extract opcode from rINST 11882 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 11883 GOTO_OPCODE(ip) @ jump to next instruction 11884 11885/* continuation for OP_USHR_LONG_2ADDR */ 11886 11887.LOP_USHR_LONG_2ADDR_finish: 11888 GET_INST_OPCODE(ip) @ extract opcode from rINST 11889 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 11890 GOTO_OPCODE(ip) @ jump to next instruction 11891 11892/* continuation for OP_IGET_VOLATILE */ 11893 11894 /* 11895 * Currently: 11896 * r0 holds resolved field 11897 * r9 holds object 11898 */ 11899.LOP_IGET_VOLATILE_finish: 11900 @bl common_squeak0 11901 cmp r9, #0 @ check object for null 11902 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11903 beq common_errNullObject @ object was null 11904 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11905 SMP_DMB @ acquiring load 11906 mov r2, rINST, lsr #8 @ r2<- A+ 11907 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11908 and r2, r2, #15 @ r2<- A 11909 GET_INST_OPCODE(ip) @ extract opcode from rINST 11910 SET_VREG(r0, r2) @ fp[A]<- r0 11911 GOTO_OPCODE(ip) @ jump to next instruction 11912 11913/* continuation for OP_IPUT_VOLATILE */ 11914 11915 /* 11916 * Currently: 11917 * r0 holds resolved field 11918 * r9 holds object 11919 */ 11920.LOP_IPUT_VOLATILE_finish: 11921 @bl common_squeak0 11922 mov r1, rINST, lsr #8 @ r1<- A+ 11923 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11924 and r1, r1, #15 @ r1<- A 11925 cmp r9, #0 @ check object for null 11926 GET_VREG(r0, r1) @ r0<- fp[A] 11927 beq common_errNullObject @ object was null 11928 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11929 GET_INST_OPCODE(ip) @ extract opcode from rINST 11930 SMP_DMB @ releasing store 11931 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 11932 GOTO_OPCODE(ip) @ jump to next instruction 11933 11934/* continuation for OP_SGET_VOLATILE */ 11935 11936 /* 11937 * Continuation if the field has not yet been resolved. 11938 * r1: BBBB field ref 11939 */ 11940.LOP_SGET_VOLATILE_resolve: 11941 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11942 EXPORT_PC() @ resolve() could throw, so export now 11943 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11944 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11945 cmp r0, #0 @ success? 11946 bne .LOP_SGET_VOLATILE_finish @ yes, finish 11947 b common_exceptionThrown @ no, handle exception 11948 11949/* continuation for OP_SPUT_VOLATILE */ 11950 11951 /* 11952 * Continuation if the field has not yet been resolved. 11953 * r1: BBBB field ref 11954 */ 11955.LOP_SPUT_VOLATILE_resolve: 11956 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11957 EXPORT_PC() @ resolve() could throw, so export now 11958 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11959 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11960 cmp r0, #0 @ success? 11961 bne .LOP_SPUT_VOLATILE_finish @ yes, finish 11962 b common_exceptionThrown @ no, handle exception 11963 11964/* continuation for OP_IGET_OBJECT_VOLATILE */ 11965 11966 /* 11967 * Currently: 11968 * r0 holds resolved field 11969 * r9 holds object 11970 */ 11971.LOP_IGET_OBJECT_VOLATILE_finish: 11972 @bl common_squeak0 11973 cmp r9, #0 @ check object for null 11974 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11975 beq common_errNullObject @ object was null 11976 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11977 SMP_DMB @ acquiring load 11978 mov r2, rINST, lsr #8 @ r2<- A+ 11979 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11980 and r2, r2, #15 @ r2<- A 11981 GET_INST_OPCODE(ip) @ extract opcode from rINST 11982 SET_VREG(r0, r2) @ fp[A]<- r0 11983 GOTO_OPCODE(ip) @ jump to next instruction 11984 11985/* continuation for OP_IGET_WIDE_VOLATILE */ 11986 11987 /* 11988 * Currently: 11989 * r0 holds resolved field 11990 * r9 holds object 11991 */ 11992.LOP_IGET_WIDE_VOLATILE_finish: 11993 cmp r9, #0 @ check object for null 11994 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11995 beq common_errNullObject @ object was null 11996 .if 1 11997 add r0, r9, r3 @ r0<- address of field 11998 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 11999 .else 12000 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 12001 .endif 12002 mov r2, rINST, lsr #8 @ r2<- A+ 12003 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 12004 and r2, r2, #15 @ r2<- A 12005 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 12006 GET_INST_OPCODE(ip) @ extract opcode from rINST 12007 stmia r3, {r0-r1} @ fp[A]<- r0/r1 12008 GOTO_OPCODE(ip) @ jump to next instruction 12009 12010/* continuation for OP_IPUT_WIDE_VOLATILE */ 12011 12012 /* 12013 * Currently: 12014 * r0 holds resolved field 12015 * r9 holds object 12016 */ 12017.LOP_IPUT_WIDE_VOLATILE_finish: 12018 mov r2, rINST, lsr #8 @ r2<- A+ 12019 cmp r9, #0 @ check object for null 12020 and r2, r2, #15 @ r2<- A 12021 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12022 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 12023 beq common_errNullObject @ object was null 12024 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 12025 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 12026 GET_INST_OPCODE(r10) @ extract opcode from rINST 12027 .if 1 12028 add r2, r9, r3 @ r2<- target address 12029 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 12030 .else 12031 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 12032 .endif 12033 GOTO_OPCODE(r10) @ jump to next instruction 12034 12035/* continuation for OP_SGET_WIDE_VOLATILE */ 12036 12037 /* 12038 * Continuation if the field has not yet been resolved. 12039 * r1: BBBB field ref 12040 * 12041 * Returns StaticField pointer in r0. 12042 */ 12043.LOP_SGET_WIDE_VOLATILE_resolve: 12044 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12045 EXPORT_PC() @ resolve() could throw, so export now 12046 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12047 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12048 cmp r0, #0 @ success? 12049 bne .LOP_SGET_WIDE_VOLATILE_finish @ yes, finish 12050 b common_exceptionThrown @ no, handle exception 12051 12052/* continuation for OP_SPUT_WIDE_VOLATILE */ 12053 12054 /* 12055 * Continuation if the field has not yet been resolved. 12056 * r1: BBBB field ref 12057 * r9: &fp[AA] 12058 * 12059 * Returns StaticField pointer in r2. 12060 */ 12061.LOP_SPUT_WIDE_VOLATILE_resolve: 12062 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12063 EXPORT_PC() @ resolve() could throw, so export now 12064 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12065 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12066 cmp r0, #0 @ success? 12067 mov r2, r0 @ copy to r2 12068 bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish 12069 b common_exceptionThrown @ no, handle exception 12070 12071/* continuation for OP_EXECUTE_INLINE */ 12072 12073 /* 12074 * Extract args, call function. 12075 * r0 = #of args (0-4) 12076 * r10 = call index 12077 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 12078 * 12079 * Other ideas: 12080 * - Use a jump table from the main piece to jump directly into the 12081 * AND/LDR pairs. Costs a data load, saves a branch. 12082 * - Have five separate pieces that do the loading, so we can work the 12083 * interleave a little better. Increases code size. 12084 */ 12085.LOP_EXECUTE_INLINE_continue: 12086 rsb r0, r0, #4 @ r0<- 4-r0 12087 FETCH(r9, 2) @ r9<- FEDC 12088 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 12089 bl common_abort @ (skipped due to ARM prefetch) 120904: and ip, r9, #0xf000 @ isolate F 12091 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 120923: and ip, r9, #0x0f00 @ isolate E 12093 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 120942: and ip, r9, #0x00f0 @ isolate D 12095 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 120961: and ip, r9, #0x000f @ isolate C 12097 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 120980: 12099 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 12100 ldr pc, [r9, r10, lsl #4] @ sizeof=16, "func" is first entry 12101 @ (not reached) 12102 12103.LOP_EXECUTE_INLINE_table: 12104 .word gDvmInlineOpsTable 12105 12106/* continuation for OP_EXECUTE_INLINE_RANGE */ 12107 12108 /* 12109 * Extract args, call function. 12110 * r0 = #of args (0-4) 12111 * r10 = call index 12112 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 12113 */ 12114.LOP_EXECUTE_INLINE_RANGE_continue: 12115 rsb r0, r0, #4 @ r0<- 4-r0 12116 FETCH(r9, 2) @ r9<- CCCC 12117 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 12118 bl common_abort @ (skipped due to ARM prefetch) 121194: add ip, r9, #3 @ base+3 12120 GET_VREG(r3, ip) @ r3<- vBase[3] 121213: add ip, r9, #2 @ base+2 12122 GET_VREG(r2, ip) @ r2<- vBase[2] 121232: add ip, r9, #1 @ base+1 12124 GET_VREG(r1, ip) @ r1<- vBase[1] 121251: add ip, r9, #0 @ (nop) 12126 GET_VREG(r0, ip) @ r0<- vBase[0] 121270: 12128 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation 12129 ldr pc, [r9, r10, lsl #4] @ sizeof=16, "func" is first entry 12130 @ (not reached) 12131 12132.LOP_EXECUTE_INLINE_RANGE_table: 12133 .word gDvmInlineOpsTable 12134 12135/* continuation for OP_IPUT_OBJECT_VOLATILE */ 12136 12137 /* 12138 * Currently: 12139 * r0 holds resolved field 12140 * r9 holds object 12141 */ 12142.LOP_IPUT_OBJECT_VOLATILE_finish: 12143 @bl common_squeak0 12144 mov r1, rINST, lsr #8 @ r1<- A+ 12145 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12146 and r1, r1, #15 @ r1<- A 12147 cmp r9, #0 @ check object for null 12148 GET_VREG(r0, r1) @ r0<- fp[A] 12149 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 12150 beq common_errNullObject @ object was null 12151 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 12152 GET_INST_OPCODE(ip) @ extract opcode from rINST 12153 SMP_DMB @ releasing store 12154 str r0, [r9, r3] @ obj.field (32 bits)<- r0 12155 cmp r0, #0 @ stored a null reference? 12156 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 12157 GOTO_OPCODE(ip) @ jump to next instruction 12158 12159/* continuation for OP_SGET_OBJECT_VOLATILE */ 12160 12161 /* 12162 * Continuation if the field has not yet been resolved. 12163 * r1: BBBB field ref 12164 */ 12165.LOP_SGET_OBJECT_VOLATILE_resolve: 12166 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12167 EXPORT_PC() @ resolve() could throw, so export now 12168 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12169 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12170 cmp r0, #0 @ success? 12171 bne .LOP_SGET_OBJECT_VOLATILE_finish @ yes, finish 12172 b common_exceptionThrown @ no, handle exception 12173 12174/* continuation for OP_SPUT_OBJECT_VOLATILE */ 12175.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0 12176 mov r2, rINST, lsr #8 @ r2<- AA 12177 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 12178 GET_VREG(r1, r2) @ r1<- fp[AA] 12179 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 12180 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz 12181 GET_INST_OPCODE(ip) @ extract opcode from rINST 12182 SMP_DMB @ releasing store 12183 str r1, [r0, #offStaticField_value] @ field<- vAA 12184 cmp r1, #0 @ stored a null object? 12185 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 12186 GOTO_OPCODE(ip) @ jump to next instruction 12187 12188/* continuation for OP_CONST_CLASS_JUMBO */ 12189 12190 /* 12191 * Continuation if the Class has not yet been resolved. 12192 * r1: AAAAAAAA (Class ref) 12193 * r9: target register 12194 */ 12195.LOP_CONST_CLASS_JUMBO_resolve: 12196 EXPORT_PC() 12197 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 12198 mov r2, #1 @ r2<- true 12199 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 12200 bl dvmResolveClass @ r0<- Class reference 12201 cmp r0, #0 @ failed? 12202 beq common_exceptionThrown @ yup, handle the exception 12203 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 12204 GET_INST_OPCODE(ip) @ extract opcode from rINST 12205 SET_VREG(r0, r9) @ vBBBB<- r0 12206 GOTO_OPCODE(ip) @ jump to next instruction 12207 12208/* continuation for OP_CHECK_CAST_JUMBO */ 12209 12210 /* 12211 * Trivial test failed, need to perform full check. This is common. 12212 * r0 holds obj->clazz 12213 * r1 holds desired class resolved from AAAAAAAA 12214 * r9 holds object 12215 */ 12216.LOP_CHECK_CAST_JUMBO_fullcheck: 12217 mov r10, r1 @ avoid ClassObject getting clobbered 12218 bl dvmInstanceofNonTrivial @ r0<- boolean result 12219 cmp r0, #0 @ failed? 12220 bne .LOP_CHECK_CAST_JUMBO_okay @ no, success 12221 12222 @ A cast has failed. We need to throw a ClassCastException. 12223 EXPORT_PC() @ about to throw 12224 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz (actual class) 12225 mov r1, r10 @ r1<- desired class 12226 bl dvmThrowClassCastException 12227 b common_exceptionThrown 12228 12229 /* 12230 * Advance PC and get the next opcode. 12231 */ 12232.LOP_CHECK_CAST_JUMBO_okay: 12233 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 12234 GET_INST_OPCODE(ip) @ extract opcode from rINST 12235 GOTO_OPCODE(ip) @ jump to next instruction 12236 12237 /* 12238 * Resolution required. This is the least-likely path. 12239 * 12240 * r2 holds AAAAAAAA 12241 * r9 holds object 12242 */ 12243.LOP_CHECK_CAST_JUMBO_resolve: 12244 EXPORT_PC() @ resolve() could throw 12245 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 12246 mov r1, r2 @ r1<- AAAAAAAA 12247 mov r2, #0 @ r2<- false 12248 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 12249 bl dvmResolveClass @ r0<- resolved ClassObject ptr 12250 cmp r0, #0 @ got null? 12251 beq common_exceptionThrown @ yes, handle exception 12252 mov r1, r0 @ r1<- class resolved from AAAAAAAA 12253 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 12254 b .LOP_CHECK_CAST_JUMBO_resolved @ pick up where we left off 12255 12256/* continuation for OP_INSTANCE_OF_JUMBO */ 12257 12258 /* 12259 * Class resolved, determine type of check necessary. This is common. 12260 * r0 holds obj->clazz 12261 * r1 holds class resolved from AAAAAAAA 12262 * r9 holds BBBB 12263 */ 12264.LOP_INSTANCE_OF_JUMBO_resolved: 12265 cmp r0, r1 @ same class (trivial success)? 12266 beq .LOP_INSTANCE_OF_JUMBO_trivial @ yes, trivial finish 12267 @ fall through to OP_INSTANCE_OF_JUMBO_fullcheck 12268 12269 /* 12270 * Trivial test failed, need to perform full check. This is common. 12271 * r0 holds obj->clazz 12272 * r1 holds class resolved from AAAAAAAA 12273 * r9 holds BBBB 12274 */ 12275.LOP_INSTANCE_OF_JUMBO_fullcheck: 12276 bl dvmInstanceofNonTrivial @ r0<- boolean result 12277 @ fall through to OP_INSTANCE_OF_JUMBO_store 12278 12279 /* 12280 * r0 holds boolean result 12281 * r9 holds BBBB 12282 */ 12283.LOP_INSTANCE_OF_JUMBO_store: 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 * Trivial test succeeded, save and bail. 12291 * r9 holds BBBB 12292 */ 12293.LOP_INSTANCE_OF_JUMBO_trivial: 12294 mov r0, #1 @ indicate success 12295 @ could b OP_INSTANCE_OF_JUMBO_store, but copying is faster and cheaper 12296 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12297 SET_VREG(r0, r9) @ vBBBB<- r0 12298 GET_INST_OPCODE(ip) @ extract opcode from rINST 12299 GOTO_OPCODE(ip) @ jump to next instruction 12300 12301 /* 12302 * Resolution required. This is the least-likely path. 12303 * 12304 * r3 holds AAAAAAAA 12305 * r9 holds BBBB 12306 */ 12307 12308.LOP_INSTANCE_OF_JUMBO_resolve: 12309 EXPORT_PC() @ resolve() could throw 12310 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 12311 mov r1, r3 @ r1<- AAAAAAAA 12312 mov r2, #1 @ r2<- true 12313 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 12314 bl dvmResolveClass @ r0<- resolved ClassObject ptr 12315 cmp r0, #0 @ got null? 12316 beq common_exceptionThrown @ yes, handle exception 12317 FETCH(r3, 4) @ r3<- vCCCC 12318 mov r1, r0 @ r1<- class resolved from AAAAAAAA 12319 GET_VREG(r0, r3) @ r0<- vCCCC (object) 12320 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 12321 b .LOP_INSTANCE_OF_JUMBO_resolved @ pick up where we left off 12322 12323/* continuation for OP_NEW_INSTANCE_JUMBO */ 12324 12325 .balign 32 @ minimize cache lines 12326.LOP_NEW_INSTANCE_JUMBO_finish: @ r0=new object 12327 FETCH(r3, 3) @ r3<- BBBB 12328 cmp r0, #0 @ failed? 12329 beq common_exceptionThrown @ yes, handle the exception 12330 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 12331 GET_INST_OPCODE(ip) @ extract opcode from rINST 12332 SET_VREG(r0, r3) @ vBBBB<- r0 12333 GOTO_OPCODE(ip) @ jump to next instruction 12334 12335 /* 12336 * Class initialization required. 12337 * 12338 * r0 holds class object 12339 */ 12340.LOP_NEW_INSTANCE_JUMBO_needinit: 12341 mov r9, r0 @ save r0 12342 bl dvmInitClass @ initialize class 12343 cmp r0, #0 @ check boolean result 12344 mov r0, r9 @ restore r0 12345 bne .LOP_NEW_INSTANCE_JUMBO_initialized @ success, continue 12346 b common_exceptionThrown @ failed, deal with init exception 12347 12348 /* 12349 * Resolution required. This is the least-likely path. 12350 * 12351 * r1 holds AAAAAAAA 12352 */ 12353.LOP_NEW_INSTANCE_JUMBO_resolve: 12354 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 12355 mov r2, #0 @ r2<- false 12356 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 12357 bl dvmResolveClass @ r0<- resolved ClassObject ptr 12358 cmp r0, #0 @ got null? 12359 bne .LOP_NEW_INSTANCE_JUMBO_resolved @ no, continue 12360 b common_exceptionThrown @ yes, handle exception 12361 12362/* continuation for OP_NEW_ARRAY_JUMBO */ 12363 12364 12365 /* 12366 * Resolve class. (This is an uncommon case.) 12367 * 12368 * r1 holds array length 12369 * r2 holds class ref AAAAAAAA 12370 */ 12371.LOP_NEW_ARRAY_JUMBO_resolve: 12372 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 12373 mov r9, r1 @ r9<- length (save) 12374 mov r1, r2 @ r1<- AAAAAAAA 12375 mov r2, #0 @ r2<- false 12376 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 12377 bl dvmResolveClass @ r0<- call(clazz, ref) 12378 cmp r0, #0 @ got null? 12379 mov r1, r9 @ r1<- length (restore) 12380 beq common_exceptionThrown @ yes, handle exception 12381 @ fall through to OP_NEW_ARRAY_JUMBO_finish 12382 12383 /* 12384 * Finish allocation. 12385 * 12386 * r0 holds class 12387 * r1 holds array length 12388 */ 12389.LOP_NEW_ARRAY_JUMBO_finish: 12390 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 12391 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 12392 cmp r0, #0 @ failed? 12393 FETCH(r2, 3) @ r2<- vBBBB 12394 beq common_exceptionThrown @ yes, handle the exception 12395 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12396 GET_INST_OPCODE(ip) @ extract opcode from rINST 12397 SET_VREG(r0, r2) @ vBBBB<- r0 12398 GOTO_OPCODE(ip) @ jump to next instruction 12399 12400/* continuation for OP_FILLED_NEW_ARRAY_JUMBO */ 12401 12402 /* 12403 * On entry: 12404 * r0 holds array class 12405 */ 12406.LOP_FILLED_NEW_ARRAY_JUMBO_continue: 12407 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 12408 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 12409 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 12410 FETCH(r1, 3) @ r1<- BBBB (length) 12411 cmp rINST, #'I' @ array of ints? 12412 cmpne rINST, #'L' @ array of objects? 12413 cmpne rINST, #'[' @ array of arrays? 12414 mov r9, r1 @ save length in r9 12415 bne .LOP_FILLED_NEW_ARRAY_JUMBO_notimpl @ no, not handled yet 12416 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 12417 cmp r0, #0 @ null return? 12418 beq common_exceptionThrown @ alloc failed, handle exception 12419 12420 FETCH(r1, 4) @ r1<- CCCC 12421 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 12422 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 12423 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 12424 subs r9, r9, #1 @ length--, check for neg 12425 FETCH_ADVANCE_INST(5) @ advance to next instr, load rINST 12426 bmi 2f @ was zero, bail 12427 12428 @ copy values from registers into the array 12429 @ r0=array, r1=CCCC, r9=BBBB (length) 12430 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 124311: ldr r3, [r2], #4 @ r3<- *r2++ 12432 subs r9, r9, #1 @ count-- 12433 str r3, [r0], #4 @ *contents++ = vX 12434 bpl 1b 12435 124362: ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 12437 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 12438 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 12439 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 12440 cmp r1, #'I' @ Is int array? 12441 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 12442 GOTO_OPCODE(ip) @ execute it 12443 12444 /* 12445 * Throw an exception indicating that we have not implemented this 12446 * mode of filled-new-array. 12447 */ 12448.LOP_FILLED_NEW_ARRAY_JUMBO_notimpl: 12449 ldr r0, .L_strInternalError 12450 ldr r1, .L_strFilledNewArrayNotImpl 12451 bl dvmThrowException 12452 b common_exceptionThrown 12453 12454/* continuation for OP_IGET_JUMBO */ 12455 12456 /* 12457 * Currently: 12458 * r0 holds resolved field 12459 * r9 holds object 12460 */ 12461.LOP_IGET_JUMBO_resolved: 12462 cmp r0, #0 @ resolution unsuccessful? 12463 beq common_exceptionThrown @ yes, throw exception 12464 @ fall through to OP_IGET_JUMBO_finish 12465 12466 /* 12467 * Currently: 12468 * r0 holds resolved field 12469 * r9 holds object 12470 */ 12471.LOP_IGET_JUMBO_finish: 12472 @bl common_squeak0 12473 cmp r9, #0 @ check object for null 12474 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12475 beq common_errNullObject @ object was null 12476 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 12477 @ no-op @ acquiring load 12478 FETCH(r2, 3) @ r2<- BBBB 12479 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12480 SET_VREG(r0, r2) @ fp[BBBB]<- r0 12481 GET_INST_OPCODE(ip) @ extract opcode from rINST 12482 GOTO_OPCODE(ip) @ jump to next instruction 12483 12484/* continuation for OP_IGET_WIDE_JUMBO */ 12485 12486 /* 12487 * Currently: 12488 * r0 holds resolved field 12489 * r9 holds object 12490 */ 12491.LOP_IGET_WIDE_JUMBO_resolved: 12492 cmp r0, #0 @ resolution unsuccessful? 12493 beq common_exceptionThrown @ yes, throw exception 12494 @ fall through to OP_IGET_WIDE_JUMBO_finish 12495 12496 /* 12497 * Currently: 12498 * r0 holds resolved field 12499 * r9 holds object 12500 */ 12501.LOP_IGET_WIDE_JUMBO_finish: 12502 cmp r9, #0 @ check object for null 12503 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12504 beq common_errNullObject @ object was null 12505 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 12506 FETCH(r2, 3) @ r2<- BBBB 12507 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12508 add r3, rFP, r2, lsl #2 @ r3<- &fp[BBBB] 12509 GET_INST_OPCODE(ip) @ extract opcode from rINST 12510 stmia r3, {r0-r1} @ fp[BBBB]<- r0/r1 12511 GOTO_OPCODE(ip) @ jump to next instruction 12512 12513/* continuation for OP_IGET_OBJECT_JUMBO */ 12514 12515 /* 12516 * Currently: 12517 * r0 holds resolved field 12518 * r9 holds object 12519 */ 12520.LOP_IGET_OBJECT_JUMBO_resolved: 12521 cmp r0, #0 @ resolution unsuccessful? 12522 beq common_exceptionThrown @ yes, throw exception 12523 @ fall through to OP_IGET_OBJECT_JUMBO_finish 12524 12525 /* 12526 * Currently: 12527 * r0 holds resolved field 12528 * r9 holds object 12529 */ 12530.LOP_IGET_OBJECT_JUMBO_finish: 12531 @bl common_squeak0 12532 cmp r9, #0 @ check object for null 12533 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12534 beq common_errNullObject @ object was null 12535 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 12536 @ no-op @ acquiring load 12537 FETCH(r2, 3) @ r2<- BBBB 12538 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12539 SET_VREG(r0, r2) @ fp[BBBB]<- r0 12540 GET_INST_OPCODE(ip) @ extract opcode from rINST 12541 GOTO_OPCODE(ip) @ jump to next instruction 12542 12543/* continuation for OP_IGET_BOOLEAN_JUMBO */ 12544 12545 /* 12546 * Currently: 12547 * r0 holds resolved field 12548 * r9 holds object 12549 */ 12550.LOP_IGET_BOOLEAN_JUMBO_resolved: 12551 cmp r0, #0 @ resolution unsuccessful? 12552 beq common_exceptionThrown @ yes, throw exception 12553 @ fall through to OP_IGET_BOOLEAN_JUMBO_finish 12554 12555 /* 12556 * Currently: 12557 * r0 holds resolved field 12558 * r9 holds object 12559 */ 12560.LOP_IGET_BOOLEAN_JUMBO_finish: 12561 @bl common_squeak1 12562 cmp r9, #0 @ check object for null 12563 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12564 beq common_errNullObject @ object was null 12565 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 12566 @ no-op @ acquiring load 12567 FETCH(r2, 3) @ r2<- BBBB 12568 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12569 SET_VREG(r0, r2) @ fp[BBBB]<- r0 12570 GET_INST_OPCODE(ip) @ extract opcode from rINST 12571 GOTO_OPCODE(ip) @ jump to next instruction 12572 12573/* continuation for OP_IGET_BYTE_JUMBO */ 12574 12575 /* 12576 * Currently: 12577 * r0 holds resolved field 12578 * r9 holds object 12579 */ 12580.LOP_IGET_BYTE_JUMBO_resolved: 12581 cmp r0, #0 @ resolution unsuccessful? 12582 beq common_exceptionThrown @ yes, throw exception 12583 @ fall through to OP_IGET_BYTE_JUMBO_finish 12584 12585 /* 12586 * Currently: 12587 * r0 holds resolved field 12588 * r9 holds object 12589 */ 12590.LOP_IGET_BYTE_JUMBO_finish: 12591 @bl common_squeak2 12592 cmp r9, #0 @ check object for null 12593 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12594 beq common_errNullObject @ object was null 12595 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 12596 @ no-op @ acquiring load 12597 FETCH(r2, 3) @ r2<- BBBB 12598 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12599 SET_VREG(r0, r2) @ fp[BBBB]<- r0 12600 GET_INST_OPCODE(ip) @ extract opcode from rINST 12601 GOTO_OPCODE(ip) @ jump to next instruction 12602 12603/* continuation for OP_IGET_CHAR_JUMBO */ 12604 12605 /* 12606 * Currently: 12607 * r0 holds resolved field 12608 * r9 holds object 12609 */ 12610.LOP_IGET_CHAR_JUMBO_resolved: 12611 cmp r0, #0 @ resolution unsuccessful? 12612 beq common_exceptionThrown @ yes, throw exception 12613 @ fall through to OP_IGET_CHAR_JUMBO_finish 12614 12615 /* 12616 * Currently: 12617 * r0 holds resolved field 12618 * r9 holds object 12619 */ 12620.LOP_IGET_CHAR_JUMBO_finish: 12621 @bl common_squeak3 12622 cmp r9, #0 @ check object for null 12623 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12624 beq common_errNullObject @ object was null 12625 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 12626 @ no-op @ acquiring load 12627 FETCH(r2, 3) @ r2<- BBBB 12628 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12629 SET_VREG(r0, r2) @ fp[BBBB]<- r0 12630 GET_INST_OPCODE(ip) @ extract opcode from rINST 12631 GOTO_OPCODE(ip) @ jump to next instruction 12632 12633/* continuation for OP_IGET_SHORT_JUMBO */ 12634 12635 /* 12636 * Currently: 12637 * r0 holds resolved field 12638 * r9 holds object 12639 */ 12640.LOP_IGET_SHORT_JUMBO_resolved: 12641 cmp r0, #0 @ resolution unsuccessful? 12642 beq common_exceptionThrown @ yes, throw exception 12643 @ fall through to OP_IGET_SHORT_JUMBO_finish 12644 12645 /* 12646 * Currently: 12647 * r0 holds resolved field 12648 * r9 holds object 12649 */ 12650.LOP_IGET_SHORT_JUMBO_finish: 12651 @bl common_squeak4 12652 cmp r9, #0 @ check object for null 12653 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12654 beq common_errNullObject @ object was null 12655 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 12656 @ no-op @ acquiring load 12657 FETCH(r2, 3) @ r2<- BBBB 12658 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12659 SET_VREG(r0, r2) @ fp[BBBB]<- r0 12660 GET_INST_OPCODE(ip) @ extract opcode from rINST 12661 GOTO_OPCODE(ip) @ jump to next instruction 12662 12663/* continuation for OP_IPUT_JUMBO */ 12664 12665 /* 12666 * Currently: 12667 * r0 holds resolved field 12668 * r9 holds object 12669 */ 12670.LOP_IPUT_JUMBO_resolved: 12671 cmp r0, #0 @ resolution unsuccessful? 12672 beq common_exceptionThrown @ yes, throw exception 12673 @ fall through to OP_IPUT_JUMBO_finish 12674 12675 /* 12676 * Currently: 12677 * r0 holds resolved field 12678 * r9 holds object 12679 */ 12680.LOP_IPUT_JUMBO_finish: 12681 @bl common_squeak0 12682 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12683 FETCH(r1, 3) @ r1<- BBBB 12684 cmp r9, #0 @ check object for null 12685 GET_VREG(r0, r1) @ r0<- fp[BBBB] 12686 beq common_errNullObject @ object was null 12687 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12688 GET_INST_OPCODE(ip) @ extract opcode from rINST 12689 @ no-op @ releasing store 12690 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 12691 GOTO_OPCODE(ip) @ jump to next instruction 12692 12693/* continuation for OP_IPUT_WIDE_JUMBO */ 12694 12695 /* 12696 * Currently: 12697 * r0 holds resolved field 12698 * r9 holds object 12699 */ 12700.LOP_IPUT_WIDE_JUMBO_resolved: 12701 cmp r0, #0 @ resolution unsuccessful? 12702 beq common_exceptionThrown @ yes, throw exception 12703 @ fall through to OP_IPUT_WIDE_JUMBO_finish 12704 12705 /* 12706 * Currently: 12707 * r0 holds resolved field 12708 * r9 holds object 12709 */ 12710.LOP_IPUT_WIDE_JUMBO_finish: 12711 cmp r9, #0 @ check object for null 12712 FETCH(r2, 3) @ r1<- BBBB 12713 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12714 add r2, rFP, r2, lsl #2 @ r3<- &fp[BBBB] 12715 beq common_errNullObject @ object was null 12716 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12717 ldmia r2, {r0-r1} @ r0/r1<- fp[BBBB] 12718 GET_INST_OPCODE(r10) @ extract opcode from rINST 12719 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 12720 GOTO_OPCODE(r10) @ jump to next instruction 12721 12722/* continuation for OP_IPUT_OBJECT_JUMBO */ 12723 12724 /* 12725 * Currently: 12726 * r0 holds resolved field 12727 * r9 holds object 12728 */ 12729.LOP_IPUT_OBJECT_JUMBO_resolved: 12730 cmp r0, #0 @ resolution unsuccessful? 12731 beq common_exceptionThrown @ yes, throw exception 12732 @ fall through to OP_IPUT_OBJECT_JUMBO_finish 12733 12734 /* 12735 * Currently: 12736 * r0 holds resolved field 12737 * r9 holds object 12738 */ 12739.LOP_IPUT_OBJECT_JUMBO_finish: 12740 @bl common_squeak0 12741 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12742 FETCH(r1, 3) @ r1<- BBBB 12743 cmp r9, #0 @ check object for null 12744 GET_VREG(r0, r1) @ r0<- fp[BBBB] 12745 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 12746 beq common_errNullObject @ object was null 12747 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12748 GET_INST_OPCODE(ip) @ extract opcode from rINST 12749 @ no-op @ releasing store 12750 str r0, [r9, r3] @ obj.field (32 bits)<- r0 12751 cmp r0, #0 @ stored a null reference? 12752 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 12753 GOTO_OPCODE(ip) @ jump to next instruction 12754 12755/* continuation for OP_IPUT_BOOLEAN_JUMBO */ 12756 12757 /* 12758 * Currently: 12759 * r0 holds resolved field 12760 * r9 holds object 12761 */ 12762.LOP_IPUT_BOOLEAN_JUMBO_resolved: 12763 cmp r0, #0 @ resolution unsuccessful? 12764 beq common_exceptionThrown @ yes, throw exception 12765 @ fall through to OP_IPUT_BOOLEAN_JUMBO_finish 12766 12767 /* 12768 * Currently: 12769 * r0 holds resolved field 12770 * r9 holds object 12771 */ 12772.LOP_IPUT_BOOLEAN_JUMBO_finish: 12773 @bl common_squeak1 12774 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12775 FETCH(r1, 3) @ r1<- BBBB 12776 cmp r9, #0 @ check object for null 12777 GET_VREG(r0, r1) @ r0<- fp[BBBB] 12778 beq common_errNullObject @ object was null 12779 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12780 GET_INST_OPCODE(ip) @ extract opcode from rINST 12781 @ no-op @ releasing store 12782 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 12783 GOTO_OPCODE(ip) @ jump to next instruction 12784 12785/* continuation for OP_IPUT_BYTE_JUMBO */ 12786 12787 /* 12788 * Currently: 12789 * r0 holds resolved field 12790 * r9 holds object 12791 */ 12792.LOP_IPUT_BYTE_JUMBO_resolved: 12793 cmp r0, #0 @ resolution unsuccessful? 12794 beq common_exceptionThrown @ yes, throw exception 12795 @ fall through to OP_IPUT_BYTE_JUMBO_finish 12796 12797 /* 12798 * Currently: 12799 * r0 holds resolved field 12800 * r9 holds object 12801 */ 12802.LOP_IPUT_BYTE_JUMBO_finish: 12803 @bl common_squeak2 12804 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12805 FETCH(r1, 3) @ r1<- BBBB 12806 cmp r9, #0 @ check object for null 12807 GET_VREG(r0, r1) @ r0<- fp[BBBB] 12808 beq common_errNullObject @ object was null 12809 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12810 GET_INST_OPCODE(ip) @ extract opcode from rINST 12811 @ no-op @ releasing store 12812 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 12813 GOTO_OPCODE(ip) @ jump to next instruction 12814 12815/* continuation for OP_IPUT_CHAR_JUMBO */ 12816 12817 /* 12818 * Currently: 12819 * r0 holds resolved field 12820 * r9 holds object 12821 */ 12822.LOP_IPUT_CHAR_JUMBO_resolved: 12823 cmp r0, #0 @ resolution unsuccessful? 12824 beq common_exceptionThrown @ yes, throw exception 12825 @ fall through to OP_IPUT_CHAR_JUMBO_finish 12826 12827 /* 12828 * Currently: 12829 * r0 holds resolved field 12830 * r9 holds object 12831 */ 12832.LOP_IPUT_CHAR_JUMBO_finish: 12833 @bl common_squeak3 12834 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12835 FETCH(r1, 3) @ r1<- BBBB 12836 cmp r9, #0 @ check object for null 12837 GET_VREG(r0, r1) @ r0<- fp[BBBB] 12838 beq common_errNullObject @ object was null 12839 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12840 GET_INST_OPCODE(ip) @ extract opcode from rINST 12841 @ no-op @ releasing store 12842 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 12843 GOTO_OPCODE(ip) @ jump to next instruction 12844 12845/* continuation for OP_IPUT_SHORT_JUMBO */ 12846 12847 /* 12848 * Currently: 12849 * r0 holds resolved field 12850 * r9 holds object 12851 */ 12852.LOP_IPUT_SHORT_JUMBO_resolved: 12853 cmp r0, #0 @ resolution unsuccessful? 12854 beq common_exceptionThrown @ yes, throw exception 12855 @ fall through to OP_IPUT_SHORT_JUMBO_finish 12856 12857 /* 12858 * Currently: 12859 * r0 holds resolved field 12860 * r9 holds object 12861 */ 12862.LOP_IPUT_SHORT_JUMBO_finish: 12863 @bl common_squeak4 12864 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12865 FETCH(r1, 3) @ r1<- BBBB 12866 cmp r9, #0 @ check object for null 12867 GET_VREG(r0, r1) @ r0<- fp[BBBB] 12868 beq common_errNullObject @ object was null 12869 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12870 GET_INST_OPCODE(ip) @ extract opcode from rINST 12871 @ no-op @ releasing store 12872 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 12873 GOTO_OPCODE(ip) @ jump to next instruction 12874 12875/* continuation for OP_SGET_JUMBO */ 12876 12877 /* 12878 * Continuation if the field has not yet been resolved. 12879 * r1: AAAAAAAA field ref 12880 */ 12881.LOP_SGET_JUMBO_resolve: 12882 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12883 EXPORT_PC() @ resolve() could throw, so export now 12884 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12885 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12886 cmp r0, #0 @ success? 12887 bne .LOP_SGET_JUMBO_finish @ yes, finish 12888 b common_exceptionThrown @ no, handle exception 12889 12890/* continuation for OP_SGET_WIDE_JUMBO */ 12891 12892 /* 12893 * Continuation if the field has not yet been resolved. 12894 * r1: BBBB field ref 12895 * 12896 * Returns StaticField pointer in r0. 12897 */ 12898.LOP_SGET_WIDE_JUMBO_resolve: 12899 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12900 EXPORT_PC() @ resolve() could throw, so export now 12901 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12902 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12903 cmp r0, #0 @ success? 12904 bne .LOP_SGET_WIDE_JUMBO_finish @ yes, finish 12905 b common_exceptionThrown @ no, handle exception 12906 12907/* continuation for OP_SGET_OBJECT_JUMBO */ 12908 12909 /* 12910 * Continuation if the field has not yet been resolved. 12911 * r1: AAAAAAAA field ref 12912 */ 12913.LOP_SGET_OBJECT_JUMBO_resolve: 12914 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12915 EXPORT_PC() @ resolve() could throw, so export now 12916 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12917 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12918 cmp r0, #0 @ success? 12919 bne .LOP_SGET_OBJECT_JUMBO_finish @ yes, finish 12920 b common_exceptionThrown @ no, handle exception 12921 12922/* continuation for OP_SGET_BOOLEAN_JUMBO */ 12923 12924 /* 12925 * Continuation if the field has not yet been resolved. 12926 * r1: AAAAAAAA field ref 12927 */ 12928.LOP_SGET_BOOLEAN_JUMBO_resolve: 12929 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12930 EXPORT_PC() @ resolve() could throw, so export now 12931 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12932 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12933 cmp r0, #0 @ success? 12934 bne .LOP_SGET_BOOLEAN_JUMBO_finish @ yes, finish 12935 b common_exceptionThrown @ no, handle exception 12936 12937/* continuation for OP_SGET_BYTE_JUMBO */ 12938 12939 /* 12940 * Continuation if the field has not yet been resolved. 12941 * r1: AAAAAAAA field ref 12942 */ 12943.LOP_SGET_BYTE_JUMBO_resolve: 12944 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12945 EXPORT_PC() @ resolve() could throw, so export now 12946 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12947 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12948 cmp r0, #0 @ success? 12949 bne .LOP_SGET_BYTE_JUMBO_finish @ yes, finish 12950 b common_exceptionThrown @ no, handle exception 12951 12952/* continuation for OP_SGET_CHAR_JUMBO */ 12953 12954 /* 12955 * Continuation if the field has not yet been resolved. 12956 * r1: AAAAAAAA field ref 12957 */ 12958.LOP_SGET_CHAR_JUMBO_resolve: 12959 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12960 EXPORT_PC() @ resolve() could throw, so export now 12961 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12962 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12963 cmp r0, #0 @ success? 12964 bne .LOP_SGET_CHAR_JUMBO_finish @ yes, finish 12965 b common_exceptionThrown @ no, handle exception 12966 12967/* continuation for OP_SGET_SHORT_JUMBO */ 12968 12969 /* 12970 * Continuation if the field has not yet been resolved. 12971 * r1: AAAAAAAA field ref 12972 */ 12973.LOP_SGET_SHORT_JUMBO_resolve: 12974 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12975 EXPORT_PC() @ resolve() could throw, so export now 12976 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12977 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12978 cmp r0, #0 @ success? 12979 bne .LOP_SGET_SHORT_JUMBO_finish @ yes, finish 12980 b common_exceptionThrown @ no, handle exception 12981 12982/* continuation for OP_SPUT_JUMBO */ 12983 12984 /* 12985 * Continuation if the field has not yet been resolved. 12986 * r1: AAAAAAAA field ref 12987 */ 12988.LOP_SPUT_JUMBO_resolve: 12989 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12990 EXPORT_PC() @ resolve() could throw, so export now 12991 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12992 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12993 cmp r0, #0 @ success? 12994 bne .LOP_SPUT_JUMBO_finish @ yes, finish 12995 b common_exceptionThrown @ no, handle exception 12996 12997/* continuation for OP_SPUT_WIDE_JUMBO */ 12998 12999 /* 13000 * Continuation if the field has not yet been resolved. 13001 * r1: BBBB field ref 13002 * r9: &fp[AA] 13003 * 13004 * Returns StaticField pointer in r2. 13005 */ 13006.LOP_SPUT_WIDE_JUMBO_resolve: 13007 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 13008 EXPORT_PC() @ resolve() could throw, so export now 13009 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 13010 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 13011 cmp r0, #0 @ success? 13012 mov r2, r0 @ copy to r2 13013 bne .LOP_SPUT_WIDE_JUMBO_finish @ yes, finish 13014 b common_exceptionThrown @ no, handle exception 13015 13016/* continuation for OP_SPUT_OBJECT_JUMBO */ 13017 13018.LOP_SPUT_OBJECT_JUMBO_finish: @ field ptr in r0 13019 FETCH(r2, 3) @ r2<- BBBB 13020 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 13021 GET_VREG(r1, r2) @ r1<- fp[BBBB] 13022 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 13023 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz 13024 GET_INST_OPCODE(ip) @ extract opcode from rINST 13025 @ no-op @ releasing store 13026 str r1, [r0, #offStaticField_value] @ field<- vBBBB 13027 cmp r1, #0 @ stored a null object? 13028 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 13029 GOTO_OPCODE(ip) @ jump to next instruction 13030 13031/* continuation for OP_SPUT_BOOLEAN_JUMBO */ 13032 13033 /* 13034 * Continuation if the field has not yet been resolved. 13035 * r1: AAAAAAAA field ref 13036 */ 13037.LOP_SPUT_BOOLEAN_JUMBO_resolve: 13038 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 13039 EXPORT_PC() @ resolve() could throw, so export now 13040 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 13041 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 13042 cmp r0, #0 @ success? 13043 bne .LOP_SPUT_BOOLEAN_JUMBO_finish @ yes, finish 13044 b common_exceptionThrown @ no, handle exception 13045 13046/* continuation for OP_SPUT_BYTE_JUMBO */ 13047 13048 /* 13049 * Continuation if the field has not yet been resolved. 13050 * r1: AAAAAAAA field ref 13051 */ 13052.LOP_SPUT_BYTE_JUMBO_resolve: 13053 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 13054 EXPORT_PC() @ resolve() could throw, so export now 13055 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 13056 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 13057 cmp r0, #0 @ success? 13058 bne .LOP_SPUT_BYTE_JUMBO_finish @ yes, finish 13059 b common_exceptionThrown @ no, handle exception 13060 13061/* continuation for OP_SPUT_CHAR_JUMBO */ 13062 13063 /* 13064 * Continuation if the field has not yet been resolved. 13065 * r1: AAAAAAAA field ref 13066 */ 13067.LOP_SPUT_CHAR_JUMBO_resolve: 13068 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 13069 EXPORT_PC() @ resolve() could throw, so export now 13070 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 13071 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 13072 cmp r0, #0 @ success? 13073 bne .LOP_SPUT_CHAR_JUMBO_finish @ yes, finish 13074 b common_exceptionThrown @ no, handle exception 13075 13076/* continuation for OP_SPUT_SHORT_JUMBO */ 13077 13078 /* 13079 * Continuation if the field has not yet been resolved. 13080 * r1: AAAAAAAA field ref 13081 */ 13082.LOP_SPUT_SHORT_JUMBO_resolve: 13083 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 13084 EXPORT_PC() @ resolve() could throw, so export now 13085 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 13086 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 13087 cmp r0, #0 @ success? 13088 bne .LOP_SPUT_SHORT_JUMBO_finish @ yes, finish 13089 b common_exceptionThrown @ no, handle exception 13090 13091/* continuation for OP_INVOKE_VIRTUAL_JUMBO */ 13092 13093 /* 13094 * At this point: 13095 * r0 = resolved base method 13096 */ 13097.LOP_INVOKE_VIRTUAL_JUMBO_continue: 13098 FETCH(r10, 4) @ r10<- CCCC 13099 GET_VREG(r1, r10) @ r1<- "this" ptr 13100 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 13101 cmp r1, #0 @ is "this" null? 13102 beq common_errNullObject @ null "this", throw exception 13103 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 13104 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 13105 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 13106 bl common_invokeMethodJumbo @ continue on 13107 13108/* continuation for OP_INVOKE_SUPER_JUMBO */ 13109 13110 /* 13111 * At this point: 13112 * r0 = resolved base method 13113 * r9 = method->clazz 13114 */ 13115.LOP_INVOKE_SUPER_JUMBO_continue: 13116 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 13117 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 13118 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 13119 EXPORT_PC() @ must export for invoke 13120 cmp r2, r3 @ compare (methodIndex, vtableCount) 13121 bcs .LOP_INVOKE_SUPER_JUMBO_nsm @ method not present in superclass 13122 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 13123 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 13124 bl common_invokeMethodJumbo @ continue on 13125 13126.LOP_INVOKE_SUPER_JUMBO_resolve: 13127 mov r0, r9 @ r0<- method->clazz 13128 mov r2, #METHOD_VIRTUAL @ resolver method type 13129 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 13130 cmp r0, #0 @ got null? 13131 bne .LOP_INVOKE_SUPER_JUMBO_continue @ no, continue 13132 b common_exceptionThrown @ yes, handle exception 13133 13134 /* 13135 * Throw a NoSuchMethodError with the method name as the message. 13136 * r0 = resolved base method 13137 */ 13138.LOP_INVOKE_SUPER_JUMBO_nsm: 13139 ldr r1, [r0, #offMethod_name] @ r1<- method name 13140 b common_errNoSuchMethod 13141 13142/* continuation for OP_INVOKE_DIRECT_JUMBO */ 13143 13144 /* 13145 * On entry: 13146 * r1 = reference (CCCC) 13147 * r10 = "this" register 13148 */ 13149.LOP_INVOKE_DIRECT_JUMBO_resolve: 13150 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 13151 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 13152 mov r2, #METHOD_DIRECT @ resolver method type 13153 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 13154 cmp r0, #0 @ got null? 13155 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 13156 bne .LOP_INVOKE_DIRECT_JUMBO_finish @ no, continue 13157 b common_exceptionThrown @ yes, handle exception 13158 13159 .size dvmAsmSisterStart, .-dvmAsmSisterStart 13160 .global dvmAsmSisterEnd 13161dvmAsmSisterEnd: 13162 13163/* File: armv5te/footer.S */ 13164 13165/* 13166 * =========================================================================== 13167 * Common subroutines and data 13168 * =========================================================================== 13169 */ 13170 13171 13172 13173 .text 13174 .align 2 13175 13176#if defined(WITH_JIT) 13177#if defined(WITH_SELF_VERIFICATION) 13178 .global dvmJitToInterpPunt 13179dvmJitToInterpPunt: 13180 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13181 mov r2,#kSVSPunt @ r2<- interpreter entry point 13182 mov r3, #0 13183 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 13184 b jitSVShadowRunEnd @ doesn't return 13185 13186 .global dvmJitToInterpSingleStep 13187dvmJitToInterpSingleStep: 13188 str lr,[rGLUE,#offGlue_jitResumeNPC] 13189 str r1,[rGLUE,#offGlue_jitResumeDPC] 13190 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 13191 b jitSVShadowRunEnd @ doesn't return 13192 13193 .global dvmJitToInterpNoChainNoProfile 13194dvmJitToInterpNoChainNoProfile: 13195 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13196 mov r0,rPC @ pass our target PC 13197 mov r2,#kSVSNoProfile @ r2<- interpreter entry point 13198 mov r3, #0 @ 0 means !inJitCodeCache 13199 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land 13200 b jitSVShadowRunEnd @ doesn't return 13201 13202 .global dvmJitToInterpTraceSelectNoChain 13203dvmJitToInterpTraceSelectNoChain: 13204 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13205 mov r0,rPC @ pass our target PC 13206 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 13207 mov r3, #0 @ 0 means !inJitCodeCache 13208 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 13209 b jitSVShadowRunEnd @ doesn't return 13210 13211 .global dvmJitToInterpTraceSelect 13212dvmJitToInterpTraceSelect: 13213 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13214 ldr r0,[lr, #-1] @ pass our target PC 13215 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 13216 mov r3, #0 @ 0 means !inJitCodeCache 13217 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 13218 b jitSVShadowRunEnd @ doesn't return 13219 13220 .global dvmJitToInterpBackwardBranch 13221dvmJitToInterpBackwardBranch: 13222 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13223 ldr r0,[lr, #-1] @ pass our target PC 13224 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 13225 mov r3, #0 @ 0 means !inJitCodeCache 13226 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 13227 b jitSVShadowRunEnd @ doesn't return 13228 13229 .global dvmJitToInterpNormal 13230dvmJitToInterpNormal: 13231 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13232 ldr r0,[lr, #-1] @ pass our target PC 13233 mov r2,#kSVSNormal @ r2<- interpreter entry point 13234 mov r3, #0 @ 0 means !inJitCodeCache 13235 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 13236 b jitSVShadowRunEnd @ doesn't return 13237 13238 .global dvmJitToInterpNoChain 13239dvmJitToInterpNoChain: 13240 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13241 mov r0,rPC @ pass our target PC 13242 mov r2,#kSVSNoChain @ r2<- interpreter entry point 13243 mov r3, #0 @ 0 means !inJitCodeCache 13244 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 13245 b jitSVShadowRunEnd @ doesn't return 13246#else 13247/* 13248 * Return from the translation cache to the interpreter when the compiler is 13249 * having issues translating/executing a Dalvik instruction. We have to skip 13250 * the code cache lookup otherwise it is possible to indefinitely bouce 13251 * between the interpreter and the code cache if the instruction that fails 13252 * to be compiled happens to be at a trace start. 13253 */ 13254 .global dvmJitToInterpPunt 13255dvmJitToInterpPunt: 13256 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13257 mov rPC, r0 13258#if defined(WITH_JIT_TUNING) 13259 mov r0,lr 13260 bl dvmBumpPunt; 13261#endif 13262 EXPORT_PC() 13263 mov r0, #0 13264 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land 13265 adrl rIBASE, dvmAsmInstructionStart 13266 FETCH_INST() 13267 GET_INST_OPCODE(ip) 13268 GOTO_OPCODE(ip) 13269 13270/* 13271 * Return to the interpreter to handle a single instruction. 13272 * On entry: 13273 * r0 <= PC 13274 * r1 <= PC of resume instruction 13275 * lr <= resume point in translation 13276 */ 13277 .global dvmJitToInterpSingleStep 13278dvmJitToInterpSingleStep: 13279 str lr,[rGLUE,#offGlue_jitResumeNPC] 13280 str r1,[rGLUE,#offGlue_jitResumeDPC] 13281 mov r1,#kInterpEntryInstr 13282 @ enum is 4 byte in aapcs-EABI 13283 str r1, [rGLUE, #offGlue_entryPoint] 13284 mov rPC,r0 13285 EXPORT_PC() 13286 13287 adrl rIBASE, dvmAsmInstructionStart 13288 mov r2,#kJitSingleStep @ Ask for single step and then revert 13289 str r2,[rGLUE,#offGlue_jitState] 13290 mov r1,#1 @ set changeInterp to bail to debug interp 13291 b common_gotoBail 13292 13293/* 13294 * Return from the translation cache and immediately request 13295 * a translation for the exit target. Commonly used for callees. 13296 */ 13297 .global dvmJitToInterpTraceSelectNoChain 13298dvmJitToInterpTraceSelectNoChain: 13299#if defined(WITH_JIT_TUNING) 13300 bl dvmBumpNoChain 13301#endif 13302 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13303 mov r0,rPC 13304 bl dvmJitGetTraceAddr @ Is there a translation? 13305 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 13306 mov r1, rPC @ arg1 of translation may need this 13307 mov lr, #0 @ in case target is HANDLER_INTERPRET 13308 cmp r0,#0 @ !0 means translation exists 13309 bxne r0 @ continue native execution if so 13310 b 2f @ branch over to use the interpreter 13311 13312/* 13313 * Return from the translation cache and immediately request 13314 * a translation for the exit target. Commonly used following 13315 * invokes. 13316 */ 13317 .global dvmJitToInterpTraceSelect 13318dvmJitToInterpTraceSelect: 13319 ldr rPC,[lr, #-1] @ get our target PC 13320 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13321 add rINST,lr,#-5 @ save start of chain branch 13322 add rINST, #-4 @ .. which is 9 bytes back 13323 mov r0,rPC 13324 bl dvmJitGetTraceAddr @ Is there a translation? 13325 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 13326 cmp r0,#0 13327 beq 2f 13328 mov r1,rINST 13329 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 13330 mov r1, rPC @ arg1 of translation may need this 13331 mov lr, #0 @ in case target is HANDLER_INTERPRET 13332 cmp r0,#0 @ successful chain? 13333 bxne r0 @ continue native execution 13334 b toInterpreter @ didn't chain - resume with interpreter 13335 13336/* No translation, so request one if profiling isn't disabled*/ 133372: 13338 adrl rIBASE, dvmAsmInstructionStart 13339 GET_JIT_PROF_TABLE(r0) 13340 FETCH_INST() 13341 cmp r0, #0 13342 movne r2,#kJitTSelectRequestHot @ ask for trace selection 13343 bne common_selectTrace 13344 GET_INST_OPCODE(ip) 13345 GOTO_OPCODE(ip) 13346 13347/* 13348 * Return from the translation cache to the interpreter. 13349 * The return was done with a BLX from thumb mode, and 13350 * the following 32-bit word contains the target rPC value. 13351 * Note that lr (r14) will have its low-order bit set to denote 13352 * its thumb-mode origin. 13353 * 13354 * We'll need to stash our lr origin away, recover the new 13355 * target and then check to see if there is a translation available 13356 * for our new target. If so, we do a translation chain and 13357 * go back to native execution. Otherwise, it's back to the 13358 * interpreter (after treating this entry as a potential 13359 * trace start). 13360 */ 13361 .global dvmJitToInterpNormal 13362dvmJitToInterpNormal: 13363 ldr rPC,[lr, #-1] @ get our target PC 13364 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13365 add rINST,lr,#-5 @ save start of chain branch 13366 add rINST,#-4 @ .. which is 9 bytes back 13367#if defined(WITH_JIT_TUNING) 13368 bl dvmBumpNormal 13369#endif 13370 mov r0,rPC 13371 bl dvmJitGetTraceAddr @ Is there a translation? 13372 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 13373 cmp r0,#0 13374 beq toInterpreter @ go if not, otherwise do chain 13375 mov r1,rINST 13376 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 13377 mov r1, rPC @ arg1 of translation may need this 13378 mov lr, #0 @ in case target is HANDLER_INTERPRET 13379 cmp r0,#0 @ successful chain? 13380 bxne r0 @ continue native execution 13381 b toInterpreter @ didn't chain - resume with interpreter 13382 13383/* 13384 * Return from the translation cache to the interpreter to do method invocation. 13385 * Check if translation exists for the callee, but don't chain to it. 13386 */ 13387 .global dvmJitToInterpNoChainNoProfile 13388dvmJitToInterpNoChainNoProfile: 13389#if defined(WITH_JIT_TUNING) 13390 bl dvmBumpNoChain 13391#endif 13392 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13393 mov r0,rPC 13394 bl dvmJitGetTraceAddr @ Is there a translation? 13395 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 13396 mov r1, rPC @ arg1 of translation may need this 13397 mov lr, #0 @ in case target is HANDLER_INTERPRET 13398 cmp r0,#0 13399 bxne r0 @ continue native execution if so 13400 EXPORT_PC() 13401 adrl rIBASE, dvmAsmInstructionStart 13402 FETCH_INST() 13403 GET_INST_OPCODE(ip) @ extract opcode from rINST 13404 GOTO_OPCODE(ip) @ jump to next instruction 13405 13406/* 13407 * Return from the translation cache to the interpreter to do method invocation. 13408 * Check if translation exists for the callee, but don't chain to it. 13409 */ 13410 .global dvmJitToInterpNoChain 13411dvmJitToInterpNoChain: 13412#if defined(WITH_JIT_TUNING) 13413 bl dvmBumpNoChain 13414#endif 13415 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13416 mov r0,rPC 13417 bl dvmJitGetTraceAddr @ Is there a translation? 13418 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 13419 mov r1, rPC @ arg1 of translation may need this 13420 mov lr, #0 @ in case target is HANDLER_INTERPRET 13421 cmp r0,#0 13422 bxne r0 @ continue native execution if so 13423#endif 13424 13425/* 13426 * No translation, restore interpreter regs and start interpreting. 13427 * rGLUE & rFP were preserved in the translated code, and rPC has 13428 * already been restored by the time we get here. We'll need to set 13429 * up rIBASE & rINST, and load the address of the JitTable into r0. 13430 */ 13431toInterpreter: 13432 EXPORT_PC() 13433 adrl rIBASE, dvmAsmInstructionStart 13434 FETCH_INST() 13435 GET_JIT_PROF_TABLE(r0) 13436 @ NOTE: intended fallthrough 13437 13438/* 13439 * Common code to update potential trace start counter, and initiate 13440 * a trace-build if appropriate. On entry, rPC should point to the 13441 * next instruction to execute, and rINST should be already loaded with 13442 * the next opcode word, and r0 holds a pointer to the jit profile 13443 * table (pJitProfTable). 13444 */ 13445common_testUpdateProfile: 13446 cmp r0,#0 13447 GET_INST_OPCODE(ip) 13448 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 13449 13450common_updateProfile: 13451 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 13452 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits 13453 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter 13454 GET_INST_OPCODE(ip) 13455 subs r1,r1,#1 @ decrement counter 13456 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it 13457 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 13458 13459/* 13460 * Here, we switch to the debug interpreter to request 13461 * trace selection. First, though, check to see if there 13462 * is already a native translation in place (and, if so, 13463 * jump to it now). 13464 */ 13465 GET_JIT_THRESHOLD(r1) 13466 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13467 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter 13468 EXPORT_PC() 13469 mov r0,rPC 13470 bl dvmJitGetTraceAddr @ r0<- dvmJitGetTraceAddr(rPC) 13471 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 13472 mov r1, rPC @ arg1 of translation may need this 13473 mov lr, #0 @ in case target is HANDLER_INTERPRET 13474 cmp r0,#0 13475#if !defined(WITH_SELF_VERIFICATION) 13476 bxne r0 @ jump to the translation 13477 mov r2,#kJitTSelectRequest @ ask for trace selection 13478 @ fall-through to common_selectTrace 13479#else 13480 moveq r2,#kJitTSelectRequest @ ask for trace selection 13481 beq common_selectTrace 13482 /* 13483 * At this point, we have a target translation. However, if 13484 * that translation is actually the interpret-only pseudo-translation 13485 * we want to treat it the same as no translation. 13486 */ 13487 mov r10, r0 @ save target 13488 bl dvmCompilerGetInterpretTemplate 13489 cmp r0, r10 @ special case? 13490 bne jitSVShadowRunStart @ set up self verification shadow space 13491 @ Need to clear the inJitCodeCache flag 13492 ldr r10, [rGLUE, #offGlue_self] @ r10 <- glue->self 13493 mov r3, #0 @ 0 means not in the JIT code cache 13494 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land 13495 GET_INST_OPCODE(ip) 13496 GOTO_OPCODE(ip) 13497 /* no return */ 13498#endif 13499 13500/* 13501 * On entry: 13502 * r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot 13503 */ 13504common_selectTrace: 13505 str r2,[rGLUE,#offGlue_jitState] 13506 mov r2,#kInterpEntryInstr @ normal entry reason 13507 str r2,[rGLUE,#offGlue_entryPoint] 13508 mov r1,#1 @ set changeInterp 13509 b common_gotoBail 13510 13511#if defined(WITH_SELF_VERIFICATION) 13512/* 13513 * Save PC and registers to shadow memory for self verification mode 13514 * before jumping to native translation. 13515 * On entry: 13516 * rPC, rFP, rGLUE: the values that they should contain 13517 * r10: the address of the target translation. 13518 */ 13519jitSVShadowRunStart: 13520 mov r0,rPC @ r0<- program counter 13521 mov r1,rFP @ r1<- frame pointer 13522 mov r2,rGLUE @ r2<- InterpState pointer 13523 mov r3,r10 @ r3<- target translation 13524 bl dvmSelfVerificationSaveState @ save registers to shadow space 13525 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 13526 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 13527 bx r10 @ jump to the translation 13528 13529/* 13530 * Restore PC, registers, and interpState to original values 13531 * before jumping back to the interpreter. 13532 */ 13533jitSVShadowRunEnd: 13534 mov r1,rFP @ pass ending fp 13535 bl dvmSelfVerificationRestoreState @ restore pc and fp values 13536 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 13537 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 13538 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 13539 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 13540 cmp r1,#0 @ check for punt condition 13541 beq 1f 13542 mov r2,#kJitSelfVerification @ ask for self verification 13543 str r2,[rGLUE,#offGlue_jitState] 13544 mov r2,#kInterpEntryInstr @ normal entry reason 13545 str r2,[rGLUE,#offGlue_entryPoint] 13546 mov r1,#1 @ set changeInterp 13547 b common_gotoBail 13548 135491: @ exit to interpreter without check 13550 EXPORT_PC() 13551 adrl rIBASE, dvmAsmInstructionStart 13552 FETCH_INST() 13553 GET_INST_OPCODE(ip) 13554 GOTO_OPCODE(ip) 13555#endif 13556 13557#endif 13558 13559/* 13560 * Common code when a backward branch is taken. 13561 * 13562 * TODO: we could avoid a branch by just setting r0 and falling through 13563 * into the common_periodicChecks code, and having a test on r0 at the 13564 * end determine if we should return to the caller or update & branch to 13565 * the next instr. 13566 * 13567 * On entry: 13568 * r9 is PC adjustment *in bytes* 13569 */ 13570common_backwardBranch: 13571 mov r0, #kInterpEntryInstr 13572 bl common_periodicChecks 13573#if defined(WITH_JIT) 13574 GET_JIT_PROF_TABLE(r0) 13575 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 13576 cmp r0,#0 13577 bne common_updateProfile 13578 GET_INST_OPCODE(ip) 13579 GOTO_OPCODE(ip) 13580#else 13581 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 13582 GET_INST_OPCODE(ip) @ extract opcode from rINST 13583 GOTO_OPCODE(ip) @ jump to next instruction 13584#endif 13585 13586 13587/* 13588 * Need to see if the thread needs to be suspended or debugger/profiler 13589 * activity has begun. If so, we suspend the thread or side-exit to 13590 * the debug interpreter as appropriate. 13591 * 13592 * The common case is no activity on any of these, so we want to figure 13593 * that out quickly. If something is up, we can then sort out what. 13594 * 13595 * We want to be fast if the VM was built without debugger or profiler 13596 * support, but we also need to recognize that the system is usually 13597 * shipped with both of these enabled. 13598 * 13599 * TODO: reduce this so we're just checking a single location. 13600 * 13601 * On entry: 13602 * r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling) 13603 * r9 is trampoline PC adjustment *in bytes* 13604 */ 13605common_periodicChecks: 13606 ldr r1, [rGLUE, #offGlue_pInterpBreak] @ r3<- &interpBreak 13607 /* speculatively load address of thread-specific suspend count */ 13608 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 13609 ldr r1, [r1] @ r1<- interpBreak 13610 /* speculatively load thread-specific suspend count */ 13611 ldr ip, [r3] @ ip<- suspendCount (int) 13612 cmp r1, #0 @ anything unusual? 13613 bxeq lr @ return if not 13614 /* 13615 * One or more interesting events have happened. Figure out what. 13616 * 13617 * r0 still holds the reentry type. 13618 */ 13619 cmp ip, #0 @ want suspend? 13620 beq 3f @ no, must be something else 13621 13622 stmfd sp!, {r0, lr} @ preserve r0 and lr 13623#if defined(WITH_JIT) 13624 /* 13625 * Refresh the Jit's cached copy of profile table pointer. This pointer 13626 * doubles as the Jit's on/off switch. 13627 */ 13628 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable 13629 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 13630 ldr r3, [r3] @ r3 <- pJitProfTable 13631 EXPORT_PC() @ need for precise GC 13632 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch 13633#else 13634 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 13635 EXPORT_PC() @ need for precise GC 13636#endif 13637 bl dvmCheckSuspendPending @ do full check, suspend if necessary 13638 ldmfd sp!, {r0, lr} @ restore r0 and lr 13639 13640 /* 13641 * Reload the interpBreak flags - they may have changed while we 13642 * were suspended. 13643 */ 13644 ldr r1, [rGLUE, #offGlue_pInterpBreak] @ r1<- &interpBreak 13645 ldr r1, [r1] @ r1<- interpBreak 136463: 13647 /* 13648 * TODO: this code is too fragile. Need a general mechanism 13649 * to identify what actions to take by submode. Some profiling modes 13650 * (instruction count) need to single-step, while method tracing 13651 * may not. Debugging with breakpoints can run unfettered, but 13652 * source-level single-stepping requires Dalvik singlestepping. 13653 * GC may require a one-shot action and then full-speed resumption. 13654 */ 13655 ands r1, #(kSubModeDebuggerActive | kSubModeEmulatorTrace | kSubModeInstCounting) 13656 bxeq lr @ nothing to do, return 13657 13658 @ debugger/profiler enabled, bail out; glue->entryPoint was set above 13659 str r0, [rGLUE, #offGlue_entryPoint] @ store r0, need for debug/prof 13660 add rPC, rPC, r9 @ update rPC 13661 mov r1, #1 @ "want switch" = true 13662 b common_gotoBail @ side exit 13663 13664 13665/* 13666 * The equivalent of "goto bail", this calls through the "bail handler". 13667 * 13668 * State registers will be saved to the "glue" area before bailing. 13669 * 13670 * On entry: 13671 * r1 is "bool changeInterp", indicating if we want to switch to the 13672 * other interpreter or just bail all the way out 13673 */ 13674common_gotoBail: 13675 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 13676 mov r0, rGLUE @ r0<- glue ptr 13677 b dvmMterpStdBail @ call(glue, changeInterp) 13678 13679 @add r1, r1, #1 @ using (boolean+1) 13680 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 13681 @bl _longjmp @ does not return 13682 @bl common_abort 13683 13684 13685/* 13686 * Common code for jumbo method invocation. 13687 * NOTE: this adjusts rPC to account for the difference in instruction width. 13688 * As a result, the savedPc in the stack frame will not be wholly accurate. So 13689 * long as that is only used for source file line number calculations, we're 13690 * okay. 13691 * 13692 * On entry: 13693 * r0 is "Method* methodToCall", the method we're trying to call 13694 */ 13695common_invokeMethodJumbo: 13696.LinvokeNewJumbo: 13697 @ prepare to copy args to "outs" area of current frame 13698 add rPC, rPC, #4 @ adjust pc to make return consistent 13699 FETCH(r2, 1) @ r2<- BBBB (arg count) 13700 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 13701 cmp r2, #0 @ no args? 13702 beq .LinvokeArgsDone @ if no args, skip the rest 13703 FETCH(r1, 2) @ r1<- CCCC 13704 b .LinvokeRangeArgs @ handle args like invoke range 13705 13706/* 13707 * Common code for method invocation with range. 13708 * 13709 * On entry: 13710 * r0 is "Method* methodToCall", the method we're trying to call 13711 */ 13712common_invokeMethodRange: 13713.LinvokeNewRange: 13714 @ prepare to copy args to "outs" area of current frame 13715 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 13716 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 13717 beq .LinvokeArgsDone @ if no args, skip the rest 13718 FETCH(r1, 2) @ r1<- CCCC 13719 13720.LinvokeRangeArgs: 13721 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 13722 @ (very few methods have > 10 args; could unroll for common cases) 13723 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 13724 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 137251: ldr r1, [r3], #4 @ val = *fp++ 13726 subs r2, r2, #1 @ count-- 13727 str r1, [r10], #4 @ *outs++ = val 13728 bne 1b @ ...while count != 0 13729 b .LinvokeArgsDone 13730 13731/* 13732 * Common code for method invocation without range. 13733 * 13734 * On entry: 13735 * r0 is "Method* methodToCall", the method we're trying to call 13736 */ 13737common_invokeMethodNoRange: 13738.LinvokeNewNoRange: 13739 @ prepare to copy args to "outs" area of current frame 13740 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 13741 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 13742 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 13743 beq .LinvokeArgsDone 13744 13745 @ r0=methodToCall, r1=GFED, r2=count, r10=outs 13746.LinvokeNonRange: 13747 rsb r2, r2, #5 @ r2<- 5-r2 13748 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 13749 bl common_abort @ (skipped due to ARM prefetch) 137505: and ip, rINST, #0x0f00 @ isolate A 13751 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 13752 mov r0, r0 @ nop 13753 str r2, [r10, #-4]! @ *--outs = vA 137544: and ip, r1, #0xf000 @ isolate G 13755 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 13756 mov r0, r0 @ nop 13757 str r2, [r10, #-4]! @ *--outs = vG 137583: and ip, r1, #0x0f00 @ isolate F 13759 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 13760 mov r0, r0 @ nop 13761 str r2, [r10, #-4]! @ *--outs = vF 137622: and ip, r1, #0x00f0 @ isolate E 13763 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 13764 mov r0, r0 @ nop 13765 str r2, [r10, #-4]! @ *--outs = vE 137661: and ip, r1, #0x000f @ isolate D 13767 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 13768 mov r0, r0 @ nop 13769 str r2, [r10, #-4]! @ *--outs = vD 137700: @ fall through to .LinvokeArgsDone 13771 13772.LinvokeArgsDone: @ r0=methodToCall 13773 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 13774 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 13775 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 13776 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 13777 @ find space for the new stack frame, check for overflow 13778 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 13779 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 13780 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 13781@ bl common_dumpRegs 13782 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 13783 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 13784 cmp r3, r9 @ bottom < interpStackEnd? 13785 ldr lr, [rGLUE, #offGlue_pInterpBreak] 13786 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 13787 blo .LstackOverflow @ yes, this frame will overflow stack 13788 13789 @ set up newSaveArea 13790 ldr lr, [lr] @ lr<- active submodes 13791#ifdef EASY_GDB 13792 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 13793 str ip, [r10, #offStackSaveArea_prevSave] 13794#endif 13795 str rFP, [r10, #offStackSaveArea_prevFrame] 13796 str rPC, [r10, #offStackSaveArea_savedPc] 13797#if defined(WITH_JIT) 13798 mov r9, #0 13799 str r9, [r10, #offStackSaveArea_returnAddr] 13800#endif 13801 ands lr, #kSubModeMethodTrace @ method tracing? 13802 beq 1f @ skip if not 13803 stmfd sp!, {r0-r3} @ preserve r0-r3 13804 mov r1, r6 13805 @ r0=methodToCall, r1=rGlue 13806 bl dvmFastMethodTraceEnter 13807 ldmfd sp!, {r0-r3} @ restore r0-r3 138081: 13809 str r0, [r10, #offStackSaveArea_method] 13810 tst r3, #ACC_NATIVE 13811 bne .LinvokeNative 13812 13813 /* 13814 stmfd sp!, {r0-r3} 13815 bl common_printNewline 13816 mov r0, rFP 13817 mov r1, #0 13818 bl dvmDumpFp 13819 ldmfd sp!, {r0-r3} 13820 stmfd sp!, {r0-r3} 13821 mov r0, r1 13822 mov r1, r10 13823 bl dvmDumpFp 13824 bl common_printNewline 13825 ldmfd sp!, {r0-r3} 13826 */ 13827 13828 ldrh r9, [r2] @ r9 <- load INST from new PC 13829 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 13830 mov rPC, r2 @ publish new rPC 13831 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 13832 13833 @ Update "glue" values for the new method 13834 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 13835 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 13836 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 13837#if defined(WITH_JIT) 13838 GET_JIT_PROF_TABLE(r0) 13839 mov rFP, r1 @ fp = newFp 13840 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 13841 mov rINST, r9 @ publish new rINST 13842 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 13843 cmp r0,#0 13844 bne common_updateProfile 13845 GOTO_OPCODE(ip) @ jump to next instruction 13846#else 13847 mov rFP, r1 @ fp = newFp 13848 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 13849 mov rINST, r9 @ publish new rINST 13850 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 13851 GOTO_OPCODE(ip) @ jump to next instruction 13852#endif 13853 13854.LinvokeNative: 13855 @ Prep for the native call 13856 @ r0=methodToCall, r1=newFp, r10=newSaveArea 13857 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 13858 ldr lr, [rGLUE, #offGlue_pInterpBreak] 13859 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 13860 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 13861 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 13862 ldr lr, [lr] @ lr<- active submodes 13863 mov r9, r3 @ r9<- glue->self (preserve) 13864 13865 mov r2, r0 @ r2<- methodToCall 13866 mov r0, r1 @ r0<- newFp (points to args) 13867 add r1, rGLUE, #offGlue_retval @ r1<- &retval 13868 13869#ifdef ASSIST_DEBUGGER 13870 /* insert fake function header to help gdb find the stack frame */ 13871 b .Lskip 13872 .type dalvik_mterp, %function 13873dalvik_mterp: 13874 .fnstart 13875 MTERP_ENTRY1 13876 MTERP_ENTRY2 13877.Lskip: 13878#endif 13879 13880 ands lr, #kSubModeMethodTrace @ method tracing? 13881 beq 110f @ hop if not 13882 @ r2=JNIMethod, r6=rGLUE 13883 stmfd sp!, {r2,r6} 13884 13885 mov lr, pc @ set return addr 13886 ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 13887 13888 @ r0=JNIMethod, r1=rGLUE 13889 ldmfd sp!, {r0-r1} 13890 bl dvmFastNativeMethodTraceExit 13891 b 220f 13892110: 13893 mov lr, pc @ set return addr 13894 ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 13895220: 13896#if defined(WITH_JIT) 13897 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status 13898#endif 13899 13900 @ native return; r9=self, r10=newSaveArea 13901 @ equivalent to dvmPopJniLocals 13902 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 13903 ldr r1, [r9, #offThread_exception] @ check for exception 13904#if defined(WITH_JIT) 13905 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable 13906#endif 13907 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 13908 cmp r1, #0 @ null? 13909 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 13910#if defined(WITH_JIT) 13911 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch 13912#endif 13913 bne common_exceptionThrown @ no, handle exception 13914 13915 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 13916 GET_INST_OPCODE(ip) @ extract opcode from rINST 13917 GOTO_OPCODE(ip) @ jump to next instruction 13918 13919.LstackOverflow: @ r0=methodToCall 13920 mov r1, r0 @ r1<- methodToCall 13921 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 13922 bl dvmHandleStackOverflow 13923 b common_exceptionThrown 13924#ifdef ASSIST_DEBUGGER 13925 .fnend 13926 .size dalvik_mterp, .-dalvik_mterp 13927#endif 13928 13929 13930 /* 13931 * Common code for method invocation, calling through "glue code". 13932 * 13933 * TODO: now that we have range and non-range invoke handlers, this 13934 * needs to be split into two. Maybe just create entry points 13935 * that set r9 and jump here? 13936 * 13937 * On entry: 13938 * r0 is "Method* methodToCall", the method we're trying to call 13939 * r9 is "bool methodCallRange", indicating if this is a /range variant 13940 */ 13941 .if 0 13942.LinvokeOld: 13943 sub sp, sp, #8 @ space for args + pad 13944 FETCH(ip, 2) @ ip<- FEDC or CCCC 13945 mov r2, r0 @ A2<- methodToCall 13946 mov r0, rGLUE @ A0<- glue 13947 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 13948 mov r1, r9 @ A1<- methodCallRange 13949 mov r3, rINST, lsr #8 @ A3<- AA 13950 str ip, [sp, #0] @ A4<- ip 13951 bl dvmMterp_invokeMethod @ call the C invokeMethod 13952 add sp, sp, #8 @ remove arg area 13953 b common_resumeAfterGlueCall @ continue to next instruction 13954 .endif 13955 13956 13957 13958/* 13959 * Common code for handling a return instruction. 13960 * 13961 * This does not return. 13962 */ 13963common_returnFromMethod: 13964.LreturnNew: 13965 mov r0, #kInterpEntryReturn 13966 mov r9, #0 13967 bl common_periodicChecks 13968 13969 ldr lr, [rGLUE, #offGlue_pInterpBreak] 13970 SAVEAREA_FROM_FP(r0, rFP) 13971 ldr lr, [lr] @ lr<- active submodes 13972 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 13973 ands lr, #kSubModeMethodTrace @ method tracing? 13974 beq 333f 13975 stmfd sp!, {r0-r3} @ preserve r0-r3 13976 mov r0, r6 13977 @ r0=rGlue 13978 bl dvmFastJavaMethodTraceExit 13979 ldmfd sp!, {r0-r3} @ restore r0-r3 13980333: 13981 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 13982 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 13983 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 13984 @ r2<- method we're returning to 13985 cmp r2, #0 @ is this a break frame? 13986#if defined(WORKAROUND_CORTEX_A9_745320) 13987 /* Don't use conditional loads if the HW defect exists */ 13988 beq 101f 13989 ldr r10, [r2, #offMethod_clazz] @ r10<- method->clazz 13990101: 13991#else 13992 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 13993#endif 13994 mov r1, #0 @ "want switch" = false 13995 beq common_gotoBail @ break frame, bail out completely 13996 13997 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 13998 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 13999 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 14000 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 14001#if defined(WITH_JIT) 14002 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr 14003 mov rPC, r9 @ publish new rPC 14004 str r1, [rGLUE, #offGlue_methodClassDex] 14005 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land 14006 cmp r10, #0 @ caller is compiled code 14007 blxne r10 14008 GET_INST_OPCODE(ip) @ extract opcode from rINST 14009 GOTO_OPCODE(ip) @ jump to next instruction 14010#else 14011 GET_INST_OPCODE(ip) @ extract opcode from rINST 14012 mov rPC, r9 @ publish new rPC 14013 str r1, [rGLUE, #offGlue_methodClassDex] 14014 GOTO_OPCODE(ip) @ jump to next instruction 14015#endif 14016 14017 /* 14018 * Return handling, calls through "glue code". 14019 */ 14020 .if 0 14021.LreturnOld: 14022 SAVE_PC_FP_TO_GLUE() @ export state 14023 mov r0, rGLUE @ arg to function 14024 bl dvmMterp_returnFromMethod 14025 b common_resumeAfterGlueCall 14026 .endif 14027 14028 14029/* 14030 * Somebody has thrown an exception. Handle it. 14031 * 14032 * If the exception processing code returns to us (instead of falling 14033 * out of the interpreter), continue with whatever the next instruction 14034 * now happens to be. 14035 * 14036 * This does not return. 14037 */ 14038 .global dvmMterpCommonExceptionThrown 14039dvmMterpCommonExceptionThrown: 14040common_exceptionThrown: 14041.LexceptionNew: 14042 mov r0, #kInterpEntryThrow 14043 mov r9, #0 14044 bl common_periodicChecks 14045 14046 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 14047 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 14048 mov r1, r10 @ r1<- self 14049 mov r0, r9 @ r0<- exception 14050 bl dvmAddTrackedAlloc @ don't let the exception be GCed 14051 mov r3, #0 @ r3<- NULL 14052 str r3, [r10, #offThread_exception] @ self->exception = NULL 14053 14054 /* set up args and a local for "&fp" */ 14055 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 14056 str rFP, [sp, #-4]! @ *--sp = fp 14057 mov ip, sp @ ip<- &fp 14058 mov r3, #0 @ r3<- false 14059 str ip, [sp, #-4]! @ *--sp = &fp 14060 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 14061 mov r0, r10 @ r0<- self 14062 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 14063 mov r2, r9 @ r2<- exception 14064 sub r1, rPC, r1 @ r1<- pc - method->insns 14065 mov r1, r1, asr #1 @ r1<- offset in code units 14066 14067 /* call, r0 gets catchRelPc (a code-unit offset) */ 14068 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 14069 14070 /* fix earlier stack overflow if necessary; may trash rFP */ 14071 ldrb r1, [r10, #offThread_stackOverflowed] 14072 cmp r1, #0 @ did we overflow earlier? 14073 beq 1f @ no, skip ahead 14074 mov rFP, r0 @ save relPc result in rFP 14075 mov r0, r10 @ r0<- self 14076 mov r1, r9 @ r1<- exception 14077 bl dvmCleanupStackOverflow @ call(self) 14078 mov r0, rFP @ restore result 140791: 14080 14081 /* update frame pointer and check result from dvmFindCatchBlock */ 14082 ldr rFP, [sp, #4] @ retrieve the updated rFP 14083 cmp r0, #0 @ is catchRelPc < 0? 14084 add sp, sp, #8 @ restore stack 14085 bmi .LnotCaughtLocally 14086 14087 /* adjust locals to match self->curFrame and updated PC */ 14088 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 14089 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 14090 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 14091 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 14092 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 14093 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 14094 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 14095 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 14096 14097 /* release the tracked alloc on the exception */ 14098 mov r0, r9 @ r0<- exception 14099 mov r1, r10 @ r1<- self 14100 bl dvmReleaseTrackedAlloc @ release the exception 14101 14102 /* restore the exception if the handler wants it */ 14103 FETCH_INST() @ load rINST from rPC 14104 GET_INST_OPCODE(ip) @ extract opcode from rINST 14105 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 14106 streq r9, [r10, #offThread_exception] @ yes, restore the exception 14107 GOTO_OPCODE(ip) @ jump to next instruction 14108 14109.LnotCaughtLocally: @ r9=exception, r10=self 14110 /* fix stack overflow if necessary */ 14111 ldrb r1, [r10, #offThread_stackOverflowed] 14112 cmp r1, #0 @ did we overflow earlier? 14113 movne r0, r10 @ if yes: r0<- self 14114 movne r1, r9 @ if yes: r1<- exception 14115 blne dvmCleanupStackOverflow @ if yes: call(self) 14116 14117 @ may want to show "not caught locally" debug messages here 14118#if DVM_SHOW_EXCEPTION >= 2 14119 /* call __android_log_print(prio, tag, format, ...) */ 14120 /* "Exception %s from %s:%d not caught locally" */ 14121 @ dvmLineNumFromPC(method, pc - method->insns) 14122 ldr r0, [rGLUE, #offGlue_method] 14123 ldr r1, [r0, #offMethod_insns] 14124 sub r1, rPC, r1 14125 asr r1, r1, #1 14126 bl dvmLineNumFromPC 14127 str r0, [sp, #-4]! 14128 @ dvmGetMethodSourceFile(method) 14129 ldr r0, [rGLUE, #offGlue_method] 14130 bl dvmGetMethodSourceFile 14131 str r0, [sp, #-4]! 14132 @ exception->clazz->descriptor 14133 ldr r3, [r9, #offObject_clazz] 14134 ldr r3, [r3, #offClassObject_descriptor] 14135 @ 14136 ldr r2, strExceptionNotCaughtLocally 14137 ldr r1, strLogTag 14138 mov r0, #3 @ LOG_DEBUG 14139 bl __android_log_print 14140#endif 14141 str r9, [r10, #offThread_exception] @ restore exception 14142 mov r0, r9 @ r0<- exception 14143 mov r1, r10 @ r1<- self 14144 bl dvmReleaseTrackedAlloc @ release the exception 14145 mov r1, #0 @ "want switch" = false 14146 b common_gotoBail @ bail out 14147 14148 14149 /* 14150 * Exception handling, calls through "glue code". 14151 */ 14152 .if 0 14153.LexceptionOld: 14154 SAVE_PC_FP_TO_GLUE() @ export state 14155 mov r0, rGLUE @ arg to function 14156 bl dvmMterp_exceptionThrown 14157 b common_resumeAfterGlueCall 14158 .endif 14159 14160 14161/* 14162 * After returning from a "glued" function, pull out the updated 14163 * values and start executing at the next instruction. 14164 */ 14165common_resumeAfterGlueCall: 14166 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 14167 FETCH_INST() @ load rINST from rPC 14168 GET_INST_OPCODE(ip) @ extract opcode from rINST 14169 GOTO_OPCODE(ip) @ jump to next instruction 14170 14171/* 14172 * Invalid array index. Note that our calling convention is strange; we use r1 14173 * and r3 because those just happen to be the registers all our callers are 14174 * using. We shuffle them here before calling the C function. 14175 * r1: index 14176 * r3: size 14177 */ 14178common_errArrayIndex: 14179 EXPORT_PC() 14180 mov r0, r1 14181 mov r1, r3 14182 bl dvmThrowAIOOBE 14183 b common_exceptionThrown 14184 14185/* 14186 * Integer divide or mod by zero. 14187 */ 14188common_errDivideByZero: 14189 EXPORT_PC() 14190 ldr r0, strArithmeticException 14191 ldr r1, strDivideByZero 14192 bl dvmThrowException 14193 b common_exceptionThrown 14194 14195/* 14196 * Attempt to allocate an array with a negative size. 14197 */ 14198common_errNegativeArraySize: 14199 EXPORT_PC() 14200 ldr r0, strNegativeArraySizeException 14201 mov r1, #0 14202 bl dvmThrowException 14203 b common_exceptionThrown 14204 14205/* 14206 * Invocation of a non-existent method. 14207 */ 14208common_errNoSuchMethod: 14209 EXPORT_PC() 14210 ldr r0, strNoSuchMethodError 14211 mov r1, #0 14212 bl dvmThrowException 14213 b common_exceptionThrown 14214 14215/* 14216 * We encountered a null object when we weren't expecting one. We 14217 * export the PC, throw a NullPointerException, and goto the exception 14218 * processing code. 14219 */ 14220common_errNullObject: 14221 EXPORT_PC() 14222 ldr r0, strNullPointerException 14223 mov r1, #0 14224 bl dvmThrowException 14225 b common_exceptionThrown 14226 14227/* 14228 * For debugging, cause an immediate fault. The source address will 14229 * be in lr (use a bl instruction to jump here). 14230 */ 14231common_abort: 14232 ldr pc, .LdeadFood 14233.LdeadFood: 14234 .word 0xdeadf00d 14235 14236/* 14237 * Spit out a "we were here", preserving all registers. (The attempt 14238 * to save ip won't work, but we need to save an even number of 14239 * registers for EABI 64-bit stack alignment.) 14240 */ 14241 .macro SQUEAK num 14242common_squeak\num: 14243 stmfd sp!, {r0, r1, r2, r3, ip, lr} 14244 ldr r0, strSqueak 14245 mov r1, #\num 14246 bl printf 14247 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 14248 bx lr 14249 .endm 14250 14251 SQUEAK 0 14252 SQUEAK 1 14253 SQUEAK 2 14254 SQUEAK 3 14255 SQUEAK 4 14256 SQUEAK 5 14257 14258/* 14259 * Spit out the number in r0, preserving registers. 14260 */ 14261common_printNum: 14262 stmfd sp!, {r0, r1, r2, r3, ip, lr} 14263 mov r1, r0 14264 ldr r0, strSqueak 14265 bl printf 14266 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 14267 bx lr 14268 14269/* 14270 * Print a newline, preserving registers. 14271 */ 14272common_printNewline: 14273 stmfd sp!, {r0, r1, r2, r3, ip, lr} 14274 ldr r0, strNewline 14275 bl printf 14276 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 14277 bx lr 14278 14279 /* 14280 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 14281 */ 14282common_printHex: 14283 stmfd sp!, {r0, r1, r2, r3, ip, lr} 14284 mov r1, r0 14285 ldr r0, strPrintHex 14286 bl printf 14287 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 14288 bx lr 14289 14290/* 14291 * Print the 64-bit quantity in r0-r1, preserving registers. 14292 */ 14293common_printLong: 14294 stmfd sp!, {r0, r1, r2, r3, ip, lr} 14295 mov r3, r1 14296 mov r2, r0 14297 ldr r0, strPrintLong 14298 bl printf 14299 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 14300 bx lr 14301 14302/* 14303 * Print full method info. Pass the Method* in r0. Preserves regs. 14304 */ 14305common_printMethod: 14306 stmfd sp!, {r0, r1, r2, r3, ip, lr} 14307 bl dvmMterpPrintMethod 14308 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 14309 bx lr 14310 14311/* 14312 * Call a C helper function that dumps regs and possibly some 14313 * additional info. Requires the C function to be compiled in. 14314 */ 14315 .if 0 14316common_dumpRegs: 14317 stmfd sp!, {r0, r1, r2, r3, ip, lr} 14318 bl dvmMterpDumpArmRegs 14319 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 14320 bx lr 14321 .endif 14322 14323#if 0 14324/* 14325 * Experiment on VFP mode. 14326 * 14327 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 14328 * 14329 * Updates the bits specified by "mask", setting them to the values in "val". 14330 */ 14331setFPSCR: 14332 and r0, r0, r1 @ make sure no stray bits are set 14333 fmrx r2, fpscr @ get VFP reg 14334 mvn r1, r1 @ bit-invert mask 14335 and r2, r2, r1 @ clear masked bits 14336 orr r2, r2, r0 @ set specified bits 14337 fmxr fpscr, r2 @ set VFP reg 14338 mov r0, r2 @ return new value 14339 bx lr 14340 14341 .align 2 14342 .global dvmConfigureFP 14343 .type dvmConfigureFP, %function 14344dvmConfigureFP: 14345 stmfd sp!, {ip, lr} 14346 /* 0x03000000 sets DN/FZ */ 14347 /* 0x00009f00 clears the six exception enable flags */ 14348 bl common_squeak0 14349 mov r0, #0x03000000 @ r0<- 0x03000000 14350 add r1, r0, #0x9f00 @ r1<- 0x03009f00 14351 bl setFPSCR 14352 ldmfd sp!, {ip, pc} 14353#endif 14354 14355 14356/* 14357 * String references, must be close to the code that uses them. 14358 */ 14359 .align 2 14360strArithmeticException: 14361 .word .LstrArithmeticException 14362strDivideByZero: 14363 .word .LstrDivideByZero 14364strNegativeArraySizeException: 14365 .word .LstrNegativeArraySizeException 14366strNoSuchMethodError: 14367 .word .LstrNoSuchMethodError 14368strNullPointerException: 14369 .word .LstrNullPointerException 14370 14371strLogTag: 14372 .word .LstrLogTag 14373strExceptionNotCaughtLocally: 14374 .word .LstrExceptionNotCaughtLocally 14375 14376strNewline: 14377 .word .LstrNewline 14378strSqueak: 14379 .word .LstrSqueak 14380strPrintHex: 14381 .word .LstrPrintHex 14382strPrintLong: 14383 .word .LstrPrintLong 14384 14385/* 14386 * Zero-terminated ASCII string data. 14387 * 14388 * On ARM we have two choices: do like gcc does, and LDR from a .word 14389 * with the address, or use an ADR pseudo-op to get the address 14390 * directly. ADR saves 4 bytes and an indirection, but it's using a 14391 * PC-relative addressing mode and hence has a limited range, which 14392 * makes it not work well with mergeable string sections. 14393 */ 14394 .section .rodata.str1.4,"aMS",%progbits,1 14395 14396.LstrBadEntryPoint: 14397 .asciz "Bad entry point %d\n" 14398.LstrArithmeticException: 14399 .asciz "Ljava/lang/ArithmeticException;" 14400.LstrDivideByZero: 14401 .asciz "divide by zero" 14402.LstrFilledNewArrayNotImpl: 14403 .asciz "filled-new-array only implemented for objects and 'int'" 14404.LstrInternalError: 14405 .asciz "Ljava/lang/InternalError;" 14406.LstrInstantiationError: 14407 .asciz "Ljava/lang/InstantiationError;" 14408.LstrNegativeArraySizeException: 14409 .asciz "Ljava/lang/NegativeArraySizeException;" 14410.LstrNoSuchMethodError: 14411 .asciz "Ljava/lang/NoSuchMethodError;" 14412.LstrNullPointerException: 14413 .asciz "Ljava/lang/NullPointerException;" 14414 14415.LstrLogTag: 14416 .asciz "mterp" 14417.LstrExceptionNotCaughtLocally: 14418 .asciz "Exception %s from %s:%d not caught locally\n" 14419 14420.LstrNewline: 14421 .asciz "\n" 14422.LstrSqueak: 14423 .asciz "<%d>" 14424.LstrPrintHex: 14425 .asciz "<0x%x>" 14426.LstrPrintLong: 14427 .asciz "<%lld>" 14428 14429