InterpAsm-armv5te-vfp.S revision d3a92b577f11c6357c76dc850c6cbf352ef4c760
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 363 364 .global dvmMterpStdBail 365 .type dvmMterpStdBail, %function 366 367/* 368 * Restore the stack pointer and PC from the save point established on entry. 369 * This is essentially the same as a longjmp, but should be cheaper. The 370 * last instruction causes us to return to whoever called dvmMterpStdRun. 371 * 372 * We pushed some registers on the stack in dvmMterpStdRun, then saved 373 * SP and LR. Here we restore SP, restore the registers, and then restore 374 * LR to PC. 375 * 376 * On entry: 377 * r0 MterpGlue* glue 378 * r1 bool changeInterp 379 */ 380dvmMterpStdBail: 381 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 382 mov r0, r1 @ return the changeInterp value 383 add sp, sp, #4 @ un-align 64 384 ldmfd sp!, {r4-r10,fp,pc} @ restore 9 regs and return 385 386 387/* 388 * String references. 389 */ 390strBadEntryPoint: 391 .word .LstrBadEntryPoint 392 393 394 .global dvmAsmInstructionStart 395 .type dvmAsmInstructionStart, %function 396dvmAsmInstructionStart = .L_OP_NOP 397 .text 398 399/* ------------------------------ */ 400 .balign 64 401.L_OP_NOP: /* 0x00 */ 402/* File: armv5te/OP_NOP.S */ 403 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST 404 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 405 GOTO_OPCODE(ip) @ execute it 406 407#ifdef ASSIST_DEBUGGER 408 /* insert fake function header to help gdb find the stack frame */ 409 .type dalvik_inst, %function 410dalvik_inst: 411 .fnstart 412 MTERP_ENTRY1 413 MTERP_ENTRY2 414 .fnend 415#endif 416 417/* ------------------------------ */ 418 .balign 64 419.L_OP_MOVE: /* 0x01 */ 420/* File: armv5te/OP_MOVE.S */ 421 /* for move, move-object, long-to-int */ 422 /* op vA, vB */ 423 mov r1, rINST, lsr #12 @ r1<- B from 15:12 424 mov r0, rINST, lsr #8 @ r0<- A from 11:8 425 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 426 GET_VREG(r2, r1) @ r2<- fp[B] 427 and r0, r0, #15 428 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 429 SET_VREG(r2, r0) @ fp[A]<- r2 430 GOTO_OPCODE(ip) @ execute next instruction 431 432/* ------------------------------ */ 433 .balign 64 434.L_OP_MOVE_FROM16: /* 0x02 */ 435/* File: armv5te/OP_MOVE_FROM16.S */ 436 /* for: move/from16, move-object/from16 */ 437 /* op vAA, vBBBB */ 438 FETCH(r1, 1) @ r1<- BBBB 439 mov r0, rINST, lsr #8 @ r0<- AA 440 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 441 GET_VREG(r2, r1) @ r2<- fp[BBBB] 442 GET_INST_OPCODE(ip) @ extract opcode from rINST 443 SET_VREG(r2, r0) @ fp[AA]<- r2 444 GOTO_OPCODE(ip) @ jump to next instruction 445 446/* ------------------------------ */ 447 .balign 64 448.L_OP_MOVE_16: /* 0x03 */ 449/* File: armv5te/OP_MOVE_16.S */ 450 /* for: move/16, move-object/16 */ 451 /* op vAAAA, vBBBB */ 452 FETCH(r1, 2) @ r1<- BBBB 453 FETCH(r0, 1) @ r0<- AAAA 454 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 455 GET_VREG(r2, r1) @ r2<- fp[BBBB] 456 GET_INST_OPCODE(ip) @ extract opcode from rINST 457 SET_VREG(r2, r0) @ fp[AAAA]<- r2 458 GOTO_OPCODE(ip) @ jump to next instruction 459 460/* ------------------------------ */ 461 .balign 64 462.L_OP_MOVE_WIDE: /* 0x04 */ 463/* File: armv5te/OP_MOVE_WIDE.S */ 464 /* move-wide vA, vB */ 465 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 466 mov r2, rINST, lsr #8 @ r2<- A(+) 467 mov r3, rINST, lsr #12 @ r3<- B 468 and r2, r2, #15 469 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 470 add r2, rFP, r2, lsl #2 @ r2<- &fp[A] 471 ldmia r3, {r0-r1} @ r0/r1<- fp[B] 472 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 473 GET_INST_OPCODE(ip) @ extract opcode from rINST 474 stmia r2, {r0-r1} @ fp[A]<- r0/r1 475 GOTO_OPCODE(ip) @ jump to next instruction 476 477/* ------------------------------ */ 478 .balign 64 479.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 480/* File: armv5te/OP_MOVE_WIDE_FROM16.S */ 481 /* move-wide/from16 vAA, vBBBB */ 482 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 483 FETCH(r3, 1) @ r3<- BBBB 484 mov r2, rINST, lsr #8 @ r2<- AA 485 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 486 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 487 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 488 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 489 GET_INST_OPCODE(ip) @ extract opcode from rINST 490 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 491 GOTO_OPCODE(ip) @ jump to next instruction 492 493/* ------------------------------ */ 494 .balign 64 495.L_OP_MOVE_WIDE_16: /* 0x06 */ 496/* File: armv5te/OP_MOVE_WIDE_16.S */ 497 /* move-wide/16 vAAAA, vBBBB */ 498 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 499 FETCH(r3, 2) @ r3<- BBBB 500 FETCH(r2, 1) @ r2<- AAAA 501 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 502 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA] 503 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 504 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 505 GET_INST_OPCODE(ip) @ extract opcode from rINST 506 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1 507 GOTO_OPCODE(ip) @ jump to next instruction 508 509/* ------------------------------ */ 510 .balign 64 511.L_OP_MOVE_OBJECT: /* 0x07 */ 512/* File: armv5te/OP_MOVE_OBJECT.S */ 513/* File: armv5te/OP_MOVE.S */ 514 /* for move, move-object, long-to-int */ 515 /* op vA, vB */ 516 mov r1, rINST, lsr #12 @ r1<- B from 15:12 517 mov r0, rINST, lsr #8 @ r0<- A from 11:8 518 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 519 GET_VREG(r2, r1) @ r2<- fp[B] 520 and r0, r0, #15 521 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 522 SET_VREG(r2, r0) @ fp[A]<- r2 523 GOTO_OPCODE(ip) @ execute next instruction 524 525 526/* ------------------------------ */ 527 .balign 64 528.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 529/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */ 530/* File: armv5te/OP_MOVE_FROM16.S */ 531 /* for: move/from16, move-object/from16 */ 532 /* op vAA, vBBBB */ 533 FETCH(r1, 1) @ r1<- BBBB 534 mov r0, rINST, lsr #8 @ r0<- AA 535 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 536 GET_VREG(r2, r1) @ r2<- fp[BBBB] 537 GET_INST_OPCODE(ip) @ extract opcode from rINST 538 SET_VREG(r2, r0) @ fp[AA]<- r2 539 GOTO_OPCODE(ip) @ jump to next instruction 540 541 542/* ------------------------------ */ 543 .balign 64 544.L_OP_MOVE_OBJECT_16: /* 0x09 */ 545/* File: armv5te/OP_MOVE_OBJECT_16.S */ 546/* File: armv5te/OP_MOVE_16.S */ 547 /* for: move/16, move-object/16 */ 548 /* op vAAAA, vBBBB */ 549 FETCH(r1, 2) @ r1<- BBBB 550 FETCH(r0, 1) @ r0<- AAAA 551 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 552 GET_VREG(r2, r1) @ r2<- fp[BBBB] 553 GET_INST_OPCODE(ip) @ extract opcode from rINST 554 SET_VREG(r2, r0) @ fp[AAAA]<- r2 555 GOTO_OPCODE(ip) @ jump to next instruction 556 557 558/* ------------------------------ */ 559 .balign 64 560.L_OP_MOVE_RESULT: /* 0x0a */ 561/* File: armv5te/OP_MOVE_RESULT.S */ 562 /* for: move-result, move-result-object */ 563 /* op vAA */ 564 mov r2, rINST, lsr #8 @ r2<- AA 565 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 566 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 567 GET_INST_OPCODE(ip) @ extract opcode from rINST 568 SET_VREG(r0, r2) @ fp[AA]<- r0 569 GOTO_OPCODE(ip) @ jump to next instruction 570 571/* ------------------------------ */ 572 .balign 64 573.L_OP_MOVE_RESULT_WIDE: /* 0x0b */ 574/* File: armv5te/OP_MOVE_RESULT_WIDE.S */ 575 /* move-result-wide vAA */ 576 mov r2, rINST, lsr #8 @ r2<- AA 577 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 578 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 579 ldmia r3, {r0-r1} @ r0/r1<- retval.j 580 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 581 GET_INST_OPCODE(ip) @ extract opcode from rINST 582 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 583 GOTO_OPCODE(ip) @ jump to next instruction 584 585/* ------------------------------ */ 586 .balign 64 587.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 588/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */ 589/* File: armv5te/OP_MOVE_RESULT.S */ 590 /* for: move-result, move-result-object */ 591 /* op vAA */ 592 mov r2, rINST, lsr #8 @ r2<- AA 593 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 594 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 595 GET_INST_OPCODE(ip) @ extract opcode from rINST 596 SET_VREG(r0, r2) @ fp[AA]<- r0 597 GOTO_OPCODE(ip) @ jump to next instruction 598 599 600/* ------------------------------ */ 601 .balign 64 602.L_OP_MOVE_EXCEPTION: /* 0x0d */ 603/* File: armv5te/OP_MOVE_EXCEPTION.S */ 604 /* move-exception vAA */ 605 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 606 mov r2, rINST, lsr #8 @ r2<- AA 607 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass 608 mov r1, #0 @ r1<- 0 609 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 610 SET_VREG(r3, r2) @ fp[AA]<- exception obj 611 GET_INST_OPCODE(ip) @ extract opcode from rINST 612 str r1, [r0, #offThread_exception] @ dvmClearException bypass 613 GOTO_OPCODE(ip) @ jump to next instruction 614 615/* ------------------------------ */ 616 .balign 64 617.L_OP_RETURN_VOID: /* 0x0e */ 618/* File: armv5te/OP_RETURN_VOID.S */ 619 b common_returnFromMethod 620 621/* ------------------------------ */ 622 .balign 64 623.L_OP_RETURN: /* 0x0f */ 624/* File: armv5te/OP_RETURN.S */ 625 /* 626 * Return a 32-bit value. Copies the return value into the "glue" 627 * structure, then jumps to the return handler. 628 * 629 * for: return, return-object 630 */ 631 /* op vAA */ 632 mov r2, rINST, lsr #8 @ r2<- AA 633 GET_VREG(r0, r2) @ r0<- vAA 634 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 635 b common_returnFromMethod 636 637/* ------------------------------ */ 638 .balign 64 639.L_OP_RETURN_WIDE: /* 0x10 */ 640/* File: armv5te/OP_RETURN_WIDE.S */ 641 /* 642 * Return a 64-bit value. Copies the return value into the "glue" 643 * structure, then jumps to the return handler. 644 */ 645 /* return-wide vAA */ 646 mov r2, rINST, lsr #8 @ r2<- AA 647 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 648 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 649 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1 650 stmia r3, {r0-r1} @ retval<- r0/r1 651 b common_returnFromMethod 652 653/* ------------------------------ */ 654 .balign 64 655.L_OP_RETURN_OBJECT: /* 0x11 */ 656/* File: armv5te/OP_RETURN_OBJECT.S */ 657/* File: armv5te/OP_RETURN.S */ 658 /* 659 * Return a 32-bit value. Copies the return value into the "glue" 660 * structure, then jumps to the return handler. 661 * 662 * for: return, return-object 663 */ 664 /* op vAA */ 665 mov r2, rINST, lsr #8 @ r2<- AA 666 GET_VREG(r0, r2) @ r0<- vAA 667 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 668 b common_returnFromMethod 669 670 671/* ------------------------------ */ 672 .balign 64 673.L_OP_CONST_4: /* 0x12 */ 674/* File: armv5te/OP_CONST_4.S */ 675 /* const/4 vA, #+B */ 676 mov r1, rINST, lsl #16 @ r1<- Bxxx0000 677 mov r0, rINST, lsr #8 @ r0<- A+ 678 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 679 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended) 680 and r0, r0, #15 681 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 682 SET_VREG(r1, r0) @ fp[A]<- r1 683 GOTO_OPCODE(ip) @ execute next instruction 684 685/* ------------------------------ */ 686 .balign 64 687.L_OP_CONST_16: /* 0x13 */ 688/* File: armv5te/OP_CONST_16.S */ 689 /* const/16 vAA, #+BBBB */ 690 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 691 mov r3, rINST, lsr #8 @ r3<- AA 692 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 693 SET_VREG(r0, r3) @ vAA<- r0 694 GET_INST_OPCODE(ip) @ extract opcode from rINST 695 GOTO_OPCODE(ip) @ jump to next instruction 696 697/* ------------------------------ */ 698 .balign 64 699.L_OP_CONST: /* 0x14 */ 700/* File: armv5te/OP_CONST.S */ 701 /* const vAA, #+BBBBbbbb */ 702 mov r3, rINST, lsr #8 @ r3<- AA 703 FETCH(r0, 1) @ r0<- bbbb (low) 704 FETCH(r1, 2) @ r1<- BBBB (high) 705 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 706 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 707 GET_INST_OPCODE(ip) @ extract opcode from rINST 708 SET_VREG(r0, r3) @ vAA<- r0 709 GOTO_OPCODE(ip) @ jump to next instruction 710 711/* ------------------------------ */ 712 .balign 64 713.L_OP_CONST_HIGH16: /* 0x15 */ 714/* File: armv5te/OP_CONST_HIGH16.S */ 715 /* const/high16 vAA, #+BBBB0000 */ 716 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended) 717 mov r3, rINST, lsr #8 @ r3<- AA 718 mov r0, r0, lsl #16 @ r0<- BBBB0000 719 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 720 SET_VREG(r0, r3) @ vAA<- r0 721 GET_INST_OPCODE(ip) @ extract opcode from rINST 722 GOTO_OPCODE(ip) @ jump to next instruction 723 724/* ------------------------------ */ 725 .balign 64 726.L_OP_CONST_WIDE_16: /* 0x16 */ 727/* File: armv5te/OP_CONST_WIDE_16.S */ 728 /* const-wide/16 vAA, #+BBBB */ 729 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 730 mov r3, rINST, lsr #8 @ r3<- AA 731 mov r1, r0, asr #31 @ r1<- ssssssss 732 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 733 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 734 GET_INST_OPCODE(ip) @ extract opcode from rINST 735 stmia r3, {r0-r1} @ vAA<- r0/r1 736 GOTO_OPCODE(ip) @ jump to next instruction 737 738/* ------------------------------ */ 739 .balign 64 740.L_OP_CONST_WIDE_32: /* 0x17 */ 741/* File: armv5te/OP_CONST_WIDE_32.S */ 742 /* const-wide/32 vAA, #+BBBBbbbb */ 743 FETCH(r0, 1) @ r0<- 0000bbbb (low) 744 mov r3, rINST, lsr #8 @ r3<- AA 745 FETCH_S(r2, 2) @ r2<- ssssBBBB (high) 746 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 747 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb 748 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 749 mov r1, r0, asr #31 @ r1<- ssssssss 750 GET_INST_OPCODE(ip) @ extract opcode from rINST 751 stmia r3, {r0-r1} @ vAA<- r0/r1 752 GOTO_OPCODE(ip) @ jump to next instruction 753 754/* ------------------------------ */ 755 .balign 64 756.L_OP_CONST_WIDE: /* 0x18 */ 757/* File: armv5te/OP_CONST_WIDE.S */ 758 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 759 FETCH(r0, 1) @ r0<- bbbb (low) 760 FETCH(r1, 2) @ r1<- BBBB (low middle) 761 FETCH(r2, 3) @ r2<- hhhh (high middle) 762 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word) 763 FETCH(r3, 4) @ r3<- HHHH (high) 764 mov r9, rINST, lsr #8 @ r9<- AA 765 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word) 766 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 767 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 768 GET_INST_OPCODE(ip) @ extract opcode from rINST 769 stmia r9, {r0-r1} @ vAA<- r0/r1 770 GOTO_OPCODE(ip) @ jump to next instruction 771 772/* ------------------------------ */ 773 .balign 64 774.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 775/* File: armv5te/OP_CONST_WIDE_HIGH16.S */ 776 /* const-wide/high16 vAA, #+BBBB000000000000 */ 777 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended) 778 mov r3, rINST, lsr #8 @ r3<- AA 779 mov r0, #0 @ r0<- 00000000 780 mov r1, r1, lsl #16 @ r1<- BBBB0000 781 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 782 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 783 GET_INST_OPCODE(ip) @ extract opcode from rINST 784 stmia r3, {r0-r1} @ vAA<- r0/r1 785 GOTO_OPCODE(ip) @ jump to next instruction 786 787/* ------------------------------ */ 788 .balign 64 789.L_OP_CONST_STRING: /* 0x1a */ 790/* File: armv5te/OP_CONST_STRING.S */ 791 /* const/string vAA, String@BBBB */ 792 FETCH(r1, 1) @ r1<- BBBB 793 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 794 mov r9, rINST, lsr #8 @ r9<- AA 795 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 796 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 797 cmp r0, #0 @ not yet resolved? 798 beq .LOP_CONST_STRING_resolve 799 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 800 GET_INST_OPCODE(ip) @ extract opcode from rINST 801 SET_VREG(r0, r9) @ vAA<- r0 802 GOTO_OPCODE(ip) @ jump to next instruction 803 804/* ------------------------------ */ 805 .balign 64 806.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 807/* File: armv5te/OP_CONST_STRING_JUMBO.S */ 808 /* const/string vAA, String@BBBBBBBB */ 809 FETCH(r0, 1) @ r0<- bbbb (low) 810 FETCH(r1, 2) @ r1<- BBBB (high) 811 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 812 mov r9, rINST, lsr #8 @ r9<- AA 813 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 814 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 815 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 816 cmp r0, #0 817 beq .LOP_CONST_STRING_JUMBO_resolve 818 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 819 GET_INST_OPCODE(ip) @ extract opcode from rINST 820 SET_VREG(r0, r9) @ vAA<- r0 821 GOTO_OPCODE(ip) @ jump to next instruction 822 823/* ------------------------------ */ 824 .balign 64 825.L_OP_CONST_CLASS: /* 0x1c */ 826/* File: armv5te/OP_CONST_CLASS.S */ 827 /* const/class vAA, Class@BBBB */ 828 FETCH(r1, 1) @ r1<- BBBB 829 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 830 mov r9, rINST, lsr #8 @ r9<- AA 831 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 832 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB] 833 cmp r0, #0 @ not yet resolved? 834 beq .LOP_CONST_CLASS_resolve 835 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 836 GET_INST_OPCODE(ip) @ extract opcode from rINST 837 SET_VREG(r0, r9) @ vAA<- r0 838 GOTO_OPCODE(ip) @ jump to next instruction 839 840/* ------------------------------ */ 841 .balign 64 842.L_OP_MONITOR_ENTER: /* 0x1d */ 843/* File: armv5te/OP_MONITOR_ENTER.S */ 844 /* 845 * Synchronize on an object. 846 */ 847 /* monitor-enter vAA */ 848 mov r2, rINST, lsr #8 @ r2<- AA 849 GET_VREG(r1, r2) @ r1<- vAA (object) 850 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 851 cmp r1, #0 @ null object? 852 EXPORT_PC() @ need for precise GC 853 beq common_errNullObject @ null object, throw an exception 854 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 855 bl dvmLockObject @ call(self, obj) 856 GET_INST_OPCODE(ip) @ extract opcode from rINST 857 GOTO_OPCODE(ip) @ jump to next instruction 858 859/* ------------------------------ */ 860 .balign 64 861.L_OP_MONITOR_EXIT: /* 0x1e */ 862/* File: armv5te/OP_MONITOR_EXIT.S */ 863 /* 864 * Unlock an object. 865 * 866 * Exceptions that occur when unlocking a monitor need to appear as 867 * if they happened at the following instruction. See the Dalvik 868 * instruction spec. 869 */ 870 /* monitor-exit vAA */ 871 mov r2, rINST, lsr #8 @ r2<- AA 872 EXPORT_PC() @ before fetch: export the PC 873 GET_VREG(r1, r2) @ r1<- vAA (object) 874 cmp r1, #0 @ null object? 875 beq 1f @ yes 876 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 877 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 878 cmp r0, #0 @ failed? 879 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 880 beq common_exceptionThrown @ yes, exception is pending 881 GET_INST_OPCODE(ip) @ extract opcode from rINST 882 GOTO_OPCODE(ip) @ jump to next instruction 8831: 884 FETCH_ADVANCE_INST(1) @ advance before throw 885 b common_errNullObject 886 887/* ------------------------------ */ 888 .balign 64 889.L_OP_CHECK_CAST: /* 0x1f */ 890/* File: armv5te/OP_CHECK_CAST.S */ 891 /* 892 * Check to see if a cast from one class to another is allowed. 893 */ 894 /* check-cast vAA, class@BBBB */ 895 mov r3, rINST, lsr #8 @ r3<- AA 896 FETCH(r2, 1) @ r2<- BBBB 897 GET_VREG(r9, r3) @ r9<- object 898 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 899 cmp r9, #0 @ is object null? 900 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 901 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 902 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 903 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 904 cmp r1, #0 @ have we resolved this before? 905 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 906.LOP_CHECK_CAST_resolved: 907 cmp r0, r1 @ same class (trivial success)? 908 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 909.LOP_CHECK_CAST_okay: 910 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 911 GET_INST_OPCODE(ip) @ extract opcode from rINST 912 GOTO_OPCODE(ip) @ jump to next instruction 913 914/* ------------------------------ */ 915 .balign 64 916.L_OP_INSTANCE_OF: /* 0x20 */ 917/* File: armv5te/OP_INSTANCE_OF.S */ 918 /* 919 * Check to see if an object reference is an instance of a class. 920 * 921 * Most common situation is a non-null object, being compared against 922 * an already-resolved class. 923 */ 924 /* instance-of vA, vB, class@CCCC */ 925 mov r3, rINST, lsr #12 @ r3<- B 926 mov r9, rINST, lsr #8 @ r9<- A+ 927 GET_VREG(r0, r3) @ r0<- vB (object) 928 and r9, r9, #15 @ r9<- A 929 cmp r0, #0 @ is object null? 930 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 931 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 932 FETCH(r3, 1) @ r3<- CCCC 933 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 934 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 935 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 936 cmp r1, #0 @ have we resolved this before? 937 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 938.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 939 cmp r0, r1 @ same class (trivial success)? 940 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 941 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 942 943/* ------------------------------ */ 944 .balign 64 945.L_OP_ARRAY_LENGTH: /* 0x21 */ 946/* File: armv5te/OP_ARRAY_LENGTH.S */ 947 /* 948 * Return the length of an array. 949 */ 950 mov r1, rINST, lsr #12 @ r1<- B 951 mov r2, rINST, lsr #8 @ r2<- A+ 952 GET_VREG(r0, r1) @ r0<- vB (object ref) 953 and r2, r2, #15 @ r2<- A 954 cmp r0, #0 @ is object null? 955 beq common_errNullObject @ yup, fail 956 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 957 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 958 GET_INST_OPCODE(ip) @ extract opcode from rINST 959 SET_VREG(r3, r2) @ vB<- length 960 GOTO_OPCODE(ip) @ jump to next instruction 961 962/* ------------------------------ */ 963 .balign 64 964.L_OP_NEW_INSTANCE: /* 0x22 */ 965/* File: armv5te/OP_NEW_INSTANCE.S */ 966 /* 967 * Create a new instance of a class. 968 */ 969 /* new-instance vAA, class@BBBB */ 970 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 971 FETCH(r1, 1) @ r1<- BBBB 972 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 973 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 974 EXPORT_PC() @ req'd for init, resolve, alloc 975 cmp r0, #0 @ already resolved? 976 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 977.LOP_NEW_INSTANCE_resolved: @ r0=class 978 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 979 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 980 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 981.LOP_NEW_INSTANCE_initialized: @ r0=class 982 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 983 bl dvmAllocObject @ r0<- new object 984 b .LOP_NEW_INSTANCE_finish @ continue 985 986/* ------------------------------ */ 987 .balign 64 988.L_OP_NEW_ARRAY: /* 0x23 */ 989/* File: armv5te/OP_NEW_ARRAY.S */ 990 /* 991 * Allocate an array of objects, specified with the array class 992 * and a count. 993 * 994 * The verifier guarantees that this is an array class, so we don't 995 * check for it here. 996 */ 997 /* new-array vA, vB, class@CCCC */ 998 mov r0, rINST, lsr #12 @ r0<- B 999 FETCH(r2, 1) @ r2<- CCCC 1000 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1001 GET_VREG(r1, r0) @ r1<- vB (array length) 1002 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1003 cmp r1, #0 @ check length 1004 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 1005 bmi common_errNegativeArraySize @ negative length, bail 1006 cmp r0, #0 @ already resolved? 1007 EXPORT_PC() @ req'd for resolve, alloc 1008 bne .LOP_NEW_ARRAY_finish @ resolved, continue 1009 b .LOP_NEW_ARRAY_resolve @ do resolve now 1010 1011/* ------------------------------ */ 1012 .balign 64 1013.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1014/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1015 /* 1016 * Create a new array with elements filled from registers. 1017 * 1018 * for: filled-new-array, filled-new-array/range 1019 */ 1020 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1021 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1022 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1023 FETCH(r1, 1) @ r1<- BBBB 1024 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1025 EXPORT_PC() @ need for resolve and alloc 1026 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1027 mov r10, rINST, lsr #8 @ r10<- AA or BA 1028 cmp r0, #0 @ already resolved? 1029 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10308: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1031 mov r2, #0 @ r2<- false 1032 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1033 bl dvmResolveClass @ r0<- call(clazz, ref) 1034 cmp r0, #0 @ got null? 1035 beq common_exceptionThrown @ yes, handle exception 1036 b .LOP_FILLED_NEW_ARRAY_continue 1037 1038/* ------------------------------ */ 1039 .balign 64 1040.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1041/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1042/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1043 /* 1044 * Create a new array with elements filled from registers. 1045 * 1046 * for: filled-new-array, filled-new-array/range 1047 */ 1048 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1049 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1050 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1051 FETCH(r1, 1) @ r1<- BBBB 1052 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1053 EXPORT_PC() @ need for resolve and alloc 1054 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1055 mov r10, rINST, lsr #8 @ r10<- AA or BA 1056 cmp r0, #0 @ already resolved? 1057 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10588: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1059 mov r2, #0 @ r2<- false 1060 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1061 bl dvmResolveClass @ r0<- call(clazz, ref) 1062 cmp r0, #0 @ got null? 1063 beq common_exceptionThrown @ yes, handle exception 1064 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1065 1066 1067/* ------------------------------ */ 1068 .balign 64 1069.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1070/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1071 /* fill-array-data vAA, +BBBBBBBB */ 1072 FETCH(r0, 1) @ r0<- bbbb (lo) 1073 FETCH(r1, 2) @ r1<- BBBB (hi) 1074 mov r3, rINST, lsr #8 @ r3<- AA 1075 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1076 GET_VREG(r0, r3) @ r0<- vAA (array object) 1077 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1078 EXPORT_PC(); 1079 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1080 cmp r0, #0 @ 0 means an exception is thrown 1081 beq common_exceptionThrown @ has exception 1082 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1083 GET_INST_OPCODE(ip) @ extract opcode from rINST 1084 GOTO_OPCODE(ip) @ jump to next instruction 1085 1086/* ------------------------------ */ 1087 .balign 64 1088.L_OP_THROW: /* 0x27 */ 1089/* File: armv5te/OP_THROW.S */ 1090 /* 1091 * Throw an exception object in the current thread. 1092 */ 1093 /* throw vAA */ 1094 mov r2, rINST, lsr #8 @ r2<- AA 1095 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1096 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1097 EXPORT_PC() @ exception handler can throw 1098 cmp r1, #0 @ null object? 1099 beq common_errNullObject @ yes, throw an NPE instead 1100 @ bypass dvmSetException, just store it 1101 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1102 b common_exceptionThrown 1103 1104/* ------------------------------ */ 1105 .balign 64 1106.L_OP_GOTO: /* 0x28 */ 1107/* File: armv5te/OP_GOTO.S */ 1108 /* 1109 * Unconditional branch, 8-bit offset. 1110 * 1111 * The branch distance is a signed code-unit offset, which we need to 1112 * double to get a byte offset. 1113 */ 1114 /* goto +AA */ 1115 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1116 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1117 mov r9, r9, lsl #1 @ r9<- byte offset 1118 bmi common_backwardBranch @ backward branch, do periodic checks 1119#if defined(WITH_JIT) 1120 GET_JIT_PROF_TABLE(r0) 1121 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1122 cmp r0,#0 1123 bne common_updateProfile 1124 GET_INST_OPCODE(ip) @ extract opcode from rINST 1125 GOTO_OPCODE(ip) @ jump to next instruction 1126#else 1127 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1128 GET_INST_OPCODE(ip) @ extract opcode from rINST 1129 GOTO_OPCODE(ip) @ jump to next instruction 1130#endif 1131 1132/* ------------------------------ */ 1133 .balign 64 1134.L_OP_GOTO_16: /* 0x29 */ 1135/* File: armv5te/OP_GOTO_16.S */ 1136 /* 1137 * Unconditional branch, 16-bit offset. 1138 * 1139 * The branch distance is a signed code-unit offset, which we need to 1140 * double to get a byte offset. 1141 */ 1142 /* goto/16 +AAAA */ 1143 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1144 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1145 bmi common_backwardBranch @ backward branch, do periodic checks 1146#if defined(WITH_JIT) 1147 GET_JIT_PROF_TABLE(r0) 1148 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1149 cmp r0,#0 1150 bne common_updateProfile 1151 GET_INST_OPCODE(ip) @ extract opcode from rINST 1152 GOTO_OPCODE(ip) @ jump to next instruction 1153#else 1154 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1155 GET_INST_OPCODE(ip) @ extract opcode from rINST 1156 GOTO_OPCODE(ip) @ jump to next instruction 1157#endif 1158 1159/* ------------------------------ */ 1160 .balign 64 1161.L_OP_GOTO_32: /* 0x2a */ 1162/* File: armv5te/OP_GOTO_32.S */ 1163 /* 1164 * Unconditional branch, 32-bit offset. 1165 * 1166 * The branch distance is a signed code-unit offset, which we need to 1167 * double to get a byte offset. 1168 * 1169 * Unlike most opcodes, this one is allowed to branch to itself, so 1170 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1171 * instruction doesn't affect the V flag, so we need to clear it 1172 * explicitly. 1173 */ 1174 /* goto/32 +AAAAAAAA */ 1175 FETCH(r0, 1) @ r0<- aaaa (lo) 1176 FETCH(r1, 2) @ r1<- AAAA (hi) 1177 cmp ip, ip @ (clear V flag during stall) 1178 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1179 mov r9, r0, asl #1 @ r9<- byte offset 1180 ble common_backwardBranch @ backward branch, do periodic checks 1181#if defined(WITH_JIT) 1182 GET_JIT_PROF_TABLE(r0) 1183 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1184 cmp r0,#0 1185 bne common_updateProfile 1186 GET_INST_OPCODE(ip) @ extract opcode from rINST 1187 GOTO_OPCODE(ip) @ jump to next instruction 1188#else 1189 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1190 GET_INST_OPCODE(ip) @ extract opcode from rINST 1191 GOTO_OPCODE(ip) @ jump to next instruction 1192#endif 1193 1194/* ------------------------------ */ 1195 .balign 64 1196.L_OP_PACKED_SWITCH: /* 0x2b */ 1197/* File: armv5te/OP_PACKED_SWITCH.S */ 1198 /* 1199 * Handle a packed-switch or sparse-switch instruction. In both cases 1200 * we decode it and hand it off to a helper function. 1201 * 1202 * We don't really expect backward branches in a switch statement, but 1203 * they're perfectly legal, so we check for them here. 1204 * 1205 * for: packed-switch, sparse-switch 1206 */ 1207 /* op vAA, +BBBB */ 1208 FETCH(r0, 1) @ r0<- bbbb (lo) 1209 FETCH(r1, 2) @ r1<- BBBB (hi) 1210 mov r3, rINST, lsr #8 @ r3<- AA 1211 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1212 GET_VREG(r1, r3) @ r1<- vAA 1213 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1214 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1215 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1216 bmi common_backwardBranch @ backward branch, do periodic checks 1217 beq common_backwardBranch @ (want to use BLE but V is unknown) 1218#if defined(WITH_JIT) 1219 GET_JIT_PROF_TABLE(r0) 1220 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1221 cmp r0,#0 1222 bne common_updateProfile 1223 GET_INST_OPCODE(ip) @ extract opcode from rINST 1224 GOTO_OPCODE(ip) @ jump to next instruction 1225#else 1226 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1227 GET_INST_OPCODE(ip) @ extract opcode from rINST 1228 GOTO_OPCODE(ip) @ jump to next instruction 1229#endif 1230 1231/* ------------------------------ */ 1232 .balign 64 1233.L_OP_SPARSE_SWITCH: /* 0x2c */ 1234/* File: armv5te/OP_SPARSE_SWITCH.S */ 1235/* File: armv5te/OP_PACKED_SWITCH.S */ 1236 /* 1237 * Handle a packed-switch or sparse-switch instruction. In both cases 1238 * we decode it and hand it off to a helper function. 1239 * 1240 * We don't really expect backward branches in a switch statement, but 1241 * they're perfectly legal, so we check for them here. 1242 * 1243 * for: packed-switch, sparse-switch 1244 */ 1245 /* op vAA, +BBBB */ 1246 FETCH(r0, 1) @ r0<- bbbb (lo) 1247 FETCH(r1, 2) @ r1<- BBBB (hi) 1248 mov r3, rINST, lsr #8 @ r3<- AA 1249 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1250 GET_VREG(r1, r3) @ r1<- vAA 1251 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1252 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1253 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1254 bmi common_backwardBranch @ backward branch, do periodic checks 1255 beq common_backwardBranch @ (want to use BLE but V is unknown) 1256#if defined(WITH_JIT) 1257 GET_JIT_PROF_TABLE(r0) 1258 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1259 cmp r0,#0 1260 bne common_updateProfile 1261 GET_INST_OPCODE(ip) @ extract opcode from rINST 1262 GOTO_OPCODE(ip) @ jump to next instruction 1263#else 1264 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1265 GET_INST_OPCODE(ip) @ extract opcode from rINST 1266 GOTO_OPCODE(ip) @ jump to next instruction 1267#endif 1268 1269 1270/* ------------------------------ */ 1271 .balign 64 1272.L_OP_CMPL_FLOAT: /* 0x2d */ 1273/* File: arm-vfp/OP_CMPL_FLOAT.S */ 1274 /* 1275 * Compare two floating-point values. Puts 0, 1, or -1 into the 1276 * destination register based on the results of the comparison. 1277 * 1278 * int compare(x, y) { 1279 * if (x == y) { 1280 * return 0; 1281 * } else if (x > y) { 1282 * return 1; 1283 * } else if (x < y) { 1284 * return -1; 1285 * } else { 1286 * return -1; 1287 * } 1288 * } 1289 */ 1290 /* op vAA, vBB, vCC */ 1291 FETCH(r0, 1) @ r0<- CCBB 1292 mov r9, rINST, lsr #8 @ r9<- AA 1293 and r2, r0, #255 @ r2<- BB 1294 mov r3, r0, lsr #8 @ r3<- CC 1295 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1296 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1297 flds s0, [r2] @ s0<- vBB 1298 flds s1, [r3] @ s1<- vCC 1299 fcmpes s0, s1 @ compare (vBB, vCC) 1300 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1301 mvn r0, #0 @ r0<- -1 (default) 1302 GET_INST_OPCODE(ip) @ extract opcode from rINST 1303 fmstat @ export status flags 1304 movgt r0, #1 @ (greater than) r1<- 1 1305 moveq r0, #0 @ (equal) r1<- 0 1306 b .LOP_CMPL_FLOAT_finish @ argh 1307 1308 1309/* ------------------------------ */ 1310 .balign 64 1311.L_OP_CMPG_FLOAT: /* 0x2e */ 1312/* File: arm-vfp/OP_CMPG_FLOAT.S */ 1313 /* 1314 * Compare two floating-point values. Puts 0, 1, or -1 into the 1315 * destination register based on the results of the comparison. 1316 * 1317 * int compare(x, y) { 1318 * if (x == y) { 1319 * return 0; 1320 * } else if (x < y) { 1321 * return -1; 1322 * } else if (x > y) { 1323 * return 1; 1324 * } else { 1325 * return 1; 1326 * } 1327 * } 1328 */ 1329 /* op vAA, vBB, vCC */ 1330 FETCH(r0, 1) @ r0<- CCBB 1331 mov r9, rINST, lsr #8 @ r9<- AA 1332 and r2, r0, #255 @ r2<- BB 1333 mov r3, r0, lsr #8 @ r3<- CC 1334 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1335 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1336 flds s0, [r2] @ s0<- vBB 1337 flds s1, [r3] @ s1<- vCC 1338 fcmpes s0, s1 @ compare (vBB, vCC) 1339 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1340 mov r0, #1 @ r0<- 1 (default) 1341 GET_INST_OPCODE(ip) @ extract opcode from rINST 1342 fmstat @ export status flags 1343 mvnmi r0, #0 @ (less than) r1<- -1 1344 moveq r0, #0 @ (equal) r1<- 0 1345 b .LOP_CMPG_FLOAT_finish @ argh 1346 1347 1348/* ------------------------------ */ 1349 .balign 64 1350.L_OP_CMPL_DOUBLE: /* 0x2f */ 1351/* File: arm-vfp/OP_CMPL_DOUBLE.S */ 1352 /* 1353 * Compare two floating-point values. Puts 0, 1, or -1 into the 1354 * destination register based on the results of the comparison. 1355 * 1356 * int compare(x, y) { 1357 * if (x == y) { 1358 * return 0; 1359 * } else if (x > y) { 1360 * return 1; 1361 * } else if (x < y) { 1362 * return -1; 1363 * } else { 1364 * return -1; 1365 * } 1366 * } 1367 */ 1368 /* op vAA, vBB, vCC */ 1369 FETCH(r0, 1) @ r0<- CCBB 1370 mov r9, rINST, lsr #8 @ r9<- AA 1371 and r2, r0, #255 @ r2<- BB 1372 mov r3, r0, lsr #8 @ r3<- CC 1373 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1374 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1375 fldd d0, [r2] @ d0<- vBB 1376 fldd d1, [r3] @ d1<- vCC 1377 fcmped d0, d1 @ compare (vBB, vCC) 1378 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1379 mvn r0, #0 @ r0<- -1 (default) 1380 GET_INST_OPCODE(ip) @ extract opcode from rINST 1381 fmstat @ export status flags 1382 movgt r0, #1 @ (greater than) r1<- 1 1383 moveq r0, #0 @ (equal) r1<- 0 1384 b .LOP_CMPL_DOUBLE_finish @ argh 1385 1386 1387/* ------------------------------ */ 1388 .balign 64 1389.L_OP_CMPG_DOUBLE: /* 0x30 */ 1390/* File: arm-vfp/OP_CMPG_DOUBLE.S */ 1391 /* 1392 * Compare two floating-point values. Puts 0, 1, or -1 into the 1393 * destination register based on the results of the comparison. 1394 * 1395 * int compare(x, y) { 1396 * if (x == y) { 1397 * return 0; 1398 * } else if (x < y) { 1399 * return -1; 1400 * } else if (x > y) { 1401 * return 1; 1402 * } else { 1403 * return 1; 1404 * } 1405 * } 1406 */ 1407 /* op vAA, vBB, vCC */ 1408 FETCH(r0, 1) @ r0<- CCBB 1409 mov r9, rINST, lsr #8 @ r9<- AA 1410 and r2, r0, #255 @ r2<- BB 1411 mov r3, r0, lsr #8 @ r3<- CC 1412 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1413 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1414 fldd d0, [r2] @ d0<- vBB 1415 fldd d1, [r3] @ d1<- vCC 1416 fcmped d0, d1 @ compare (vBB, vCC) 1417 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1418 mov r0, #1 @ r0<- 1 (default) 1419 GET_INST_OPCODE(ip) @ extract opcode from rINST 1420 fmstat @ export status flags 1421 mvnmi r0, #0 @ (less than) r1<- -1 1422 moveq r0, #0 @ (equal) r1<- 0 1423 b .LOP_CMPG_DOUBLE_finish @ argh 1424 1425 1426/* ------------------------------ */ 1427 .balign 64 1428.L_OP_CMP_LONG: /* 0x31 */ 1429/* File: armv5te/OP_CMP_LONG.S */ 1430 /* 1431 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1432 * register based on the results of the comparison. 1433 * 1434 * We load the full values with LDM, but in practice many values could 1435 * be resolved by only looking at the high word. This could be made 1436 * faster or slower by splitting the LDM into a pair of LDRs. 1437 * 1438 * If we just wanted to set condition flags, we could do this: 1439 * subs ip, r0, r2 1440 * sbcs ip, r1, r3 1441 * subeqs ip, r0, r2 1442 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1443 * integer value, which we can do with 2 conditional mov/mvn instructions 1444 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1445 * us a constant 5-cycle path plus a branch at the end to the 1446 * instruction epilogue code. The multi-compare approach below needs 1447 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1448 * in the worst case (the 64-bit values are equal). 1449 */ 1450 /* cmp-long vAA, vBB, vCC */ 1451 FETCH(r0, 1) @ r0<- CCBB 1452 mov r9, rINST, lsr #8 @ r9<- AA 1453 and r2, r0, #255 @ r2<- BB 1454 mov r3, r0, lsr #8 @ r3<- CC 1455 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1456 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1457 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1458 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1459 cmp r1, r3 @ compare (vBB+1, vCC+1) 1460 blt .LOP_CMP_LONG_less @ signed compare on high part 1461 bgt .LOP_CMP_LONG_greater 1462 subs r1, r0, r2 @ r1<- r0 - r2 1463 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1464 bne .LOP_CMP_LONG_less 1465 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1466 1467/* ------------------------------ */ 1468 .balign 64 1469.L_OP_IF_EQ: /* 0x32 */ 1470/* File: armv5te/OP_IF_EQ.S */ 1471/* File: armv5te/bincmp.S */ 1472 /* 1473 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1474 * fragment that specifies the *reverse* comparison to perform, e.g. 1475 * for "if-le" you would use "gt". 1476 * 1477 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1478 */ 1479 /* if-cmp vA, vB, +CCCC */ 1480 mov r0, rINST, lsr #8 @ r0<- A+ 1481 mov r1, rINST, lsr #12 @ r1<- B 1482 and r0, r0, #15 1483 GET_VREG(r3, r1) @ r3<- vB 1484 GET_VREG(r2, r0) @ r2<- vA 1485 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1486 cmp r2, r3 @ compare (vA, vB) 1487 bne 1f @ branch to 1 if comparison failed 1488 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1489 movs r9, r9, asl #1 @ convert to bytes, check sign 1490 bmi common_backwardBranch @ yes, do periodic checks 14911: 1492#if defined(WITH_JIT) 1493 GET_JIT_PROF_TABLE(r0) 1494 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1495 b common_testUpdateProfile 1496#else 1497 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1498 GET_INST_OPCODE(ip) @ extract opcode from rINST 1499 GOTO_OPCODE(ip) @ jump to next instruction 1500#endif 1501 1502 1503/* ------------------------------ */ 1504 .balign 64 1505.L_OP_IF_NE: /* 0x33 */ 1506/* File: armv5te/OP_IF_NE.S */ 1507/* File: armv5te/bincmp.S */ 1508 /* 1509 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1510 * fragment that specifies the *reverse* comparison to perform, e.g. 1511 * for "if-le" you would use "gt". 1512 * 1513 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1514 */ 1515 /* if-cmp vA, vB, +CCCC */ 1516 mov r0, rINST, lsr #8 @ r0<- A+ 1517 mov r1, rINST, lsr #12 @ r1<- B 1518 and r0, r0, #15 1519 GET_VREG(r3, r1) @ r3<- vB 1520 GET_VREG(r2, r0) @ r2<- vA 1521 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1522 cmp r2, r3 @ compare (vA, vB) 1523 beq 1f @ branch to 1 if comparison failed 1524 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1525 movs r9, r9, asl #1 @ convert to bytes, check sign 1526 bmi common_backwardBranch @ yes, do periodic checks 15271: 1528#if defined(WITH_JIT) 1529 GET_JIT_PROF_TABLE(r0) 1530 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1531 b common_testUpdateProfile 1532#else 1533 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1534 GET_INST_OPCODE(ip) @ extract opcode from rINST 1535 GOTO_OPCODE(ip) @ jump to next instruction 1536#endif 1537 1538 1539/* ------------------------------ */ 1540 .balign 64 1541.L_OP_IF_LT: /* 0x34 */ 1542/* File: armv5te/OP_IF_LT.S */ 1543/* File: armv5te/bincmp.S */ 1544 /* 1545 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1546 * fragment that specifies the *reverse* comparison to perform, e.g. 1547 * for "if-le" you would use "gt". 1548 * 1549 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1550 */ 1551 /* if-cmp vA, vB, +CCCC */ 1552 mov r0, rINST, lsr #8 @ r0<- A+ 1553 mov r1, rINST, lsr #12 @ r1<- B 1554 and r0, r0, #15 1555 GET_VREG(r3, r1) @ r3<- vB 1556 GET_VREG(r2, r0) @ r2<- vA 1557 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1558 cmp r2, r3 @ compare (vA, vB) 1559 bge 1f @ branch to 1 if comparison failed 1560 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1561 movs r9, r9, asl #1 @ convert to bytes, check sign 1562 bmi common_backwardBranch @ yes, do periodic checks 15631: 1564#if defined(WITH_JIT) 1565 GET_JIT_PROF_TABLE(r0) 1566 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1567 b common_testUpdateProfile 1568#else 1569 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1570 GET_INST_OPCODE(ip) @ extract opcode from rINST 1571 GOTO_OPCODE(ip) @ jump to next instruction 1572#endif 1573 1574 1575/* ------------------------------ */ 1576 .balign 64 1577.L_OP_IF_GE: /* 0x35 */ 1578/* File: armv5te/OP_IF_GE.S */ 1579/* File: armv5te/bincmp.S */ 1580 /* 1581 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1582 * fragment that specifies the *reverse* comparison to perform, e.g. 1583 * for "if-le" you would use "gt". 1584 * 1585 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1586 */ 1587 /* if-cmp vA, vB, +CCCC */ 1588 mov r0, rINST, lsr #8 @ r0<- A+ 1589 mov r1, rINST, lsr #12 @ r1<- B 1590 and r0, r0, #15 1591 GET_VREG(r3, r1) @ r3<- vB 1592 GET_VREG(r2, r0) @ r2<- vA 1593 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1594 cmp r2, r3 @ compare (vA, vB) 1595 blt 1f @ branch to 1 if comparison failed 1596 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1597 movs r9, r9, asl #1 @ convert to bytes, check sign 1598 bmi common_backwardBranch @ yes, do periodic checks 15991: 1600#if defined(WITH_JIT) 1601 GET_JIT_PROF_TABLE(r0) 1602 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1603 b common_testUpdateProfile 1604#else 1605 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1606 GET_INST_OPCODE(ip) @ extract opcode from rINST 1607 GOTO_OPCODE(ip) @ jump to next instruction 1608#endif 1609 1610 1611/* ------------------------------ */ 1612 .balign 64 1613.L_OP_IF_GT: /* 0x36 */ 1614/* File: armv5te/OP_IF_GT.S */ 1615/* File: armv5te/bincmp.S */ 1616 /* 1617 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1618 * fragment that specifies the *reverse* comparison to perform, e.g. 1619 * for "if-le" you would use "gt". 1620 * 1621 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1622 */ 1623 /* if-cmp vA, vB, +CCCC */ 1624 mov r0, rINST, lsr #8 @ r0<- A+ 1625 mov r1, rINST, lsr #12 @ r1<- B 1626 and r0, r0, #15 1627 GET_VREG(r3, r1) @ r3<- vB 1628 GET_VREG(r2, r0) @ r2<- vA 1629 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1630 cmp r2, r3 @ compare (vA, vB) 1631 ble 1f @ branch to 1 if comparison failed 1632 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1633 movs r9, r9, asl #1 @ convert to bytes, check sign 1634 bmi common_backwardBranch @ yes, do periodic checks 16351: 1636#if defined(WITH_JIT) 1637 GET_JIT_PROF_TABLE(r0) 1638 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1639 b common_testUpdateProfile 1640#else 1641 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1642 GET_INST_OPCODE(ip) @ extract opcode from rINST 1643 GOTO_OPCODE(ip) @ jump to next instruction 1644#endif 1645 1646 1647/* ------------------------------ */ 1648 .balign 64 1649.L_OP_IF_LE: /* 0x37 */ 1650/* File: armv5te/OP_IF_LE.S */ 1651/* File: armv5te/bincmp.S */ 1652 /* 1653 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1654 * fragment that specifies the *reverse* comparison to perform, e.g. 1655 * for "if-le" you would use "gt". 1656 * 1657 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1658 */ 1659 /* if-cmp vA, vB, +CCCC */ 1660 mov r0, rINST, lsr #8 @ r0<- A+ 1661 mov r1, rINST, lsr #12 @ r1<- B 1662 and r0, r0, #15 1663 GET_VREG(r3, r1) @ r3<- vB 1664 GET_VREG(r2, r0) @ r2<- vA 1665 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1666 cmp r2, r3 @ compare (vA, vB) 1667 bgt 1f @ branch to 1 if comparison failed 1668 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1669 movs r9, r9, asl #1 @ convert to bytes, check sign 1670 bmi common_backwardBranch @ yes, do periodic checks 16711: 1672#if defined(WITH_JIT) 1673 GET_JIT_PROF_TABLE(r0) 1674 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1675 b common_testUpdateProfile 1676#else 1677 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1678 GET_INST_OPCODE(ip) @ extract opcode from rINST 1679 GOTO_OPCODE(ip) @ jump to next instruction 1680#endif 1681 1682 1683/* ------------------------------ */ 1684 .balign 64 1685.L_OP_IF_EQZ: /* 0x38 */ 1686/* File: armv5te/OP_IF_EQZ.S */ 1687/* File: armv5te/zcmp.S */ 1688 /* 1689 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1690 * fragment that specifies the *reverse* comparison to perform, e.g. 1691 * for "if-le" you would use "gt". 1692 * 1693 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1694 */ 1695 /* if-cmp vAA, +BBBB */ 1696 mov r0, rINST, lsr #8 @ r0<- AA 1697 GET_VREG(r2, r0) @ r2<- vAA 1698 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1699 cmp r2, #0 @ compare (vA, 0) 1700 bne 1f @ branch to 1 if comparison failed 1701 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1702 movs r9, r9, asl #1 @ convert to bytes, check sign 1703 bmi common_backwardBranch @ backward branch, do periodic checks 17041: 1705#if defined(WITH_JIT) 1706 GET_JIT_PROF_TABLE(r0) 1707 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1708 cmp r0,#0 1709 bne common_updateProfile 1710 GET_INST_OPCODE(ip) @ extract opcode from rINST 1711 GOTO_OPCODE(ip) @ jump to next instruction 1712#else 1713 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1714 GET_INST_OPCODE(ip) @ extract opcode from rINST 1715 GOTO_OPCODE(ip) @ jump to next instruction 1716#endif 1717 1718 1719/* ------------------------------ */ 1720 .balign 64 1721.L_OP_IF_NEZ: /* 0x39 */ 1722/* File: armv5te/OP_IF_NEZ.S */ 1723/* File: armv5te/zcmp.S */ 1724 /* 1725 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1726 * fragment that specifies the *reverse* comparison to perform, e.g. 1727 * for "if-le" you would use "gt". 1728 * 1729 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1730 */ 1731 /* if-cmp vAA, +BBBB */ 1732 mov r0, rINST, lsr #8 @ r0<- AA 1733 GET_VREG(r2, r0) @ r2<- vAA 1734 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1735 cmp r2, #0 @ compare (vA, 0) 1736 beq 1f @ branch to 1 if comparison failed 1737 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1738 movs r9, r9, asl #1 @ convert to bytes, check sign 1739 bmi common_backwardBranch @ backward branch, do periodic checks 17401: 1741#if defined(WITH_JIT) 1742 GET_JIT_PROF_TABLE(r0) 1743 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1744 cmp r0,#0 1745 bne common_updateProfile 1746 GET_INST_OPCODE(ip) @ extract opcode from rINST 1747 GOTO_OPCODE(ip) @ jump to next instruction 1748#else 1749 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1750 GET_INST_OPCODE(ip) @ extract opcode from rINST 1751 GOTO_OPCODE(ip) @ jump to next instruction 1752#endif 1753 1754 1755/* ------------------------------ */ 1756 .balign 64 1757.L_OP_IF_LTZ: /* 0x3a */ 1758/* File: armv5te/OP_IF_LTZ.S */ 1759/* File: armv5te/zcmp.S */ 1760 /* 1761 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1762 * fragment that specifies the *reverse* comparison to perform, e.g. 1763 * for "if-le" you would use "gt". 1764 * 1765 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1766 */ 1767 /* if-cmp vAA, +BBBB */ 1768 mov r0, rINST, lsr #8 @ r0<- AA 1769 GET_VREG(r2, r0) @ r2<- vAA 1770 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1771 cmp r2, #0 @ compare (vA, 0) 1772 bge 1f @ branch to 1 if comparison failed 1773 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1774 movs r9, r9, asl #1 @ convert to bytes, check sign 1775 bmi common_backwardBranch @ backward branch, do periodic checks 17761: 1777#if defined(WITH_JIT) 1778 GET_JIT_PROF_TABLE(r0) 1779 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1780 cmp r0,#0 1781 bne common_updateProfile 1782 GET_INST_OPCODE(ip) @ extract opcode from rINST 1783 GOTO_OPCODE(ip) @ jump to next instruction 1784#else 1785 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1786 GET_INST_OPCODE(ip) @ extract opcode from rINST 1787 GOTO_OPCODE(ip) @ jump to next instruction 1788#endif 1789 1790 1791/* ------------------------------ */ 1792 .balign 64 1793.L_OP_IF_GEZ: /* 0x3b */ 1794/* File: armv5te/OP_IF_GEZ.S */ 1795/* File: armv5te/zcmp.S */ 1796 /* 1797 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1798 * fragment that specifies the *reverse* comparison to perform, e.g. 1799 * for "if-le" you would use "gt". 1800 * 1801 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1802 */ 1803 /* if-cmp vAA, +BBBB */ 1804 mov r0, rINST, lsr #8 @ r0<- AA 1805 GET_VREG(r2, r0) @ r2<- vAA 1806 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1807 cmp r2, #0 @ compare (vA, 0) 1808 blt 1f @ branch to 1 if comparison failed 1809 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1810 movs r9, r9, asl #1 @ convert to bytes, check sign 1811 bmi common_backwardBranch @ backward branch, do periodic checks 18121: 1813#if defined(WITH_JIT) 1814 GET_JIT_PROF_TABLE(r0) 1815 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1816 cmp r0,#0 1817 bne common_updateProfile 1818 GET_INST_OPCODE(ip) @ extract opcode from rINST 1819 GOTO_OPCODE(ip) @ jump to next instruction 1820#else 1821 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1822 GET_INST_OPCODE(ip) @ extract opcode from rINST 1823 GOTO_OPCODE(ip) @ jump to next instruction 1824#endif 1825 1826 1827/* ------------------------------ */ 1828 .balign 64 1829.L_OP_IF_GTZ: /* 0x3c */ 1830/* File: armv5te/OP_IF_GTZ.S */ 1831/* File: armv5te/zcmp.S */ 1832 /* 1833 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1834 * fragment that specifies the *reverse* comparison to perform, e.g. 1835 * for "if-le" you would use "gt". 1836 * 1837 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1838 */ 1839 /* if-cmp vAA, +BBBB */ 1840 mov r0, rINST, lsr #8 @ r0<- AA 1841 GET_VREG(r2, r0) @ r2<- vAA 1842 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1843 cmp r2, #0 @ compare (vA, 0) 1844 ble 1f @ branch to 1 if comparison failed 1845 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1846 movs r9, r9, asl #1 @ convert to bytes, check sign 1847 bmi common_backwardBranch @ backward branch, do periodic checks 18481: 1849#if defined(WITH_JIT) 1850 GET_JIT_PROF_TABLE(r0) 1851 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1852 cmp r0,#0 1853 bne common_updateProfile 1854 GET_INST_OPCODE(ip) @ extract opcode from rINST 1855 GOTO_OPCODE(ip) @ jump to next instruction 1856#else 1857 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1858 GET_INST_OPCODE(ip) @ extract opcode from rINST 1859 GOTO_OPCODE(ip) @ jump to next instruction 1860#endif 1861 1862 1863/* ------------------------------ */ 1864 .balign 64 1865.L_OP_IF_LEZ: /* 0x3d */ 1866/* File: armv5te/OP_IF_LEZ.S */ 1867/* File: armv5te/zcmp.S */ 1868 /* 1869 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1870 * fragment that specifies the *reverse* comparison to perform, e.g. 1871 * for "if-le" you would use "gt". 1872 * 1873 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1874 */ 1875 /* if-cmp vAA, +BBBB */ 1876 mov r0, rINST, lsr #8 @ r0<- AA 1877 GET_VREG(r2, r0) @ r2<- vAA 1878 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1879 cmp r2, #0 @ compare (vA, 0) 1880 bgt 1f @ branch to 1 if comparison failed 1881 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1882 movs r9, r9, asl #1 @ convert to bytes, check sign 1883 bmi common_backwardBranch @ backward branch, do periodic checks 18841: 1885#if defined(WITH_JIT) 1886 GET_JIT_PROF_TABLE(r0) 1887 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1888 cmp r0,#0 1889 bne common_updateProfile 1890 GET_INST_OPCODE(ip) @ extract opcode from rINST 1891 GOTO_OPCODE(ip) @ jump to next instruction 1892#else 1893 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1894 GET_INST_OPCODE(ip) @ extract opcode from rINST 1895 GOTO_OPCODE(ip) @ jump to next instruction 1896#endif 1897 1898 1899/* ------------------------------ */ 1900 .balign 64 1901.L_OP_UNUSED_3E: /* 0x3e */ 1902/* File: armv5te/OP_UNUSED_3E.S */ 1903/* File: armv5te/unused.S */ 1904 bl common_abort 1905 1906 1907/* ------------------------------ */ 1908 .balign 64 1909.L_OP_UNUSED_3F: /* 0x3f */ 1910/* File: armv5te/OP_UNUSED_3F.S */ 1911/* File: armv5te/unused.S */ 1912 bl common_abort 1913 1914 1915/* ------------------------------ */ 1916 .balign 64 1917.L_OP_UNUSED_40: /* 0x40 */ 1918/* File: armv5te/OP_UNUSED_40.S */ 1919/* File: armv5te/unused.S */ 1920 bl common_abort 1921 1922 1923/* ------------------------------ */ 1924 .balign 64 1925.L_OP_UNUSED_41: /* 0x41 */ 1926/* File: armv5te/OP_UNUSED_41.S */ 1927/* File: armv5te/unused.S */ 1928 bl common_abort 1929 1930 1931/* ------------------------------ */ 1932 .balign 64 1933.L_OP_UNUSED_42: /* 0x42 */ 1934/* File: armv5te/OP_UNUSED_42.S */ 1935/* File: armv5te/unused.S */ 1936 bl common_abort 1937 1938 1939/* ------------------------------ */ 1940 .balign 64 1941.L_OP_UNUSED_43: /* 0x43 */ 1942/* File: armv5te/OP_UNUSED_43.S */ 1943/* File: armv5te/unused.S */ 1944 bl common_abort 1945 1946 1947/* ------------------------------ */ 1948 .balign 64 1949.L_OP_AGET: /* 0x44 */ 1950/* File: armv5te/OP_AGET.S */ 1951 /* 1952 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1953 * 1954 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1955 * instructions. We use a pair of FETCH_Bs instead. 1956 * 1957 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1958 */ 1959 /* op vAA, vBB, vCC */ 1960 FETCH_B(r2, 1, 0) @ r2<- BB 1961 mov r9, rINST, lsr #8 @ r9<- AA 1962 FETCH_B(r3, 1, 1) @ r3<- CC 1963 GET_VREG(r0, r2) @ r0<- vBB (array object) 1964 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1965 cmp r0, #0 @ null array object? 1966 beq common_errNullObject @ yes, bail 1967 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1968 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 1969 cmp r1, r3 @ compare unsigned index, length 1970 bcs common_errArrayIndex @ index >= length, bail 1971 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1972 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 1973 GET_INST_OPCODE(ip) @ extract opcode from rINST 1974 SET_VREG(r2, r9) @ vAA<- r2 1975 GOTO_OPCODE(ip) @ jump to next instruction 1976 1977/* ------------------------------ */ 1978 .balign 64 1979.L_OP_AGET_WIDE: /* 0x45 */ 1980/* File: armv5te/OP_AGET_WIDE.S */ 1981 /* 1982 * Array get, 64 bits. vAA <- vBB[vCC]. 1983 * 1984 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 1985 */ 1986 /* aget-wide vAA, vBB, vCC */ 1987 FETCH(r0, 1) @ r0<- CCBB 1988 mov r9, rINST, lsr #8 @ r9<- AA 1989 and r2, r0, #255 @ r2<- BB 1990 mov r3, r0, lsr #8 @ r3<- CC 1991 GET_VREG(r0, r2) @ r0<- vBB (array object) 1992 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1993 cmp r0, #0 @ null array object? 1994 beq common_errNullObject @ yes, bail 1995 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1996 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 1997 cmp r1, r3 @ compare unsigned index, length 1998 bcc .LOP_AGET_WIDE_finish @ okay, continue below 1999 b common_errArrayIndex @ index >= length, bail 2000 @ May want to swap the order of these two branches depending on how the 2001 @ branch prediction (if any) handles conditional forward branches vs. 2002 @ unconditional forward branches. 2003 2004/* ------------------------------ */ 2005 .balign 64 2006.L_OP_AGET_OBJECT: /* 0x46 */ 2007/* File: armv5te/OP_AGET_OBJECT.S */ 2008/* File: armv5te/OP_AGET.S */ 2009 /* 2010 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2011 * 2012 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2013 * instructions. We use a pair of FETCH_Bs instead. 2014 * 2015 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2016 */ 2017 /* op vAA, vBB, vCC */ 2018 FETCH_B(r2, 1, 0) @ r2<- BB 2019 mov r9, rINST, lsr #8 @ r9<- AA 2020 FETCH_B(r3, 1, 1) @ r3<- CC 2021 GET_VREG(r0, r2) @ r0<- vBB (array object) 2022 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2023 cmp r0, #0 @ null array object? 2024 beq common_errNullObject @ yes, bail 2025 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2026 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2027 cmp r1, r3 @ compare unsigned index, length 2028 bcs common_errArrayIndex @ index >= length, bail 2029 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2030 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2031 GET_INST_OPCODE(ip) @ extract opcode from rINST 2032 SET_VREG(r2, r9) @ vAA<- r2 2033 GOTO_OPCODE(ip) @ jump to next instruction 2034 2035 2036/* ------------------------------ */ 2037 .balign 64 2038.L_OP_AGET_BOOLEAN: /* 0x47 */ 2039/* File: armv5te/OP_AGET_BOOLEAN.S */ 2040/* File: armv5te/OP_AGET.S */ 2041 /* 2042 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2043 * 2044 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2045 * instructions. We use a pair of FETCH_Bs instead. 2046 * 2047 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2048 */ 2049 /* op vAA, vBB, vCC */ 2050 FETCH_B(r2, 1, 0) @ r2<- BB 2051 mov r9, rINST, lsr #8 @ r9<- AA 2052 FETCH_B(r3, 1, 1) @ r3<- CC 2053 GET_VREG(r0, r2) @ r0<- vBB (array object) 2054 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2055 cmp r0, #0 @ null array object? 2056 beq common_errNullObject @ yes, bail 2057 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2058 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2059 cmp r1, r3 @ compare unsigned index, length 2060 bcs common_errArrayIndex @ index >= length, bail 2061 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2062 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2063 GET_INST_OPCODE(ip) @ extract opcode from rINST 2064 SET_VREG(r2, r9) @ vAA<- r2 2065 GOTO_OPCODE(ip) @ jump to next instruction 2066 2067 2068/* ------------------------------ */ 2069 .balign 64 2070.L_OP_AGET_BYTE: /* 0x48 */ 2071/* File: armv5te/OP_AGET_BYTE.S */ 2072/* File: armv5te/OP_AGET.S */ 2073 /* 2074 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2075 * 2076 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2077 * instructions. We use a pair of FETCH_Bs instead. 2078 * 2079 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2080 */ 2081 /* op vAA, vBB, vCC */ 2082 FETCH_B(r2, 1, 0) @ r2<- BB 2083 mov r9, rINST, lsr #8 @ r9<- AA 2084 FETCH_B(r3, 1, 1) @ r3<- CC 2085 GET_VREG(r0, r2) @ r0<- vBB (array object) 2086 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2087 cmp r0, #0 @ null array object? 2088 beq common_errNullObject @ yes, bail 2089 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2090 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2091 cmp r1, r3 @ compare unsigned index, length 2092 bcs common_errArrayIndex @ index >= length, bail 2093 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2094 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2095 GET_INST_OPCODE(ip) @ extract opcode from rINST 2096 SET_VREG(r2, r9) @ vAA<- r2 2097 GOTO_OPCODE(ip) @ jump to next instruction 2098 2099 2100/* ------------------------------ */ 2101 .balign 64 2102.L_OP_AGET_CHAR: /* 0x49 */ 2103/* File: armv5te/OP_AGET_CHAR.S */ 2104/* File: armv5te/OP_AGET.S */ 2105 /* 2106 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2107 * 2108 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2109 * instructions. We use a pair of FETCH_Bs instead. 2110 * 2111 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2112 */ 2113 /* op vAA, vBB, vCC */ 2114 FETCH_B(r2, 1, 0) @ r2<- BB 2115 mov r9, rINST, lsr #8 @ r9<- AA 2116 FETCH_B(r3, 1, 1) @ r3<- CC 2117 GET_VREG(r0, r2) @ r0<- vBB (array object) 2118 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2119 cmp r0, #0 @ null array object? 2120 beq common_errNullObject @ yes, bail 2121 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2122 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2123 cmp r1, r3 @ compare unsigned index, length 2124 bcs common_errArrayIndex @ index >= length, bail 2125 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2126 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2127 GET_INST_OPCODE(ip) @ extract opcode from rINST 2128 SET_VREG(r2, r9) @ vAA<- r2 2129 GOTO_OPCODE(ip) @ jump to next instruction 2130 2131 2132/* ------------------------------ */ 2133 .balign 64 2134.L_OP_AGET_SHORT: /* 0x4a */ 2135/* File: armv5te/OP_AGET_SHORT.S */ 2136/* File: armv5te/OP_AGET.S */ 2137 /* 2138 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2139 * 2140 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2141 * instructions. We use a pair of FETCH_Bs instead. 2142 * 2143 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2144 */ 2145 /* op vAA, vBB, vCC */ 2146 FETCH_B(r2, 1, 0) @ r2<- BB 2147 mov r9, rINST, lsr #8 @ r9<- AA 2148 FETCH_B(r3, 1, 1) @ r3<- CC 2149 GET_VREG(r0, r2) @ r0<- vBB (array object) 2150 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2151 cmp r0, #0 @ null array object? 2152 beq common_errNullObject @ yes, bail 2153 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2154 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2155 cmp r1, r3 @ compare unsigned index, length 2156 bcs common_errArrayIndex @ index >= length, bail 2157 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2158 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2159 GET_INST_OPCODE(ip) @ extract opcode from rINST 2160 SET_VREG(r2, r9) @ vAA<- r2 2161 GOTO_OPCODE(ip) @ jump to next instruction 2162 2163 2164/* ------------------------------ */ 2165 .balign 64 2166.L_OP_APUT: /* 0x4b */ 2167/* File: armv5te/OP_APUT.S */ 2168 /* 2169 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2170 * 2171 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2172 * instructions. We use a pair of FETCH_Bs instead. 2173 * 2174 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2175 */ 2176 /* op vAA, vBB, vCC */ 2177 FETCH_B(r2, 1, 0) @ r2<- BB 2178 mov r9, rINST, lsr #8 @ r9<- AA 2179 FETCH_B(r3, 1, 1) @ r3<- CC 2180 GET_VREG(r0, r2) @ r0<- vBB (array object) 2181 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2182 cmp r0, #0 @ null array object? 2183 beq common_errNullObject @ yes, bail 2184 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2185 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2186 cmp r1, r3 @ compare unsigned index, length 2187 bcs common_errArrayIndex @ index >= length, bail 2188 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2189 GET_VREG(r2, r9) @ r2<- vAA 2190 GET_INST_OPCODE(ip) @ extract opcode from rINST 2191 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2192 GOTO_OPCODE(ip) @ jump to next instruction 2193 2194/* ------------------------------ */ 2195 .balign 64 2196.L_OP_APUT_WIDE: /* 0x4c */ 2197/* File: armv5te/OP_APUT_WIDE.S */ 2198 /* 2199 * Array put, 64 bits. vBB[vCC] <- vAA. 2200 * 2201 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 2202 */ 2203 /* aput-wide vAA, vBB, vCC */ 2204 FETCH(r0, 1) @ r0<- CCBB 2205 mov r9, rINST, lsr #8 @ r9<- AA 2206 and r2, r0, #255 @ r2<- BB 2207 mov r3, r0, lsr #8 @ r3<- CC 2208 GET_VREG(r0, r2) @ r0<- vBB (array object) 2209 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2210 cmp r0, #0 @ null array object? 2211 beq common_errNullObject @ yes, bail 2212 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2213 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2214 cmp r1, r3 @ compare unsigned index, length 2215 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2216 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2217 b common_errArrayIndex @ index >= length, bail 2218 @ May want to swap the order of these two branches depending on how the 2219 @ branch prediction (if any) handles conditional forward branches vs. 2220 @ unconditional forward branches. 2221 2222/* ------------------------------ */ 2223 .balign 64 2224.L_OP_APUT_OBJECT: /* 0x4d */ 2225/* File: armv5te/OP_APUT_OBJECT.S */ 2226 /* 2227 * Store an object into an array. vBB[vCC] <- vAA. 2228 */ 2229 /* op vAA, vBB, vCC */ 2230 FETCH(r0, 1) @ r0<- CCBB 2231 mov r9, rINST, lsr #8 @ r9<- AA 2232 and r2, r0, #255 @ r2<- BB 2233 mov r3, r0, lsr #8 @ r3<- CC 2234 GET_VREG(rINST, r2) @ rINST<- vBB (array object) 2235 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2236 cmp rINST, #0 @ null array object? 2237 GET_VREG(r9, r9) @ r9<- vAA 2238 beq common_errNullObject @ yes, bail 2239 ldr r3, [rINST, #offArrayObject_length] @ r3<- arrayObj->length 2240 add r10, rINST, r1, lsl #2 @ r10<- arrayObj + index*width 2241 cmp r1, r3 @ compare unsigned index, length 2242 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2243 b common_errArrayIndex @ index >= length, bail 2244 2245 2246/* ------------------------------ */ 2247 .balign 64 2248.L_OP_APUT_BOOLEAN: /* 0x4e */ 2249/* File: armv5te/OP_APUT_BOOLEAN.S */ 2250/* File: armv5te/OP_APUT.S */ 2251 /* 2252 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2253 * 2254 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2255 * instructions. We use a pair of FETCH_Bs instead. 2256 * 2257 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2258 */ 2259 /* op vAA, vBB, vCC */ 2260 FETCH_B(r2, 1, 0) @ r2<- BB 2261 mov r9, rINST, lsr #8 @ r9<- AA 2262 FETCH_B(r3, 1, 1) @ r3<- CC 2263 GET_VREG(r0, r2) @ r0<- vBB (array object) 2264 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2265 cmp r0, #0 @ null array object? 2266 beq common_errNullObject @ yes, bail 2267 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2268 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2269 cmp r1, r3 @ compare unsigned index, length 2270 bcs common_errArrayIndex @ index >= length, bail 2271 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2272 GET_VREG(r2, r9) @ r2<- vAA 2273 GET_INST_OPCODE(ip) @ extract opcode from rINST 2274 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2275 GOTO_OPCODE(ip) @ jump to next instruction 2276 2277 2278/* ------------------------------ */ 2279 .balign 64 2280.L_OP_APUT_BYTE: /* 0x4f */ 2281/* File: armv5te/OP_APUT_BYTE.S */ 2282/* File: armv5te/OP_APUT.S */ 2283 /* 2284 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2285 * 2286 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2287 * instructions. We use a pair of FETCH_Bs instead. 2288 * 2289 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2290 */ 2291 /* op vAA, vBB, vCC */ 2292 FETCH_B(r2, 1, 0) @ r2<- BB 2293 mov r9, rINST, lsr #8 @ r9<- AA 2294 FETCH_B(r3, 1, 1) @ r3<- CC 2295 GET_VREG(r0, r2) @ r0<- vBB (array object) 2296 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2297 cmp r0, #0 @ null array object? 2298 beq common_errNullObject @ yes, bail 2299 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2300 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2301 cmp r1, r3 @ compare unsigned index, length 2302 bcs common_errArrayIndex @ index >= length, bail 2303 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2304 GET_VREG(r2, r9) @ r2<- vAA 2305 GET_INST_OPCODE(ip) @ extract opcode from rINST 2306 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2307 GOTO_OPCODE(ip) @ jump to next instruction 2308 2309 2310/* ------------------------------ */ 2311 .balign 64 2312.L_OP_APUT_CHAR: /* 0x50 */ 2313/* File: armv5te/OP_APUT_CHAR.S */ 2314/* File: armv5te/OP_APUT.S */ 2315 /* 2316 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2317 * 2318 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2319 * instructions. We use a pair of FETCH_Bs instead. 2320 * 2321 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2322 */ 2323 /* op vAA, vBB, vCC */ 2324 FETCH_B(r2, 1, 0) @ r2<- BB 2325 mov r9, rINST, lsr #8 @ r9<- AA 2326 FETCH_B(r3, 1, 1) @ r3<- CC 2327 GET_VREG(r0, r2) @ r0<- vBB (array object) 2328 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2329 cmp r0, #0 @ null array object? 2330 beq common_errNullObject @ yes, bail 2331 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2332 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2333 cmp r1, r3 @ compare unsigned index, length 2334 bcs common_errArrayIndex @ index >= length, bail 2335 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2336 GET_VREG(r2, r9) @ r2<- vAA 2337 GET_INST_OPCODE(ip) @ extract opcode from rINST 2338 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2339 GOTO_OPCODE(ip) @ jump to next instruction 2340 2341 2342/* ------------------------------ */ 2343 .balign 64 2344.L_OP_APUT_SHORT: /* 0x51 */ 2345/* File: armv5te/OP_APUT_SHORT.S */ 2346/* File: armv5te/OP_APUT.S */ 2347 /* 2348 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2349 * 2350 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2351 * instructions. We use a pair of FETCH_Bs instead. 2352 * 2353 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2354 */ 2355 /* op vAA, vBB, vCC */ 2356 FETCH_B(r2, 1, 0) @ r2<- BB 2357 mov r9, rINST, lsr #8 @ r9<- AA 2358 FETCH_B(r3, 1, 1) @ r3<- CC 2359 GET_VREG(r0, r2) @ r0<- vBB (array object) 2360 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2361 cmp r0, #0 @ null array object? 2362 beq common_errNullObject @ yes, bail 2363 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2364 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2365 cmp r1, r3 @ compare unsigned index, length 2366 bcs common_errArrayIndex @ index >= length, bail 2367 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2368 GET_VREG(r2, r9) @ r2<- vAA 2369 GET_INST_OPCODE(ip) @ extract opcode from rINST 2370 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2371 GOTO_OPCODE(ip) @ jump to next instruction 2372 2373 2374/* ------------------------------ */ 2375 .balign 64 2376.L_OP_IGET: /* 0x52 */ 2377/* File: armv5te/OP_IGET.S */ 2378 /* 2379 * General 32-bit instance field get. 2380 * 2381 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2382 */ 2383 /* op vA, vB, field@CCCC */ 2384 mov r0, rINST, lsr #12 @ r0<- B 2385 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2386 FETCH(r1, 1) @ r1<- field ref CCCC 2387 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2388 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2389 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2390 cmp r0, #0 @ is resolved entry null? 2391 bne .LOP_IGET_finish @ no, already resolved 23928: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2393 EXPORT_PC() @ resolve() could throw 2394 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2395 bl dvmResolveInstField @ r0<- resolved InstField ptr 2396 cmp r0, #0 2397 bne .LOP_IGET_finish 2398 b common_exceptionThrown 2399 2400/* ------------------------------ */ 2401 .balign 64 2402.L_OP_IGET_WIDE: /* 0x53 */ 2403/* File: armv5te/OP_IGET_WIDE.S */ 2404 /* 2405 * Wide 32-bit instance field get. 2406 */ 2407 /* iget-wide vA, vB, field@CCCC */ 2408 mov r0, rINST, lsr #12 @ r0<- B 2409 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2410 FETCH(r1, 1) @ r1<- field ref CCCC 2411 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2412 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2413 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2414 cmp r0, #0 @ is resolved entry null? 2415 bne .LOP_IGET_WIDE_finish @ no, already resolved 24168: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2417 EXPORT_PC() @ resolve() could throw 2418 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2419 bl dvmResolveInstField @ r0<- resolved InstField ptr 2420 cmp r0, #0 2421 bne .LOP_IGET_WIDE_finish 2422 b common_exceptionThrown 2423 2424/* ------------------------------ */ 2425 .balign 64 2426.L_OP_IGET_OBJECT: /* 0x54 */ 2427/* File: armv5te/OP_IGET_OBJECT.S */ 2428/* File: armv5te/OP_IGET.S */ 2429 /* 2430 * General 32-bit instance field get. 2431 * 2432 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2433 */ 2434 /* op vA, vB, field@CCCC */ 2435 mov r0, rINST, lsr #12 @ r0<- B 2436 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2437 FETCH(r1, 1) @ r1<- field ref CCCC 2438 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2439 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2440 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2441 cmp r0, #0 @ is resolved entry null? 2442 bne .LOP_IGET_OBJECT_finish @ no, already resolved 24438: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2444 EXPORT_PC() @ resolve() could throw 2445 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2446 bl dvmResolveInstField @ r0<- resolved InstField ptr 2447 cmp r0, #0 2448 bne .LOP_IGET_OBJECT_finish 2449 b common_exceptionThrown 2450 2451 2452/* ------------------------------ */ 2453 .balign 64 2454.L_OP_IGET_BOOLEAN: /* 0x55 */ 2455/* File: armv5te/OP_IGET_BOOLEAN.S */ 2456@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2457/* File: armv5te/OP_IGET.S */ 2458 /* 2459 * General 32-bit instance field get. 2460 * 2461 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2462 */ 2463 /* op vA, vB, field@CCCC */ 2464 mov r0, rINST, lsr #12 @ r0<- B 2465 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2466 FETCH(r1, 1) @ r1<- field ref CCCC 2467 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2468 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2469 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2470 cmp r0, #0 @ is resolved entry null? 2471 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 24728: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2473 EXPORT_PC() @ resolve() could throw 2474 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2475 bl dvmResolveInstField @ r0<- resolved InstField ptr 2476 cmp r0, #0 2477 bne .LOP_IGET_BOOLEAN_finish 2478 b common_exceptionThrown 2479 2480 2481/* ------------------------------ */ 2482 .balign 64 2483.L_OP_IGET_BYTE: /* 0x56 */ 2484/* File: armv5te/OP_IGET_BYTE.S */ 2485@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2486/* File: armv5te/OP_IGET.S */ 2487 /* 2488 * General 32-bit instance field get. 2489 * 2490 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2491 */ 2492 /* op vA, vB, field@CCCC */ 2493 mov r0, rINST, lsr #12 @ r0<- B 2494 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2495 FETCH(r1, 1) @ r1<- field ref CCCC 2496 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2497 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2498 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2499 cmp r0, #0 @ is resolved entry null? 2500 bne .LOP_IGET_BYTE_finish @ no, already resolved 25018: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2502 EXPORT_PC() @ resolve() could throw 2503 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2504 bl dvmResolveInstField @ r0<- resolved InstField ptr 2505 cmp r0, #0 2506 bne .LOP_IGET_BYTE_finish 2507 b common_exceptionThrown 2508 2509 2510/* ------------------------------ */ 2511 .balign 64 2512.L_OP_IGET_CHAR: /* 0x57 */ 2513/* File: armv5te/OP_IGET_CHAR.S */ 2514@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2515/* File: armv5te/OP_IGET.S */ 2516 /* 2517 * General 32-bit instance field get. 2518 * 2519 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2520 */ 2521 /* op vA, vB, field@CCCC */ 2522 mov r0, rINST, lsr #12 @ r0<- B 2523 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2524 FETCH(r1, 1) @ r1<- field ref CCCC 2525 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2526 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2527 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2528 cmp r0, #0 @ is resolved entry null? 2529 bne .LOP_IGET_CHAR_finish @ no, already resolved 25308: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2531 EXPORT_PC() @ resolve() could throw 2532 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2533 bl dvmResolveInstField @ r0<- resolved InstField ptr 2534 cmp r0, #0 2535 bne .LOP_IGET_CHAR_finish 2536 b common_exceptionThrown 2537 2538 2539/* ------------------------------ */ 2540 .balign 64 2541.L_OP_IGET_SHORT: /* 0x58 */ 2542/* File: armv5te/OP_IGET_SHORT.S */ 2543@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2544/* File: armv5te/OP_IGET.S */ 2545 /* 2546 * General 32-bit instance field get. 2547 * 2548 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2549 */ 2550 /* op vA, vB, field@CCCC */ 2551 mov r0, rINST, lsr #12 @ r0<- B 2552 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2553 FETCH(r1, 1) @ r1<- field ref CCCC 2554 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2555 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2556 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2557 cmp r0, #0 @ is resolved entry null? 2558 bne .LOP_IGET_SHORT_finish @ no, already resolved 25598: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2560 EXPORT_PC() @ resolve() could throw 2561 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2562 bl dvmResolveInstField @ r0<- resolved InstField ptr 2563 cmp r0, #0 2564 bne .LOP_IGET_SHORT_finish 2565 b common_exceptionThrown 2566 2567 2568/* ------------------------------ */ 2569 .balign 64 2570.L_OP_IPUT: /* 0x59 */ 2571/* File: armv5te/OP_IPUT.S */ 2572 /* 2573 * General 32-bit instance field put. 2574 * 2575 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2576 */ 2577 /* op vA, vB, field@CCCC */ 2578 mov r0, rINST, lsr #12 @ r0<- B 2579 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2580 FETCH(r1, 1) @ r1<- field ref CCCC 2581 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2582 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2583 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2584 cmp r0, #0 @ is resolved entry null? 2585 bne .LOP_IPUT_finish @ no, already resolved 25868: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2587 EXPORT_PC() @ resolve() could throw 2588 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2589 bl dvmResolveInstField @ r0<- resolved InstField ptr 2590 cmp r0, #0 @ success? 2591 bne .LOP_IPUT_finish @ yes, finish up 2592 b common_exceptionThrown 2593 2594/* ------------------------------ */ 2595 .balign 64 2596.L_OP_IPUT_WIDE: /* 0x5a */ 2597/* File: armv5te/OP_IPUT_WIDE.S */ 2598 /* iput-wide vA, vB, field@CCCC */ 2599 mov r0, rINST, lsr #12 @ r0<- B 2600 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2601 FETCH(r1, 1) @ r1<- field ref CCCC 2602 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2603 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2604 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2605 cmp r0, #0 @ is resolved entry null? 2606 bne .LOP_IPUT_WIDE_finish @ no, already resolved 26078: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2608 EXPORT_PC() @ resolve() could throw 2609 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2610 bl dvmResolveInstField @ r0<- resolved InstField ptr 2611 cmp r0, #0 @ success? 2612 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2613 b common_exceptionThrown 2614 2615/* ------------------------------ */ 2616 .balign 64 2617.L_OP_IPUT_OBJECT: /* 0x5b */ 2618/* File: armv5te/OP_IPUT_OBJECT.S */ 2619 /* 2620 * 32-bit instance field put. 2621 * 2622 * for: iput-object, iput-object-volatile 2623 */ 2624 /* op vA, vB, field@CCCC */ 2625 mov r0, rINST, lsr #12 @ r0<- B 2626 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2627 FETCH(r1, 1) @ r1<- field ref CCCC 2628 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2629 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2630 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2631 cmp r0, #0 @ is resolved entry null? 2632 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 26338: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2634 EXPORT_PC() @ resolve() could throw 2635 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2636 bl dvmResolveInstField @ r0<- resolved InstField ptr 2637 cmp r0, #0 @ success? 2638 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2639 b common_exceptionThrown 2640 2641/* ------------------------------ */ 2642 .balign 64 2643.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2644/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2645@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2646/* File: armv5te/OP_IPUT.S */ 2647 /* 2648 * General 32-bit instance field put. 2649 * 2650 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2651 */ 2652 /* op vA, vB, field@CCCC */ 2653 mov r0, rINST, lsr #12 @ r0<- B 2654 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2655 FETCH(r1, 1) @ r1<- field ref CCCC 2656 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2657 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2658 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2659 cmp r0, #0 @ is resolved entry null? 2660 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 26618: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2662 EXPORT_PC() @ resolve() could throw 2663 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2664 bl dvmResolveInstField @ r0<- resolved InstField ptr 2665 cmp r0, #0 @ success? 2666 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2667 b common_exceptionThrown 2668 2669 2670/* ------------------------------ */ 2671 .balign 64 2672.L_OP_IPUT_BYTE: /* 0x5d */ 2673/* File: armv5te/OP_IPUT_BYTE.S */ 2674@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2675/* File: armv5te/OP_IPUT.S */ 2676 /* 2677 * General 32-bit instance field put. 2678 * 2679 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2680 */ 2681 /* op vA, vB, field@CCCC */ 2682 mov r0, rINST, lsr #12 @ r0<- B 2683 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2684 FETCH(r1, 1) @ r1<- field ref CCCC 2685 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2686 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2687 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2688 cmp r0, #0 @ is resolved entry null? 2689 bne .LOP_IPUT_BYTE_finish @ no, already resolved 26908: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2691 EXPORT_PC() @ resolve() could throw 2692 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2693 bl dvmResolveInstField @ r0<- resolved InstField ptr 2694 cmp r0, #0 @ success? 2695 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2696 b common_exceptionThrown 2697 2698 2699/* ------------------------------ */ 2700 .balign 64 2701.L_OP_IPUT_CHAR: /* 0x5e */ 2702/* File: armv5te/OP_IPUT_CHAR.S */ 2703@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2704/* File: armv5te/OP_IPUT.S */ 2705 /* 2706 * General 32-bit instance field put. 2707 * 2708 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2709 */ 2710 /* op vA, vB, field@CCCC */ 2711 mov r0, rINST, lsr #12 @ r0<- B 2712 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2713 FETCH(r1, 1) @ r1<- field ref CCCC 2714 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2715 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2716 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2717 cmp r0, #0 @ is resolved entry null? 2718 bne .LOP_IPUT_CHAR_finish @ no, already resolved 27198: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2720 EXPORT_PC() @ resolve() could throw 2721 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2722 bl dvmResolveInstField @ r0<- resolved InstField ptr 2723 cmp r0, #0 @ success? 2724 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2725 b common_exceptionThrown 2726 2727 2728/* ------------------------------ */ 2729 .balign 64 2730.L_OP_IPUT_SHORT: /* 0x5f */ 2731/* File: armv5te/OP_IPUT_SHORT.S */ 2732@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2733/* File: armv5te/OP_IPUT.S */ 2734 /* 2735 * General 32-bit instance field put. 2736 * 2737 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2738 */ 2739 /* op vA, vB, field@CCCC */ 2740 mov r0, rINST, lsr #12 @ r0<- B 2741 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2742 FETCH(r1, 1) @ r1<- field ref CCCC 2743 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2744 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2745 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2746 cmp r0, #0 @ is resolved entry null? 2747 bne .LOP_IPUT_SHORT_finish @ no, already resolved 27488: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2749 EXPORT_PC() @ resolve() could throw 2750 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2751 bl dvmResolveInstField @ r0<- resolved InstField ptr 2752 cmp r0, #0 @ success? 2753 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2754 b common_exceptionThrown 2755 2756 2757/* ------------------------------ */ 2758 .balign 64 2759.L_OP_SGET: /* 0x60 */ 2760/* File: armv5te/OP_SGET.S */ 2761 /* 2762 * General 32-bit SGET handler. 2763 * 2764 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2765 */ 2766 /* op vAA, field@BBBB */ 2767 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2768 FETCH(r1, 1) @ r1<- field ref BBBB 2769 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2770 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2771 cmp r0, #0 @ is resolved entry null? 2772 beq .LOP_SGET_resolve @ yes, do resolve 2773.LOP_SGET_finish: @ field ptr in r0 2774 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2775 @ no-op @ acquiring load 2776 mov r2, rINST, lsr #8 @ r2<- AA 2777 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2778 SET_VREG(r1, r2) @ fp[AA]<- r1 2779 GET_INST_OPCODE(ip) @ extract opcode from rINST 2780 GOTO_OPCODE(ip) @ jump to next instruction 2781 2782/* ------------------------------ */ 2783 .balign 64 2784.L_OP_SGET_WIDE: /* 0x61 */ 2785/* File: armv5te/OP_SGET_WIDE.S */ 2786 /* 2787 * 64-bit SGET handler. 2788 */ 2789 /* sget-wide vAA, field@BBBB */ 2790 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2791 FETCH(r1, 1) @ r1<- field ref BBBB 2792 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2793 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2794 cmp r0, #0 @ is resolved entry null? 2795 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2796.LOP_SGET_WIDE_finish: 2797 mov r9, rINST, lsr #8 @ r9<- AA 2798 .if 0 2799 add r0, r0, #offStaticField_value @ r0<- pointer to data 2800 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 2801 .else 2802 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 2803 .endif 2804 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2805 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2806 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 2807 GET_INST_OPCODE(ip) @ extract opcode from rINST 2808 GOTO_OPCODE(ip) @ jump to next instruction 2809 2810/* ------------------------------ */ 2811 .balign 64 2812.L_OP_SGET_OBJECT: /* 0x62 */ 2813/* File: armv5te/OP_SGET_OBJECT.S */ 2814/* File: armv5te/OP_SGET.S */ 2815 /* 2816 * General 32-bit SGET handler. 2817 * 2818 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2819 */ 2820 /* op vAA, field@BBBB */ 2821 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2822 FETCH(r1, 1) @ r1<- field ref BBBB 2823 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2824 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2825 cmp r0, #0 @ is resolved entry null? 2826 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2827.LOP_SGET_OBJECT_finish: @ field ptr in r0 2828 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2829 @ no-op @ acquiring load 2830 mov r2, rINST, lsr #8 @ r2<- AA 2831 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2832 SET_VREG(r1, r2) @ fp[AA]<- r1 2833 GET_INST_OPCODE(ip) @ extract opcode from rINST 2834 GOTO_OPCODE(ip) @ jump to next instruction 2835 2836 2837/* ------------------------------ */ 2838 .balign 64 2839.L_OP_SGET_BOOLEAN: /* 0x63 */ 2840/* File: armv5te/OP_SGET_BOOLEAN.S */ 2841/* File: armv5te/OP_SGET.S */ 2842 /* 2843 * General 32-bit SGET handler. 2844 * 2845 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2846 */ 2847 /* op vAA, field@BBBB */ 2848 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2849 FETCH(r1, 1) @ r1<- field ref BBBB 2850 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2851 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2852 cmp r0, #0 @ is resolved entry null? 2853 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2854.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2855 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2856 @ no-op @ acquiring load 2857 mov r2, rINST, lsr #8 @ r2<- AA 2858 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2859 SET_VREG(r1, r2) @ fp[AA]<- r1 2860 GET_INST_OPCODE(ip) @ extract opcode from rINST 2861 GOTO_OPCODE(ip) @ jump to next instruction 2862 2863 2864/* ------------------------------ */ 2865 .balign 64 2866.L_OP_SGET_BYTE: /* 0x64 */ 2867/* File: armv5te/OP_SGET_BYTE.S */ 2868/* File: armv5te/OP_SGET.S */ 2869 /* 2870 * General 32-bit SGET handler. 2871 * 2872 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2873 */ 2874 /* op vAA, field@BBBB */ 2875 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2876 FETCH(r1, 1) @ r1<- field ref BBBB 2877 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2878 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2879 cmp r0, #0 @ is resolved entry null? 2880 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2881.LOP_SGET_BYTE_finish: @ field ptr in r0 2882 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2883 @ no-op @ acquiring load 2884 mov r2, rINST, lsr #8 @ r2<- AA 2885 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2886 SET_VREG(r1, r2) @ fp[AA]<- r1 2887 GET_INST_OPCODE(ip) @ extract opcode from rINST 2888 GOTO_OPCODE(ip) @ jump to next instruction 2889 2890 2891/* ------------------------------ */ 2892 .balign 64 2893.L_OP_SGET_CHAR: /* 0x65 */ 2894/* File: armv5te/OP_SGET_CHAR.S */ 2895/* File: armv5te/OP_SGET.S */ 2896 /* 2897 * General 32-bit SGET handler. 2898 * 2899 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2900 */ 2901 /* op vAA, field@BBBB */ 2902 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2903 FETCH(r1, 1) @ r1<- field ref BBBB 2904 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2905 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2906 cmp r0, #0 @ is resolved entry null? 2907 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2908.LOP_SGET_CHAR_finish: @ field ptr in r0 2909 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2910 @ no-op @ acquiring load 2911 mov r2, rINST, lsr #8 @ r2<- AA 2912 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2913 SET_VREG(r1, r2) @ fp[AA]<- r1 2914 GET_INST_OPCODE(ip) @ extract opcode from rINST 2915 GOTO_OPCODE(ip) @ jump to next instruction 2916 2917 2918/* ------------------------------ */ 2919 .balign 64 2920.L_OP_SGET_SHORT: /* 0x66 */ 2921/* File: armv5te/OP_SGET_SHORT.S */ 2922/* File: armv5te/OP_SGET.S */ 2923 /* 2924 * General 32-bit SGET handler. 2925 * 2926 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2927 */ 2928 /* op vAA, field@BBBB */ 2929 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2930 FETCH(r1, 1) @ r1<- field ref BBBB 2931 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2932 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2933 cmp r0, #0 @ is resolved entry null? 2934 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 2935.LOP_SGET_SHORT_finish: @ field ptr in r0 2936 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2937 @ no-op @ acquiring load 2938 mov r2, rINST, lsr #8 @ r2<- AA 2939 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2940 SET_VREG(r1, r2) @ fp[AA]<- r1 2941 GET_INST_OPCODE(ip) @ extract opcode from rINST 2942 GOTO_OPCODE(ip) @ jump to next instruction 2943 2944 2945/* ------------------------------ */ 2946 .balign 64 2947.L_OP_SPUT: /* 0x67 */ 2948/* File: armv5te/OP_SPUT.S */ 2949 /* 2950 * General 32-bit SPUT handler. 2951 * 2952 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 2953 */ 2954 /* op vAA, field@BBBB */ 2955 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2956 FETCH(r1, 1) @ r1<- field ref BBBB 2957 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2958 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2959 cmp r0, #0 @ is resolved entry null? 2960 beq .LOP_SPUT_resolve @ yes, do resolve 2961.LOP_SPUT_finish: @ field ptr in r0 2962 mov r2, rINST, lsr #8 @ r2<- AA 2963 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2964 GET_VREG(r1, r2) @ r1<- fp[AA] 2965 GET_INST_OPCODE(ip) @ extract opcode from rINST 2966 @ no-op @ releasing store 2967 str r1, [r0, #offStaticField_value] @ field<- vAA 2968 GOTO_OPCODE(ip) @ jump to next instruction 2969 2970/* ------------------------------ */ 2971 .balign 64 2972.L_OP_SPUT_WIDE: /* 0x68 */ 2973/* File: armv5te/OP_SPUT_WIDE.S */ 2974 /* 2975 * 64-bit SPUT handler. 2976 */ 2977 /* sput-wide vAA, field@BBBB */ 2978 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 2979 FETCH(r1, 1) @ r1<- field ref BBBB 2980 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 2981 mov r9, rINST, lsr #8 @ r9<- AA 2982 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 2983 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2984 cmp r2, #0 @ is resolved entry null? 2985 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 2986.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9 2987 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2988 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 2989 GET_INST_OPCODE(r10) @ extract opcode from rINST 2990 .if 0 2991 add r2, r2, #offStaticField_value @ r2<- pointer to data 2992 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 2993 .else 2994 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 2995 .endif 2996 GOTO_OPCODE(r10) @ jump to next instruction 2997 2998/* ------------------------------ */ 2999 .balign 64 3000.L_OP_SPUT_OBJECT: /* 0x69 */ 3001/* File: armv5te/OP_SPUT_OBJECT.S */ 3002 /* 3003 * 32-bit SPUT handler for objects 3004 * 3005 * for: sput-object, sput-object-volatile 3006 */ 3007 /* op vAA, field@BBBB */ 3008 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3009 FETCH(r1, 1) @ r1<- field ref BBBB 3010 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3011 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3012 cmp r0, #0 @ is resolved entry null? 3013 bne .LOP_SPUT_OBJECT_finish @ no, continue 3014 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3015 EXPORT_PC() @ resolve() could throw, so export now 3016 ldr r0, [r9, #offMethod_clazz] @ r0<- method->clazz 3017 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 3018 cmp r0, #0 @ success? 3019 bne .LOP_SPUT_OBJECT_finish @ yes, finish 3020 b common_exceptionThrown @ no, handle exception 3021 3022 3023/* ------------------------------ */ 3024 .balign 64 3025.L_OP_SPUT_BOOLEAN: /* 0x6a */ 3026/* File: armv5te/OP_SPUT_BOOLEAN.S */ 3027/* File: armv5te/OP_SPUT.S */ 3028 /* 3029 * General 32-bit SPUT handler. 3030 * 3031 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3032 */ 3033 /* op vAA, field@BBBB */ 3034 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3035 FETCH(r1, 1) @ r1<- field ref BBBB 3036 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3037 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3038 cmp r0, #0 @ is resolved entry null? 3039 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 3040.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 3041 mov r2, rINST, lsr #8 @ r2<- AA 3042 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3043 GET_VREG(r1, r2) @ r1<- fp[AA] 3044 GET_INST_OPCODE(ip) @ extract opcode from rINST 3045 @ no-op @ releasing store 3046 str r1, [r0, #offStaticField_value] @ field<- vAA 3047 GOTO_OPCODE(ip) @ jump to next instruction 3048 3049 3050/* ------------------------------ */ 3051 .balign 64 3052.L_OP_SPUT_BYTE: /* 0x6b */ 3053/* File: armv5te/OP_SPUT_BYTE.S */ 3054/* File: armv5te/OP_SPUT.S */ 3055 /* 3056 * General 32-bit SPUT handler. 3057 * 3058 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3059 */ 3060 /* op vAA, field@BBBB */ 3061 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3062 FETCH(r1, 1) @ r1<- field ref BBBB 3063 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3064 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3065 cmp r0, #0 @ is resolved entry null? 3066 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 3067.LOP_SPUT_BYTE_finish: @ field ptr in r0 3068 mov r2, rINST, lsr #8 @ r2<- AA 3069 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3070 GET_VREG(r1, r2) @ r1<- fp[AA] 3071 GET_INST_OPCODE(ip) @ extract opcode from rINST 3072 @ no-op @ releasing store 3073 str r1, [r0, #offStaticField_value] @ field<- vAA 3074 GOTO_OPCODE(ip) @ jump to next instruction 3075 3076 3077/* ------------------------------ */ 3078 .balign 64 3079.L_OP_SPUT_CHAR: /* 0x6c */ 3080/* File: armv5te/OP_SPUT_CHAR.S */ 3081/* File: armv5te/OP_SPUT.S */ 3082 /* 3083 * General 32-bit SPUT handler. 3084 * 3085 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3086 */ 3087 /* op vAA, field@BBBB */ 3088 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3089 FETCH(r1, 1) @ r1<- field ref BBBB 3090 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3091 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3092 cmp r0, #0 @ is resolved entry null? 3093 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 3094.LOP_SPUT_CHAR_finish: @ field ptr in r0 3095 mov r2, rINST, lsr #8 @ r2<- AA 3096 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3097 GET_VREG(r1, r2) @ r1<- fp[AA] 3098 GET_INST_OPCODE(ip) @ extract opcode from rINST 3099 @ no-op @ releasing store 3100 str r1, [r0, #offStaticField_value] @ field<- vAA 3101 GOTO_OPCODE(ip) @ jump to next instruction 3102 3103 3104/* ------------------------------ */ 3105 .balign 64 3106.L_OP_SPUT_SHORT: /* 0x6d */ 3107/* File: armv5te/OP_SPUT_SHORT.S */ 3108/* File: armv5te/OP_SPUT.S */ 3109 /* 3110 * General 32-bit SPUT handler. 3111 * 3112 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3113 */ 3114 /* op vAA, field@BBBB */ 3115 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3116 FETCH(r1, 1) @ r1<- field ref BBBB 3117 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3118 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3119 cmp r0, #0 @ is resolved entry null? 3120 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 3121.LOP_SPUT_SHORT_finish: @ field ptr in r0 3122 mov r2, rINST, lsr #8 @ r2<- AA 3123 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3124 GET_VREG(r1, r2) @ r1<- fp[AA] 3125 GET_INST_OPCODE(ip) @ extract opcode from rINST 3126 @ no-op @ releasing store 3127 str r1, [r0, #offStaticField_value] @ field<- vAA 3128 GOTO_OPCODE(ip) @ jump to next instruction 3129 3130 3131/* ------------------------------ */ 3132 .balign 64 3133.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3134/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3135 /* 3136 * Handle a virtual method call. 3137 * 3138 * for: invoke-virtual, invoke-virtual/range 3139 */ 3140 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3141 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3142 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3143 FETCH(r1, 1) @ r1<- BBBB 3144 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3145 FETCH(r10, 2) @ r10<- GFED or CCCC 3146 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3147 .if (!0) 3148 and r10, r10, #15 @ r10<- D (or stays CCCC) 3149 .endif 3150 cmp r0, #0 @ already resolved? 3151 EXPORT_PC() @ must export for invoke 3152 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3153 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3154 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3155 mov r2, #METHOD_VIRTUAL @ resolver method type 3156 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3157 cmp r0, #0 @ got null? 3158 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3159 b common_exceptionThrown @ yes, handle exception 3160 3161/* ------------------------------ */ 3162 .balign 64 3163.L_OP_INVOKE_SUPER: /* 0x6f */ 3164/* File: armv5te/OP_INVOKE_SUPER.S */ 3165 /* 3166 * Handle a "super" method call. 3167 * 3168 * for: invoke-super, invoke-super/range 3169 */ 3170 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3171 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3172 FETCH(r10, 2) @ r10<- GFED or CCCC 3173 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3174 .if (!0) 3175 and r10, r10, #15 @ r10<- D (or stays CCCC) 3176 .endif 3177 FETCH(r1, 1) @ r1<- BBBB 3178 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3179 GET_VREG(r2, r10) @ r2<- "this" ptr 3180 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3181 cmp r2, #0 @ null "this"? 3182 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3183 beq common_errNullObject @ null "this", throw exception 3184 cmp r0, #0 @ already resolved? 3185 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3186 EXPORT_PC() @ must export for invoke 3187 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3188 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3189 3190/* ------------------------------ */ 3191 .balign 64 3192.L_OP_INVOKE_DIRECT: /* 0x70 */ 3193/* File: armv5te/OP_INVOKE_DIRECT.S */ 3194 /* 3195 * Handle a direct method call. 3196 * 3197 * (We could defer the "is 'this' pointer null" test to the common 3198 * method invocation code, and use a flag to indicate that static 3199 * calls don't count. If we do this as part of copying the arguments 3200 * out we could avoiding loading the first arg twice.) 3201 * 3202 * for: invoke-direct, invoke-direct/range 3203 */ 3204 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3205 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3206 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3207 FETCH(r1, 1) @ r1<- BBBB 3208 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3209 FETCH(r10, 2) @ r10<- GFED or CCCC 3210 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3211 .if (!0) 3212 and r10, r10, #15 @ r10<- D (or stays CCCC) 3213 .endif 3214 cmp r0, #0 @ already resolved? 3215 EXPORT_PC() @ must export for invoke 3216 GET_VREG(r2, r10) @ r2<- "this" ptr 3217 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3218.LOP_INVOKE_DIRECT_finish: 3219 cmp r2, #0 @ null "this" ref? 3220 bne common_invokeMethodNoRange @ no, continue on 3221 b common_errNullObject @ yes, throw exception 3222 3223/* ------------------------------ */ 3224 .balign 64 3225.L_OP_INVOKE_STATIC: /* 0x71 */ 3226/* File: armv5te/OP_INVOKE_STATIC.S */ 3227 /* 3228 * Handle a static method call. 3229 * 3230 * for: invoke-static, invoke-static/range 3231 */ 3232 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3233 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3234 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3235 FETCH(r1, 1) @ r1<- BBBB 3236 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3237 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3238 cmp r0, #0 @ already resolved? 3239 EXPORT_PC() @ must export for invoke 3240 bne common_invokeMethodNoRange @ yes, continue on 32410: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3242 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3243 mov r2, #METHOD_STATIC @ resolver method type 3244 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3245 cmp r0, #0 @ got null? 3246 bne common_invokeMethodNoRange @ no, continue 3247 b common_exceptionThrown @ yes, handle exception 3248 3249/* ------------------------------ */ 3250 .balign 64 3251.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3252/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3253 /* 3254 * Handle an interface method call. 3255 * 3256 * for: invoke-interface, invoke-interface/range 3257 */ 3258 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3259 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3260 FETCH(r2, 2) @ r2<- FEDC or CCCC 3261 FETCH(r1, 1) @ r1<- BBBB 3262 .if (!0) 3263 and r2, r2, #15 @ r2<- C (or stays CCCC) 3264 .endif 3265 EXPORT_PC() @ must export for invoke 3266 GET_VREG(r0, r2) @ r0<- first arg ("this") 3267 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3268 cmp r0, #0 @ null obj? 3269 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3270 beq common_errNullObject @ yes, fail 3271 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3272 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3273 cmp r0, #0 @ failed? 3274 beq common_exceptionThrown @ yes, handle exception 3275 b common_invokeMethodNoRange @ jump to common handler 3276 3277/* ------------------------------ */ 3278 .balign 64 3279.L_OP_UNUSED_73: /* 0x73 */ 3280/* File: armv5te/OP_UNUSED_73.S */ 3281/* File: armv5te/unused.S */ 3282 bl common_abort 3283 3284 3285/* ------------------------------ */ 3286 .balign 64 3287.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3288/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3289/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3290 /* 3291 * Handle a virtual method call. 3292 * 3293 * for: invoke-virtual, invoke-virtual/range 3294 */ 3295 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3296 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3297 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3298 FETCH(r1, 1) @ r1<- BBBB 3299 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3300 FETCH(r10, 2) @ r10<- GFED or CCCC 3301 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3302 .if (!1) 3303 and r10, r10, #15 @ r10<- D (or stays CCCC) 3304 .endif 3305 cmp r0, #0 @ already resolved? 3306 EXPORT_PC() @ must export for invoke 3307 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3308 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3309 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3310 mov r2, #METHOD_VIRTUAL @ resolver method type 3311 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3312 cmp r0, #0 @ got null? 3313 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3314 b common_exceptionThrown @ yes, handle exception 3315 3316 3317/* ------------------------------ */ 3318 .balign 64 3319.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3320/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3321/* File: armv5te/OP_INVOKE_SUPER.S */ 3322 /* 3323 * Handle a "super" method call. 3324 * 3325 * for: invoke-super, invoke-super/range 3326 */ 3327 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3328 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3329 FETCH(r10, 2) @ r10<- GFED or CCCC 3330 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3331 .if (!1) 3332 and r10, r10, #15 @ r10<- D (or stays CCCC) 3333 .endif 3334 FETCH(r1, 1) @ r1<- BBBB 3335 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3336 GET_VREG(r2, r10) @ r2<- "this" ptr 3337 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3338 cmp r2, #0 @ null "this"? 3339 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3340 beq common_errNullObject @ null "this", throw exception 3341 cmp r0, #0 @ already resolved? 3342 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3343 EXPORT_PC() @ must export for invoke 3344 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3345 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3346 3347 3348/* ------------------------------ */ 3349 .balign 64 3350.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3351/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3352/* File: armv5te/OP_INVOKE_DIRECT.S */ 3353 /* 3354 * Handle a direct method call. 3355 * 3356 * (We could defer the "is 'this' pointer null" test to the common 3357 * method invocation code, and use a flag to indicate that static 3358 * calls don't count. If we do this as part of copying the arguments 3359 * out we could avoiding loading the first arg twice.) 3360 * 3361 * for: invoke-direct, invoke-direct/range 3362 */ 3363 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3364 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3365 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3366 FETCH(r1, 1) @ r1<- BBBB 3367 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3368 FETCH(r10, 2) @ r10<- GFED or CCCC 3369 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3370 .if (!1) 3371 and r10, r10, #15 @ r10<- D (or stays CCCC) 3372 .endif 3373 cmp r0, #0 @ already resolved? 3374 EXPORT_PC() @ must export for invoke 3375 GET_VREG(r2, r10) @ r2<- "this" ptr 3376 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3377.LOP_INVOKE_DIRECT_RANGE_finish: 3378 cmp r2, #0 @ null "this" ref? 3379 bne common_invokeMethodRange @ no, continue on 3380 b common_errNullObject @ yes, throw exception 3381 3382 3383/* ------------------------------ */ 3384 .balign 64 3385.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3386/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3387/* File: armv5te/OP_INVOKE_STATIC.S */ 3388 /* 3389 * Handle a static method call. 3390 * 3391 * for: invoke-static, invoke-static/range 3392 */ 3393 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3394 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3395 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3396 FETCH(r1, 1) @ r1<- BBBB 3397 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3398 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3399 cmp r0, #0 @ already resolved? 3400 EXPORT_PC() @ must export for invoke 3401 bne common_invokeMethodRange @ yes, continue on 34020: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3403 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3404 mov r2, #METHOD_STATIC @ resolver method type 3405 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3406 cmp r0, #0 @ got null? 3407 bne common_invokeMethodRange @ no, continue 3408 b common_exceptionThrown @ yes, handle exception 3409 3410 3411/* ------------------------------ */ 3412 .balign 64 3413.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3414/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3415/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3416 /* 3417 * Handle an interface method call. 3418 * 3419 * for: invoke-interface, invoke-interface/range 3420 */ 3421 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3422 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3423 FETCH(r2, 2) @ r2<- FEDC or CCCC 3424 FETCH(r1, 1) @ r1<- BBBB 3425 .if (!1) 3426 and r2, r2, #15 @ r2<- C (or stays CCCC) 3427 .endif 3428 EXPORT_PC() @ must export for invoke 3429 GET_VREG(r0, r2) @ r0<- first arg ("this") 3430 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3431 cmp r0, #0 @ null obj? 3432 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3433 beq common_errNullObject @ yes, fail 3434 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3435 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3436 cmp r0, #0 @ failed? 3437 beq common_exceptionThrown @ yes, handle exception 3438 b common_invokeMethodRange @ jump to common handler 3439 3440 3441/* ------------------------------ */ 3442 .balign 64 3443.L_OP_UNUSED_79: /* 0x79 */ 3444/* File: armv5te/OP_UNUSED_79.S */ 3445/* File: armv5te/unused.S */ 3446 bl common_abort 3447 3448 3449/* ------------------------------ */ 3450 .balign 64 3451.L_OP_UNUSED_7A: /* 0x7a */ 3452/* File: armv5te/OP_UNUSED_7A.S */ 3453/* File: armv5te/unused.S */ 3454 bl common_abort 3455 3456 3457/* ------------------------------ */ 3458 .balign 64 3459.L_OP_NEG_INT: /* 0x7b */ 3460/* File: armv5te/OP_NEG_INT.S */ 3461/* File: armv5te/unop.S */ 3462 /* 3463 * Generic 32-bit unary operation. Provide an "instr" line that 3464 * specifies an instruction that performs "result = op r0". 3465 * This could be an ARM instruction or a function call. 3466 * 3467 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3468 * int-to-byte, int-to-char, int-to-short 3469 */ 3470 /* unop vA, vB */ 3471 mov r3, rINST, lsr #12 @ r3<- B 3472 mov r9, rINST, lsr #8 @ r9<- A+ 3473 GET_VREG(r0, r3) @ r0<- vB 3474 and r9, r9, #15 3475 @ optional op; may set condition codes 3476 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3477 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3478 GET_INST_OPCODE(ip) @ extract opcode from rINST 3479 SET_VREG(r0, r9) @ vAA<- r0 3480 GOTO_OPCODE(ip) @ jump to next instruction 3481 /* 9-10 instructions */ 3482 3483 3484/* ------------------------------ */ 3485 .balign 64 3486.L_OP_NOT_INT: /* 0x7c */ 3487/* File: armv5te/OP_NOT_INT.S */ 3488/* File: armv5te/unop.S */ 3489 /* 3490 * Generic 32-bit unary operation. Provide an "instr" line that 3491 * specifies an instruction that performs "result = op r0". 3492 * This could be an ARM instruction or a function call. 3493 * 3494 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3495 * int-to-byte, int-to-char, int-to-short 3496 */ 3497 /* unop vA, vB */ 3498 mov r3, rINST, lsr #12 @ r3<- B 3499 mov r9, rINST, lsr #8 @ r9<- A+ 3500 GET_VREG(r0, r3) @ r0<- vB 3501 and r9, r9, #15 3502 @ optional op; may set condition codes 3503 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3504 mvn r0, r0 @ r0<- op, r0-r3 changed 3505 GET_INST_OPCODE(ip) @ extract opcode from rINST 3506 SET_VREG(r0, r9) @ vAA<- r0 3507 GOTO_OPCODE(ip) @ jump to next instruction 3508 /* 9-10 instructions */ 3509 3510 3511/* ------------------------------ */ 3512 .balign 64 3513.L_OP_NEG_LONG: /* 0x7d */ 3514/* File: armv5te/OP_NEG_LONG.S */ 3515/* File: armv5te/unopWide.S */ 3516 /* 3517 * Generic 64-bit unary operation. Provide an "instr" line that 3518 * specifies an instruction that performs "result = op r0/r1". 3519 * This could be an ARM instruction or a function call. 3520 * 3521 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3522 */ 3523 /* unop vA, vB */ 3524 mov r9, rINST, lsr #8 @ r9<- A+ 3525 mov r3, rINST, lsr #12 @ r3<- B 3526 and r9, r9, #15 3527 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3528 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3529 ldmia r3, {r0-r1} @ r0/r1<- vAA 3530 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3531 rsbs r0, r0, #0 @ optional op; may set condition codes 3532 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3533 GET_INST_OPCODE(ip) @ extract opcode from rINST 3534 stmia r9, {r0-r1} @ vAA<- r0/r1 3535 GOTO_OPCODE(ip) @ jump to next instruction 3536 /* 12-13 instructions */ 3537 3538 3539/* ------------------------------ */ 3540 .balign 64 3541.L_OP_NOT_LONG: /* 0x7e */ 3542/* File: armv5te/OP_NOT_LONG.S */ 3543/* File: armv5te/unopWide.S */ 3544 /* 3545 * Generic 64-bit unary operation. Provide an "instr" line that 3546 * specifies an instruction that performs "result = op r0/r1". 3547 * This could be an ARM instruction or a function call. 3548 * 3549 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3550 */ 3551 /* unop vA, vB */ 3552 mov r9, rINST, lsr #8 @ r9<- A+ 3553 mov r3, rINST, lsr #12 @ r3<- B 3554 and r9, r9, #15 3555 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3556 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3557 ldmia r3, {r0-r1} @ r0/r1<- vAA 3558 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3559 mvn r0, r0 @ optional op; may set condition codes 3560 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3561 GET_INST_OPCODE(ip) @ extract opcode from rINST 3562 stmia r9, {r0-r1} @ vAA<- r0/r1 3563 GOTO_OPCODE(ip) @ jump to next instruction 3564 /* 12-13 instructions */ 3565 3566 3567/* ------------------------------ */ 3568 .balign 64 3569.L_OP_NEG_FLOAT: /* 0x7f */ 3570/* File: armv5te/OP_NEG_FLOAT.S */ 3571/* File: armv5te/unop.S */ 3572 /* 3573 * Generic 32-bit unary operation. Provide an "instr" line that 3574 * specifies an instruction that performs "result = op r0". 3575 * This could be an ARM instruction or a function call. 3576 * 3577 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3578 * int-to-byte, int-to-char, int-to-short 3579 */ 3580 /* unop vA, vB */ 3581 mov r3, rINST, lsr #12 @ r3<- B 3582 mov r9, rINST, lsr #8 @ r9<- A+ 3583 GET_VREG(r0, r3) @ r0<- vB 3584 and r9, r9, #15 3585 @ optional op; may set condition codes 3586 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3587 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3588 GET_INST_OPCODE(ip) @ extract opcode from rINST 3589 SET_VREG(r0, r9) @ vAA<- r0 3590 GOTO_OPCODE(ip) @ jump to next instruction 3591 /* 9-10 instructions */ 3592 3593 3594/* ------------------------------ */ 3595 .balign 64 3596.L_OP_NEG_DOUBLE: /* 0x80 */ 3597/* File: armv5te/OP_NEG_DOUBLE.S */ 3598/* File: armv5te/unopWide.S */ 3599 /* 3600 * Generic 64-bit unary operation. Provide an "instr" line that 3601 * specifies an instruction that performs "result = op r0/r1". 3602 * This could be an ARM instruction or a function call. 3603 * 3604 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3605 */ 3606 /* unop vA, vB */ 3607 mov r9, rINST, lsr #8 @ r9<- A+ 3608 mov r3, rINST, lsr #12 @ r3<- B 3609 and r9, r9, #15 3610 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3611 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3612 ldmia r3, {r0-r1} @ r0/r1<- vAA 3613 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3614 @ optional op; may set condition codes 3615 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3616 GET_INST_OPCODE(ip) @ extract opcode from rINST 3617 stmia r9, {r0-r1} @ vAA<- r0/r1 3618 GOTO_OPCODE(ip) @ jump to next instruction 3619 /* 12-13 instructions */ 3620 3621 3622/* ------------------------------ */ 3623 .balign 64 3624.L_OP_INT_TO_LONG: /* 0x81 */ 3625/* File: armv5te/OP_INT_TO_LONG.S */ 3626/* File: armv5te/unopWider.S */ 3627 /* 3628 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3629 * that specifies an instruction that performs "result = op r0", where 3630 * "result" is a 64-bit quantity in r0/r1. 3631 * 3632 * For: int-to-long, int-to-double, float-to-long, float-to-double 3633 */ 3634 /* unop vA, vB */ 3635 mov r9, rINST, lsr #8 @ r9<- A+ 3636 mov r3, rINST, lsr #12 @ r3<- B 3637 and r9, r9, #15 3638 GET_VREG(r0, r3) @ r0<- vB 3639 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3640 @ optional op; may set condition codes 3641 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3642 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3643 GET_INST_OPCODE(ip) @ extract opcode from rINST 3644 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3645 GOTO_OPCODE(ip) @ jump to next instruction 3646 /* 10-11 instructions */ 3647 3648 3649/* ------------------------------ */ 3650 .balign 64 3651.L_OP_INT_TO_FLOAT: /* 0x82 */ 3652/* File: arm-vfp/OP_INT_TO_FLOAT.S */ 3653/* File: arm-vfp/funop.S */ 3654 /* 3655 * Generic 32-bit unary floating-point operation. Provide an "instr" 3656 * line that specifies an instruction that performs "s1 = op s0". 3657 * 3658 * for: int-to-float, float-to-int 3659 */ 3660 /* unop vA, vB */ 3661 mov r3, rINST, lsr #12 @ r3<- B 3662 mov r9, rINST, lsr #8 @ r9<- A+ 3663 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3664 flds s0, [r3] @ s0<- vB 3665 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3666 and r9, r9, #15 @ r9<- A 3667 fsitos s1, s0 @ s1<- op 3668 GET_INST_OPCODE(ip) @ extract opcode from rINST 3669 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3670 fsts s1, [r9] @ vA<- s1 3671 GOTO_OPCODE(ip) @ jump to next instruction 3672 3673 3674/* ------------------------------ */ 3675 .balign 64 3676.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3677/* File: arm-vfp/OP_INT_TO_DOUBLE.S */ 3678/* File: arm-vfp/funopWider.S */ 3679 /* 3680 * Generic 32bit-to-64bit floating point unary operation. Provide an 3681 * "instr" line that specifies an instruction that performs "d0 = op s0". 3682 * 3683 * For: int-to-double, float-to-double 3684 */ 3685 /* unop vA, vB */ 3686 mov r3, rINST, lsr #12 @ r3<- B 3687 mov r9, rINST, lsr #8 @ r9<- A+ 3688 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3689 flds s0, [r3] @ s0<- vB 3690 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3691 and r9, r9, #15 @ r9<- A 3692 fsitod d0, s0 @ d0<- op 3693 GET_INST_OPCODE(ip) @ extract opcode from rINST 3694 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3695 fstd d0, [r9] @ vA<- d0 3696 GOTO_OPCODE(ip) @ jump to next instruction 3697 3698 3699/* ------------------------------ */ 3700 .balign 64 3701.L_OP_LONG_TO_INT: /* 0x84 */ 3702/* File: armv5te/OP_LONG_TO_INT.S */ 3703/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3704/* File: armv5te/OP_MOVE.S */ 3705 /* for move, move-object, long-to-int */ 3706 /* op vA, vB */ 3707 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3708 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3709 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3710 GET_VREG(r2, r1) @ r2<- fp[B] 3711 and r0, r0, #15 3712 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3713 SET_VREG(r2, r0) @ fp[A]<- r2 3714 GOTO_OPCODE(ip) @ execute next instruction 3715 3716 3717/* ------------------------------ */ 3718 .balign 64 3719.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3720/* File: armv5te/OP_LONG_TO_FLOAT.S */ 3721/* File: armv5te/unopNarrower.S */ 3722 /* 3723 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3724 * that specifies an instruction that performs "result = op r0/r1", where 3725 * "result" is a 32-bit quantity in r0. 3726 * 3727 * For: long-to-float, double-to-int, double-to-float 3728 * 3729 * (This would work for long-to-int, but that instruction is actually 3730 * an exact match for OP_MOVE.) 3731 */ 3732 /* unop vA, vB */ 3733 mov r3, rINST, lsr #12 @ r3<- B 3734 mov r9, rINST, lsr #8 @ r9<- A+ 3735 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3736 and r9, r9, #15 3737 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3738 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3739 @ optional op; may set condition codes 3740 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3741 GET_INST_OPCODE(ip) @ extract opcode from rINST 3742 SET_VREG(r0, r9) @ vA<- r0 3743 GOTO_OPCODE(ip) @ jump to next instruction 3744 /* 10-11 instructions */ 3745 3746 3747/* ------------------------------ */ 3748 .balign 64 3749.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3750/* File: armv5te/OP_LONG_TO_DOUBLE.S */ 3751/* File: armv5te/unopWide.S */ 3752 /* 3753 * Generic 64-bit unary operation. Provide an "instr" line that 3754 * specifies an instruction that performs "result = op r0/r1". 3755 * This could be an ARM instruction or a function call. 3756 * 3757 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3758 */ 3759 /* unop vA, vB */ 3760 mov r9, rINST, lsr #8 @ r9<- A+ 3761 mov r3, rINST, lsr #12 @ r3<- B 3762 and r9, r9, #15 3763 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3764 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3765 ldmia r3, {r0-r1} @ r0/r1<- vAA 3766 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3767 @ optional op; may set condition codes 3768 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3769 GET_INST_OPCODE(ip) @ extract opcode from rINST 3770 stmia r9, {r0-r1} @ vAA<- r0/r1 3771 GOTO_OPCODE(ip) @ jump to next instruction 3772 /* 12-13 instructions */ 3773 3774 3775/* ------------------------------ */ 3776 .balign 64 3777.L_OP_FLOAT_TO_INT: /* 0x87 */ 3778/* File: arm-vfp/OP_FLOAT_TO_INT.S */ 3779/* File: arm-vfp/funop.S */ 3780 /* 3781 * Generic 32-bit unary floating-point operation. Provide an "instr" 3782 * line that specifies an instruction that performs "s1 = op s0". 3783 * 3784 * for: int-to-float, float-to-int 3785 */ 3786 /* unop vA, vB */ 3787 mov r3, rINST, lsr #12 @ r3<- B 3788 mov r9, rINST, lsr #8 @ r9<- A+ 3789 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3790 flds s0, [r3] @ s0<- vB 3791 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3792 and r9, r9, #15 @ r9<- A 3793 ftosizs s1, s0 @ s1<- op 3794 GET_INST_OPCODE(ip) @ extract opcode from rINST 3795 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3796 fsts s1, [r9] @ vA<- s1 3797 GOTO_OPCODE(ip) @ jump to next instruction 3798 3799 3800/* ------------------------------ */ 3801 .balign 64 3802.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3803/* File: armv5te/OP_FLOAT_TO_LONG.S */ 3804@include "armv5te/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3805/* File: armv5te/unopWider.S */ 3806 /* 3807 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3808 * that specifies an instruction that performs "result = op r0", where 3809 * "result" is a 64-bit quantity in r0/r1. 3810 * 3811 * For: int-to-long, int-to-double, float-to-long, float-to-double 3812 */ 3813 /* unop vA, vB */ 3814 mov r9, rINST, lsr #8 @ r9<- A+ 3815 mov r3, rINST, lsr #12 @ r3<- B 3816 and r9, r9, #15 3817 GET_VREG(r0, r3) @ r0<- vB 3818 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3819 @ optional op; may set condition codes 3820 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3821 bl f2l_doconv @ r0<- op, r0-r3 changed 3822 GET_INST_OPCODE(ip) @ extract opcode from rINST 3823 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3824 GOTO_OPCODE(ip) @ jump to next instruction 3825 /* 10-11 instructions */ 3826 3827 3828 3829/* ------------------------------ */ 3830 .balign 64 3831.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3832/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */ 3833/* File: arm-vfp/funopWider.S */ 3834 /* 3835 * Generic 32bit-to-64bit floating point unary operation. Provide an 3836 * "instr" line that specifies an instruction that performs "d0 = op s0". 3837 * 3838 * For: int-to-double, float-to-double 3839 */ 3840 /* unop vA, vB */ 3841 mov r3, rINST, lsr #12 @ r3<- B 3842 mov r9, rINST, lsr #8 @ r9<- A+ 3843 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3844 flds s0, [r3] @ s0<- vB 3845 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3846 and r9, r9, #15 @ r9<- A 3847 fcvtds d0, s0 @ d0<- op 3848 GET_INST_OPCODE(ip) @ extract opcode from rINST 3849 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3850 fstd d0, [r9] @ vA<- d0 3851 GOTO_OPCODE(ip) @ jump to next instruction 3852 3853 3854/* ------------------------------ */ 3855 .balign 64 3856.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3857/* File: arm-vfp/OP_DOUBLE_TO_INT.S */ 3858/* File: arm-vfp/funopNarrower.S */ 3859 /* 3860 * Generic 64bit-to-32bit unary floating point operation. Provide an 3861 * "instr" line that specifies an instruction that performs "s0 = op d0". 3862 * 3863 * For: double-to-int, double-to-float 3864 */ 3865 /* unop vA, vB */ 3866 mov r3, rINST, lsr #12 @ r3<- B 3867 mov r9, rINST, lsr #8 @ r9<- A+ 3868 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3869 fldd d0, [r3] @ d0<- vB 3870 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3871 and r9, r9, #15 @ r9<- A 3872 ftosizd s0, d0 @ s0<- op 3873 GET_INST_OPCODE(ip) @ extract opcode from rINST 3874 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3875 fsts s0, [r9] @ vA<- s0 3876 GOTO_OPCODE(ip) @ jump to next instruction 3877 3878 3879/* ------------------------------ */ 3880 .balign 64 3881.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3882/* File: armv5te/OP_DOUBLE_TO_LONG.S */ 3883@include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"} 3884/* File: armv5te/unopWide.S */ 3885 /* 3886 * Generic 64-bit unary operation. Provide an "instr" line that 3887 * specifies an instruction that performs "result = op r0/r1". 3888 * This could be an ARM instruction or a function call. 3889 * 3890 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3891 */ 3892 /* unop vA, vB */ 3893 mov r9, rINST, lsr #8 @ r9<- A+ 3894 mov r3, rINST, lsr #12 @ r3<- B 3895 and r9, r9, #15 3896 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3897 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3898 ldmia r3, {r0-r1} @ r0/r1<- vAA 3899 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3900 @ optional op; may set condition codes 3901 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 3902 GET_INST_OPCODE(ip) @ extract opcode from rINST 3903 stmia r9, {r0-r1} @ vAA<- r0/r1 3904 GOTO_OPCODE(ip) @ jump to next instruction 3905 /* 12-13 instructions */ 3906 3907 3908 3909/* ------------------------------ */ 3910 .balign 64 3911.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3912/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */ 3913/* File: arm-vfp/funopNarrower.S */ 3914 /* 3915 * Generic 64bit-to-32bit unary floating point operation. Provide an 3916 * "instr" line that specifies an instruction that performs "s0 = op d0". 3917 * 3918 * For: double-to-int, double-to-float 3919 */ 3920 /* unop vA, vB */ 3921 mov r3, rINST, lsr #12 @ r3<- B 3922 mov r9, rINST, lsr #8 @ r9<- A+ 3923 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3924 fldd d0, [r3] @ d0<- vB 3925 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3926 and r9, r9, #15 @ r9<- A 3927 fcvtsd s0, d0 @ s0<- op 3928 GET_INST_OPCODE(ip) @ extract opcode from rINST 3929 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3930 fsts s0, [r9] @ vA<- s0 3931 GOTO_OPCODE(ip) @ jump to next instruction 3932 3933 3934/* ------------------------------ */ 3935 .balign 64 3936.L_OP_INT_TO_BYTE: /* 0x8d */ 3937/* File: armv5te/OP_INT_TO_BYTE.S */ 3938/* File: armv5te/unop.S */ 3939 /* 3940 * Generic 32-bit unary operation. Provide an "instr" line that 3941 * specifies an instruction that performs "result = op r0". 3942 * This could be an ARM instruction or a function call. 3943 * 3944 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3945 * int-to-byte, int-to-char, int-to-short 3946 */ 3947 /* unop vA, vB */ 3948 mov r3, rINST, lsr #12 @ r3<- B 3949 mov r9, rINST, lsr #8 @ r9<- A+ 3950 GET_VREG(r0, r3) @ r0<- vB 3951 and r9, r9, #15 3952 mov r0, r0, asl #24 @ optional op; may set condition codes 3953 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3954 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed 3955 GET_INST_OPCODE(ip) @ extract opcode from rINST 3956 SET_VREG(r0, r9) @ vAA<- r0 3957 GOTO_OPCODE(ip) @ jump to next instruction 3958 /* 9-10 instructions */ 3959 3960 3961/* ------------------------------ */ 3962 .balign 64 3963.L_OP_INT_TO_CHAR: /* 0x8e */ 3964/* File: armv5te/OP_INT_TO_CHAR.S */ 3965/* File: armv5te/unop.S */ 3966 /* 3967 * Generic 32-bit unary operation. Provide an "instr" line that 3968 * specifies an instruction that performs "result = op r0". 3969 * This could be an ARM instruction or a function call. 3970 * 3971 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3972 * int-to-byte, int-to-char, int-to-short 3973 */ 3974 /* unop vA, vB */ 3975 mov r3, rINST, lsr #12 @ r3<- B 3976 mov r9, rINST, lsr #8 @ r9<- A+ 3977 GET_VREG(r0, r3) @ r0<- vB 3978 and r9, r9, #15 3979 mov r0, r0, asl #16 @ optional op; may set condition codes 3980 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3981 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed 3982 GET_INST_OPCODE(ip) @ extract opcode from rINST 3983 SET_VREG(r0, r9) @ vAA<- r0 3984 GOTO_OPCODE(ip) @ jump to next instruction 3985 /* 9-10 instructions */ 3986 3987 3988/* ------------------------------ */ 3989 .balign 64 3990.L_OP_INT_TO_SHORT: /* 0x8f */ 3991/* File: armv5te/OP_INT_TO_SHORT.S */ 3992/* File: armv5te/unop.S */ 3993 /* 3994 * Generic 32-bit unary operation. Provide an "instr" line that 3995 * specifies an instruction that performs "result = op r0". 3996 * This could be an ARM instruction or a function call. 3997 * 3998 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3999 * int-to-byte, int-to-char, int-to-short 4000 */ 4001 /* unop vA, vB */ 4002 mov r3, rINST, lsr #12 @ r3<- B 4003 mov r9, rINST, lsr #8 @ r9<- A+ 4004 GET_VREG(r0, r3) @ r0<- vB 4005 and r9, r9, #15 4006 mov r0, r0, asl #16 @ optional op; may set condition codes 4007 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4008 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed 4009 GET_INST_OPCODE(ip) @ extract opcode from rINST 4010 SET_VREG(r0, r9) @ vAA<- r0 4011 GOTO_OPCODE(ip) @ jump to next instruction 4012 /* 9-10 instructions */ 4013 4014 4015/* ------------------------------ */ 4016 .balign 64 4017.L_OP_ADD_INT: /* 0x90 */ 4018/* File: armv5te/OP_ADD_INT.S */ 4019/* File: armv5te/binop.S */ 4020 /* 4021 * Generic 32-bit binary operation. Provide an "instr" line that 4022 * specifies an instruction that performs "result = r0 op r1". 4023 * This could be an ARM instruction or a function call. (If the result 4024 * comes back in a register other than r0, you can override "result".) 4025 * 4026 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4027 * vCC (r1). Useful for integer division and modulus. Note that we 4028 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4029 * handles it correctly. 4030 * 4031 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4032 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4033 * mul-float, div-float, rem-float 4034 */ 4035 /* binop vAA, vBB, vCC */ 4036 FETCH(r0, 1) @ r0<- CCBB 4037 mov r9, rINST, lsr #8 @ r9<- AA 4038 mov r3, r0, lsr #8 @ r3<- CC 4039 and r2, r0, #255 @ r2<- BB 4040 GET_VREG(r1, r3) @ r1<- vCC 4041 GET_VREG(r0, r2) @ r0<- vBB 4042 .if 0 4043 cmp r1, #0 @ is second operand zero? 4044 beq common_errDivideByZero 4045 .endif 4046 4047 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4048 @ optional op; may set condition codes 4049 add r0, r0, r1 @ r0<- op, r0-r3 changed 4050 GET_INST_OPCODE(ip) @ extract opcode from rINST 4051 SET_VREG(r0, r9) @ vAA<- r0 4052 GOTO_OPCODE(ip) @ jump to next instruction 4053 /* 11-14 instructions */ 4054 4055 4056/* ------------------------------ */ 4057 .balign 64 4058.L_OP_SUB_INT: /* 0x91 */ 4059/* File: armv5te/OP_SUB_INT.S */ 4060/* File: armv5te/binop.S */ 4061 /* 4062 * Generic 32-bit binary operation. Provide an "instr" line that 4063 * specifies an instruction that performs "result = r0 op r1". 4064 * This could be an ARM instruction or a function call. (If the result 4065 * comes back in a register other than r0, you can override "result".) 4066 * 4067 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4068 * vCC (r1). Useful for integer division and modulus. Note that we 4069 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4070 * handles it correctly. 4071 * 4072 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4073 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4074 * mul-float, div-float, rem-float 4075 */ 4076 /* binop vAA, vBB, vCC */ 4077 FETCH(r0, 1) @ r0<- CCBB 4078 mov r9, rINST, lsr #8 @ r9<- AA 4079 mov r3, r0, lsr #8 @ r3<- CC 4080 and r2, r0, #255 @ r2<- BB 4081 GET_VREG(r1, r3) @ r1<- vCC 4082 GET_VREG(r0, r2) @ r0<- vBB 4083 .if 0 4084 cmp r1, #0 @ is second operand zero? 4085 beq common_errDivideByZero 4086 .endif 4087 4088 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4089 @ optional op; may set condition codes 4090 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4091 GET_INST_OPCODE(ip) @ extract opcode from rINST 4092 SET_VREG(r0, r9) @ vAA<- r0 4093 GOTO_OPCODE(ip) @ jump to next instruction 4094 /* 11-14 instructions */ 4095 4096 4097/* ------------------------------ */ 4098 .balign 64 4099.L_OP_MUL_INT: /* 0x92 */ 4100/* File: armv5te/OP_MUL_INT.S */ 4101/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4102/* File: armv5te/binop.S */ 4103 /* 4104 * Generic 32-bit binary operation. Provide an "instr" line that 4105 * specifies an instruction that performs "result = r0 op r1". 4106 * This could be an ARM instruction or a function call. (If the result 4107 * comes back in a register other than r0, you can override "result".) 4108 * 4109 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4110 * vCC (r1). Useful for integer division and modulus. Note that we 4111 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4112 * handles it correctly. 4113 * 4114 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4115 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4116 * mul-float, div-float, rem-float 4117 */ 4118 /* binop vAA, vBB, vCC */ 4119 FETCH(r0, 1) @ r0<- CCBB 4120 mov r9, rINST, lsr #8 @ r9<- AA 4121 mov r3, r0, lsr #8 @ r3<- CC 4122 and r2, r0, #255 @ r2<- BB 4123 GET_VREG(r1, r3) @ r1<- vCC 4124 GET_VREG(r0, r2) @ r0<- vBB 4125 .if 0 4126 cmp r1, #0 @ is second operand zero? 4127 beq common_errDivideByZero 4128 .endif 4129 4130 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4131 @ optional op; may set condition codes 4132 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4133 GET_INST_OPCODE(ip) @ extract opcode from rINST 4134 SET_VREG(r0, r9) @ vAA<- r0 4135 GOTO_OPCODE(ip) @ jump to next instruction 4136 /* 11-14 instructions */ 4137 4138 4139/* ------------------------------ */ 4140 .balign 64 4141.L_OP_DIV_INT: /* 0x93 */ 4142/* File: armv5te/OP_DIV_INT.S */ 4143/* File: armv5te/binop.S */ 4144 /* 4145 * Generic 32-bit binary operation. Provide an "instr" line that 4146 * specifies an instruction that performs "result = r0 op r1". 4147 * This could be an ARM instruction or a function call. (If the result 4148 * comes back in a register other than r0, you can override "result".) 4149 * 4150 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4151 * vCC (r1). Useful for integer division and modulus. Note that we 4152 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4153 * handles it correctly. 4154 * 4155 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4156 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4157 * mul-float, div-float, rem-float 4158 */ 4159 /* binop vAA, vBB, vCC */ 4160 FETCH(r0, 1) @ r0<- CCBB 4161 mov r9, rINST, lsr #8 @ r9<- AA 4162 mov r3, r0, lsr #8 @ r3<- CC 4163 and r2, r0, #255 @ r2<- BB 4164 GET_VREG(r1, r3) @ r1<- vCC 4165 GET_VREG(r0, r2) @ r0<- vBB 4166 .if 1 4167 cmp r1, #0 @ is second operand zero? 4168 beq common_errDivideByZero 4169 .endif 4170 4171 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4172 @ optional op; may set condition codes 4173 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4174 GET_INST_OPCODE(ip) @ extract opcode from rINST 4175 SET_VREG(r0, r9) @ vAA<- r0 4176 GOTO_OPCODE(ip) @ jump to next instruction 4177 /* 11-14 instructions */ 4178 4179 4180/* ------------------------------ */ 4181 .balign 64 4182.L_OP_REM_INT: /* 0x94 */ 4183/* File: armv5te/OP_REM_INT.S */ 4184/* idivmod returns quotient in r0 and remainder in r1 */ 4185/* File: armv5te/binop.S */ 4186 /* 4187 * Generic 32-bit binary operation. Provide an "instr" line that 4188 * specifies an instruction that performs "result = r0 op r1". 4189 * This could be an ARM instruction or a function call. (If the result 4190 * comes back in a register other than r0, you can override "result".) 4191 * 4192 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4193 * vCC (r1). Useful for integer division and modulus. Note that we 4194 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4195 * handles it correctly. 4196 * 4197 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4198 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4199 * mul-float, div-float, rem-float 4200 */ 4201 /* binop vAA, vBB, vCC */ 4202 FETCH(r0, 1) @ r0<- CCBB 4203 mov r9, rINST, lsr #8 @ r9<- AA 4204 mov r3, r0, lsr #8 @ r3<- CC 4205 and r2, r0, #255 @ r2<- BB 4206 GET_VREG(r1, r3) @ r1<- vCC 4207 GET_VREG(r0, r2) @ r0<- vBB 4208 .if 1 4209 cmp r1, #0 @ is second operand zero? 4210 beq common_errDivideByZero 4211 .endif 4212 4213 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4214 @ optional op; may set condition codes 4215 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4216 GET_INST_OPCODE(ip) @ extract opcode from rINST 4217 SET_VREG(r1, r9) @ vAA<- r1 4218 GOTO_OPCODE(ip) @ jump to next instruction 4219 /* 11-14 instructions */ 4220 4221 4222/* ------------------------------ */ 4223 .balign 64 4224.L_OP_AND_INT: /* 0x95 */ 4225/* File: armv5te/OP_AND_INT.S */ 4226/* File: armv5te/binop.S */ 4227 /* 4228 * Generic 32-bit binary operation. Provide an "instr" line that 4229 * specifies an instruction that performs "result = r0 op r1". 4230 * This could be an ARM instruction or a function call. (If the result 4231 * comes back in a register other than r0, you can override "result".) 4232 * 4233 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4234 * vCC (r1). Useful for integer division and modulus. Note that we 4235 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4236 * handles it correctly. 4237 * 4238 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4239 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4240 * mul-float, div-float, rem-float 4241 */ 4242 /* binop vAA, vBB, vCC */ 4243 FETCH(r0, 1) @ r0<- CCBB 4244 mov r9, rINST, lsr #8 @ r9<- AA 4245 mov r3, r0, lsr #8 @ r3<- CC 4246 and r2, r0, #255 @ r2<- BB 4247 GET_VREG(r1, r3) @ r1<- vCC 4248 GET_VREG(r0, r2) @ r0<- vBB 4249 .if 0 4250 cmp r1, #0 @ is second operand zero? 4251 beq common_errDivideByZero 4252 .endif 4253 4254 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4255 @ optional op; may set condition codes 4256 and r0, r0, r1 @ r0<- op, r0-r3 changed 4257 GET_INST_OPCODE(ip) @ extract opcode from rINST 4258 SET_VREG(r0, r9) @ vAA<- r0 4259 GOTO_OPCODE(ip) @ jump to next instruction 4260 /* 11-14 instructions */ 4261 4262 4263/* ------------------------------ */ 4264 .balign 64 4265.L_OP_OR_INT: /* 0x96 */ 4266/* File: armv5te/OP_OR_INT.S */ 4267/* File: armv5te/binop.S */ 4268 /* 4269 * Generic 32-bit binary operation. Provide an "instr" line that 4270 * specifies an instruction that performs "result = r0 op r1". 4271 * This could be an ARM instruction or a function call. (If the result 4272 * comes back in a register other than r0, you can override "result".) 4273 * 4274 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4275 * vCC (r1). Useful for integer division and modulus. Note that we 4276 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4277 * handles it correctly. 4278 * 4279 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4280 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4281 * mul-float, div-float, rem-float 4282 */ 4283 /* binop vAA, vBB, vCC */ 4284 FETCH(r0, 1) @ r0<- CCBB 4285 mov r9, rINST, lsr #8 @ r9<- AA 4286 mov r3, r0, lsr #8 @ r3<- CC 4287 and r2, r0, #255 @ r2<- BB 4288 GET_VREG(r1, r3) @ r1<- vCC 4289 GET_VREG(r0, r2) @ r0<- vBB 4290 .if 0 4291 cmp r1, #0 @ is second operand zero? 4292 beq common_errDivideByZero 4293 .endif 4294 4295 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4296 @ optional op; may set condition codes 4297 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4298 GET_INST_OPCODE(ip) @ extract opcode from rINST 4299 SET_VREG(r0, r9) @ vAA<- r0 4300 GOTO_OPCODE(ip) @ jump to next instruction 4301 /* 11-14 instructions */ 4302 4303 4304/* ------------------------------ */ 4305 .balign 64 4306.L_OP_XOR_INT: /* 0x97 */ 4307/* File: armv5te/OP_XOR_INT.S */ 4308/* File: armv5te/binop.S */ 4309 /* 4310 * Generic 32-bit binary operation. Provide an "instr" line that 4311 * specifies an instruction that performs "result = r0 op r1". 4312 * This could be an ARM instruction or a function call. (If the result 4313 * comes back in a register other than r0, you can override "result".) 4314 * 4315 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4316 * vCC (r1). Useful for integer division and modulus. Note that we 4317 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4318 * handles it correctly. 4319 * 4320 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4321 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4322 * mul-float, div-float, rem-float 4323 */ 4324 /* binop vAA, vBB, vCC */ 4325 FETCH(r0, 1) @ r0<- CCBB 4326 mov r9, rINST, lsr #8 @ r9<- AA 4327 mov r3, r0, lsr #8 @ r3<- CC 4328 and r2, r0, #255 @ r2<- BB 4329 GET_VREG(r1, r3) @ r1<- vCC 4330 GET_VREG(r0, r2) @ r0<- vBB 4331 .if 0 4332 cmp r1, #0 @ is second operand zero? 4333 beq common_errDivideByZero 4334 .endif 4335 4336 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4337 @ optional op; may set condition codes 4338 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4339 GET_INST_OPCODE(ip) @ extract opcode from rINST 4340 SET_VREG(r0, r9) @ vAA<- r0 4341 GOTO_OPCODE(ip) @ jump to next instruction 4342 /* 11-14 instructions */ 4343 4344 4345/* ------------------------------ */ 4346 .balign 64 4347.L_OP_SHL_INT: /* 0x98 */ 4348/* File: armv5te/OP_SHL_INT.S */ 4349/* File: armv5te/binop.S */ 4350 /* 4351 * Generic 32-bit binary operation. Provide an "instr" line that 4352 * specifies an instruction that performs "result = r0 op r1". 4353 * This could be an ARM instruction or a function call. (If the result 4354 * comes back in a register other than r0, you can override "result".) 4355 * 4356 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4357 * vCC (r1). Useful for integer division and modulus. Note that we 4358 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4359 * handles it correctly. 4360 * 4361 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4362 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4363 * mul-float, div-float, rem-float 4364 */ 4365 /* binop vAA, vBB, vCC */ 4366 FETCH(r0, 1) @ r0<- CCBB 4367 mov r9, rINST, lsr #8 @ r9<- AA 4368 mov r3, r0, lsr #8 @ r3<- CC 4369 and r2, r0, #255 @ r2<- BB 4370 GET_VREG(r1, r3) @ r1<- vCC 4371 GET_VREG(r0, r2) @ r0<- vBB 4372 .if 0 4373 cmp r1, #0 @ is second operand zero? 4374 beq common_errDivideByZero 4375 .endif 4376 4377 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4378 and r1, r1, #31 @ optional op; may set condition codes 4379 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4380 GET_INST_OPCODE(ip) @ extract opcode from rINST 4381 SET_VREG(r0, r9) @ vAA<- r0 4382 GOTO_OPCODE(ip) @ jump to next instruction 4383 /* 11-14 instructions */ 4384 4385 4386/* ------------------------------ */ 4387 .balign 64 4388.L_OP_SHR_INT: /* 0x99 */ 4389/* File: armv5te/OP_SHR_INT.S */ 4390/* File: armv5te/binop.S */ 4391 /* 4392 * Generic 32-bit binary operation. Provide an "instr" line that 4393 * specifies an instruction that performs "result = r0 op r1". 4394 * This could be an ARM instruction or a function call. (If the result 4395 * comes back in a register other than r0, you can override "result".) 4396 * 4397 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4398 * vCC (r1). Useful for integer division and modulus. Note that we 4399 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4400 * handles it correctly. 4401 * 4402 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4403 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4404 * mul-float, div-float, rem-float 4405 */ 4406 /* binop vAA, vBB, vCC */ 4407 FETCH(r0, 1) @ r0<- CCBB 4408 mov r9, rINST, lsr #8 @ r9<- AA 4409 mov r3, r0, lsr #8 @ r3<- CC 4410 and r2, r0, #255 @ r2<- BB 4411 GET_VREG(r1, r3) @ r1<- vCC 4412 GET_VREG(r0, r2) @ r0<- vBB 4413 .if 0 4414 cmp r1, #0 @ is second operand zero? 4415 beq common_errDivideByZero 4416 .endif 4417 4418 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4419 and r1, r1, #31 @ optional op; may set condition codes 4420 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4421 GET_INST_OPCODE(ip) @ extract opcode from rINST 4422 SET_VREG(r0, r9) @ vAA<- r0 4423 GOTO_OPCODE(ip) @ jump to next instruction 4424 /* 11-14 instructions */ 4425 4426 4427/* ------------------------------ */ 4428 .balign 64 4429.L_OP_USHR_INT: /* 0x9a */ 4430/* File: armv5te/OP_USHR_INT.S */ 4431/* File: armv5te/binop.S */ 4432 /* 4433 * Generic 32-bit binary operation. Provide an "instr" line that 4434 * specifies an instruction that performs "result = r0 op r1". 4435 * This could be an ARM instruction or a function call. (If the result 4436 * comes back in a register other than r0, you can override "result".) 4437 * 4438 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4439 * vCC (r1). Useful for integer division and modulus. Note that we 4440 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4441 * handles it correctly. 4442 * 4443 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4444 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4445 * mul-float, div-float, rem-float 4446 */ 4447 /* binop vAA, vBB, vCC */ 4448 FETCH(r0, 1) @ r0<- CCBB 4449 mov r9, rINST, lsr #8 @ r9<- AA 4450 mov r3, r0, lsr #8 @ r3<- CC 4451 and r2, r0, #255 @ r2<- BB 4452 GET_VREG(r1, r3) @ r1<- vCC 4453 GET_VREG(r0, r2) @ r0<- vBB 4454 .if 0 4455 cmp r1, #0 @ is second operand zero? 4456 beq common_errDivideByZero 4457 .endif 4458 4459 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4460 and r1, r1, #31 @ optional op; may set condition codes 4461 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4462 GET_INST_OPCODE(ip) @ extract opcode from rINST 4463 SET_VREG(r0, r9) @ vAA<- r0 4464 GOTO_OPCODE(ip) @ jump to next instruction 4465 /* 11-14 instructions */ 4466 4467 4468/* ------------------------------ */ 4469 .balign 64 4470.L_OP_ADD_LONG: /* 0x9b */ 4471/* File: armv5te/OP_ADD_LONG.S */ 4472/* File: armv5te/binopWide.S */ 4473 /* 4474 * Generic 64-bit binary operation. Provide an "instr" line that 4475 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4476 * This could be an ARM instruction or a function call. (If the result 4477 * comes back in a register other than r0, you can override "result".) 4478 * 4479 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4480 * vCC (r1). Useful for integer division and modulus. 4481 * 4482 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4483 * xor-long, add-double, sub-double, mul-double, div-double, 4484 * rem-double 4485 * 4486 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4487 */ 4488 /* binop vAA, vBB, vCC */ 4489 FETCH(r0, 1) @ r0<- CCBB 4490 mov r9, rINST, lsr #8 @ r9<- AA 4491 and r2, r0, #255 @ r2<- BB 4492 mov r3, r0, lsr #8 @ r3<- CC 4493 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4494 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4495 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4496 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4497 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4498 .if 0 4499 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4500 beq common_errDivideByZero 4501 .endif 4502 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4503 4504 adds r0, r0, r2 @ optional op; may set condition codes 4505 adc r1, r1, r3 @ result<- op, r0-r3 changed 4506 GET_INST_OPCODE(ip) @ extract opcode from rINST 4507 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4508 GOTO_OPCODE(ip) @ jump to next instruction 4509 /* 14-17 instructions */ 4510 4511 4512/* ------------------------------ */ 4513 .balign 64 4514.L_OP_SUB_LONG: /* 0x9c */ 4515/* File: armv5te/OP_SUB_LONG.S */ 4516/* File: armv5te/binopWide.S */ 4517 /* 4518 * Generic 64-bit binary operation. Provide an "instr" line that 4519 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4520 * This could be an ARM instruction or a function call. (If the result 4521 * comes back in a register other than r0, you can override "result".) 4522 * 4523 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4524 * vCC (r1). Useful for integer division and modulus. 4525 * 4526 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4527 * xor-long, add-double, sub-double, mul-double, div-double, 4528 * rem-double 4529 * 4530 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4531 */ 4532 /* binop vAA, vBB, vCC */ 4533 FETCH(r0, 1) @ r0<- CCBB 4534 mov r9, rINST, lsr #8 @ r9<- AA 4535 and r2, r0, #255 @ r2<- BB 4536 mov r3, r0, lsr #8 @ r3<- CC 4537 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4538 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4539 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4540 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4541 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4542 .if 0 4543 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4544 beq common_errDivideByZero 4545 .endif 4546 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4547 4548 subs r0, r0, r2 @ optional op; may set condition codes 4549 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4550 GET_INST_OPCODE(ip) @ extract opcode from rINST 4551 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4552 GOTO_OPCODE(ip) @ jump to next instruction 4553 /* 14-17 instructions */ 4554 4555 4556/* ------------------------------ */ 4557 .balign 64 4558.L_OP_MUL_LONG: /* 0x9d */ 4559/* File: armv5te/OP_MUL_LONG.S */ 4560 /* 4561 * Signed 64-bit integer multiply. 4562 * 4563 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4564 * WX 4565 * x YZ 4566 * -------- 4567 * ZW ZX 4568 * YW YX 4569 * 4570 * The low word of the result holds ZX, the high word holds 4571 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4572 * it doesn't fit in the low 64 bits. 4573 * 4574 * Unlike most ARM math operations, multiply instructions have 4575 * restrictions on using the same register more than once (Rd and Rm 4576 * cannot be the same). 4577 */ 4578 /* mul-long vAA, vBB, vCC */ 4579 FETCH(r0, 1) @ r0<- CCBB 4580 and r2, r0, #255 @ r2<- BB 4581 mov r3, r0, lsr #8 @ r3<- CC 4582 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4583 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4584 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4585 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4586 mul ip, r2, r1 @ ip<- ZxW 4587 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4588 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4589 mov r0, rINST, lsr #8 @ r0<- AA 4590 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4591 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4592 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4593 b .LOP_MUL_LONG_finish 4594 4595/* ------------------------------ */ 4596 .balign 64 4597.L_OP_DIV_LONG: /* 0x9e */ 4598/* File: armv5te/OP_DIV_LONG.S */ 4599/* File: armv5te/binopWide.S */ 4600 /* 4601 * Generic 64-bit binary operation. Provide an "instr" line that 4602 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4603 * This could be an ARM instruction or a function call. (If the result 4604 * comes back in a register other than r0, you can override "result".) 4605 * 4606 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4607 * vCC (r1). Useful for integer division and modulus. 4608 * 4609 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4610 * xor-long, add-double, sub-double, mul-double, div-double, 4611 * rem-double 4612 * 4613 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4614 */ 4615 /* binop vAA, vBB, vCC */ 4616 FETCH(r0, 1) @ r0<- CCBB 4617 mov r9, rINST, lsr #8 @ r9<- AA 4618 and r2, r0, #255 @ r2<- BB 4619 mov r3, r0, lsr #8 @ r3<- CC 4620 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4621 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4622 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4623 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4624 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4625 .if 1 4626 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4627 beq common_errDivideByZero 4628 .endif 4629 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4630 4631 @ optional op; may set condition codes 4632 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4633 GET_INST_OPCODE(ip) @ extract opcode from rINST 4634 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4635 GOTO_OPCODE(ip) @ jump to next instruction 4636 /* 14-17 instructions */ 4637 4638 4639/* ------------------------------ */ 4640 .balign 64 4641.L_OP_REM_LONG: /* 0x9f */ 4642/* File: armv5te/OP_REM_LONG.S */ 4643/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4644/* File: armv5te/binopWide.S */ 4645 /* 4646 * Generic 64-bit binary operation. Provide an "instr" line that 4647 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4648 * This could be an ARM instruction or a function call. (If the result 4649 * comes back in a register other than r0, you can override "result".) 4650 * 4651 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4652 * vCC (r1). Useful for integer division and modulus. 4653 * 4654 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4655 * xor-long, add-double, sub-double, mul-double, div-double, 4656 * rem-double 4657 * 4658 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4659 */ 4660 /* binop vAA, vBB, vCC */ 4661 FETCH(r0, 1) @ r0<- CCBB 4662 mov r9, rINST, lsr #8 @ r9<- AA 4663 and r2, r0, #255 @ r2<- BB 4664 mov r3, r0, lsr #8 @ r3<- CC 4665 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4666 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4667 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4668 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4669 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4670 .if 1 4671 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4672 beq common_errDivideByZero 4673 .endif 4674 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4675 4676 @ optional op; may set condition codes 4677 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4678 GET_INST_OPCODE(ip) @ extract opcode from rINST 4679 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4680 GOTO_OPCODE(ip) @ jump to next instruction 4681 /* 14-17 instructions */ 4682 4683 4684/* ------------------------------ */ 4685 .balign 64 4686.L_OP_AND_LONG: /* 0xa0 */ 4687/* File: armv5te/OP_AND_LONG.S */ 4688/* File: armv5te/binopWide.S */ 4689 /* 4690 * Generic 64-bit binary operation. Provide an "instr" line that 4691 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4692 * This could be an ARM instruction or a function call. (If the result 4693 * comes back in a register other than r0, you can override "result".) 4694 * 4695 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4696 * vCC (r1). Useful for integer division and modulus. 4697 * 4698 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4699 * xor-long, add-double, sub-double, mul-double, div-double, 4700 * rem-double 4701 * 4702 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4703 */ 4704 /* binop vAA, vBB, vCC */ 4705 FETCH(r0, 1) @ r0<- CCBB 4706 mov r9, rINST, lsr #8 @ r9<- AA 4707 and r2, r0, #255 @ r2<- BB 4708 mov r3, r0, lsr #8 @ r3<- CC 4709 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4710 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4711 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4712 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4713 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4714 .if 0 4715 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4716 beq common_errDivideByZero 4717 .endif 4718 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4719 4720 and r0, r0, r2 @ optional op; may set condition codes 4721 and r1, r1, r3 @ result<- op, r0-r3 changed 4722 GET_INST_OPCODE(ip) @ extract opcode from rINST 4723 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4724 GOTO_OPCODE(ip) @ jump to next instruction 4725 /* 14-17 instructions */ 4726 4727 4728/* ------------------------------ */ 4729 .balign 64 4730.L_OP_OR_LONG: /* 0xa1 */ 4731/* File: armv5te/OP_OR_LONG.S */ 4732/* File: armv5te/binopWide.S */ 4733 /* 4734 * Generic 64-bit binary operation. Provide an "instr" line that 4735 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4736 * This could be an ARM instruction or a function call. (If the result 4737 * comes back in a register other than r0, you can override "result".) 4738 * 4739 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4740 * vCC (r1). Useful for integer division and modulus. 4741 * 4742 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4743 * xor-long, add-double, sub-double, mul-double, div-double, 4744 * rem-double 4745 * 4746 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4747 */ 4748 /* binop vAA, vBB, vCC */ 4749 FETCH(r0, 1) @ r0<- CCBB 4750 mov r9, rINST, lsr #8 @ r9<- AA 4751 and r2, r0, #255 @ r2<- BB 4752 mov r3, r0, lsr #8 @ r3<- CC 4753 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4754 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4755 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4756 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4757 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4758 .if 0 4759 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4760 beq common_errDivideByZero 4761 .endif 4762 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4763 4764 orr r0, r0, r2 @ optional op; may set condition codes 4765 orr r1, r1, r3 @ result<- op, r0-r3 changed 4766 GET_INST_OPCODE(ip) @ extract opcode from rINST 4767 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4768 GOTO_OPCODE(ip) @ jump to next instruction 4769 /* 14-17 instructions */ 4770 4771 4772/* ------------------------------ */ 4773 .balign 64 4774.L_OP_XOR_LONG: /* 0xa2 */ 4775/* File: armv5te/OP_XOR_LONG.S */ 4776/* File: armv5te/binopWide.S */ 4777 /* 4778 * Generic 64-bit binary operation. Provide an "instr" line that 4779 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4780 * This could be an ARM instruction or a function call. (If the result 4781 * comes back in a register other than r0, you can override "result".) 4782 * 4783 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4784 * vCC (r1). Useful for integer division and modulus. 4785 * 4786 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4787 * xor-long, add-double, sub-double, mul-double, div-double, 4788 * rem-double 4789 * 4790 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4791 */ 4792 /* binop vAA, vBB, vCC */ 4793 FETCH(r0, 1) @ r0<- CCBB 4794 mov r9, rINST, lsr #8 @ r9<- AA 4795 and r2, r0, #255 @ r2<- BB 4796 mov r3, r0, lsr #8 @ r3<- CC 4797 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4798 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4799 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4800 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4801 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4802 .if 0 4803 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4804 beq common_errDivideByZero 4805 .endif 4806 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4807 4808 eor r0, r0, r2 @ optional op; may set condition codes 4809 eor r1, r1, r3 @ result<- op, r0-r3 changed 4810 GET_INST_OPCODE(ip) @ extract opcode from rINST 4811 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4812 GOTO_OPCODE(ip) @ jump to next instruction 4813 /* 14-17 instructions */ 4814 4815 4816/* ------------------------------ */ 4817 .balign 64 4818.L_OP_SHL_LONG: /* 0xa3 */ 4819/* File: armv5te/OP_SHL_LONG.S */ 4820 /* 4821 * Long integer shift. This is different from the generic 32/64-bit 4822 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4823 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4824 * 6 bits of the shift distance. 4825 */ 4826 /* shl-long vAA, vBB, vCC */ 4827 FETCH(r0, 1) @ r0<- CCBB 4828 mov r9, rINST, lsr #8 @ r9<- AA 4829 and r3, r0, #255 @ r3<- BB 4830 mov r0, r0, lsr #8 @ r0<- CC 4831 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4832 GET_VREG(r2, r0) @ r2<- vCC 4833 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4834 and r2, r2, #63 @ r2<- r2 & 0x3f 4835 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4836 4837 mov r1, r1, asl r2 @ r1<- r1 << r2 4838 rsb r3, r2, #32 @ r3<- 32 - r2 4839 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 4840 subs ip, r2, #32 @ ip<- r2 - 32 4841 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 4842 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4843 b .LOP_SHL_LONG_finish 4844 4845/* ------------------------------ */ 4846 .balign 64 4847.L_OP_SHR_LONG: /* 0xa4 */ 4848/* File: armv5te/OP_SHR_LONG.S */ 4849 /* 4850 * Long integer shift. This is different from the generic 32/64-bit 4851 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4852 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4853 * 6 bits of the shift distance. 4854 */ 4855 /* shr-long vAA, vBB, vCC */ 4856 FETCH(r0, 1) @ r0<- CCBB 4857 mov r9, rINST, lsr #8 @ r9<- AA 4858 and r3, r0, #255 @ r3<- BB 4859 mov r0, r0, lsr #8 @ r0<- CC 4860 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4861 GET_VREG(r2, r0) @ r2<- vCC 4862 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4863 and r2, r2, #63 @ r0<- r0 & 0x3f 4864 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4865 4866 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4867 rsb r3, r2, #32 @ r3<- 32 - r2 4868 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4869 subs ip, r2, #32 @ ip<- r2 - 32 4870 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 4871 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4872 b .LOP_SHR_LONG_finish 4873 4874/* ------------------------------ */ 4875 .balign 64 4876.L_OP_USHR_LONG: /* 0xa5 */ 4877/* File: armv5te/OP_USHR_LONG.S */ 4878 /* 4879 * Long integer shift. This is different from the generic 32/64-bit 4880 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4881 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4882 * 6 bits of the shift distance. 4883 */ 4884 /* ushr-long vAA, vBB, vCC */ 4885 FETCH(r0, 1) @ r0<- CCBB 4886 mov r9, rINST, lsr #8 @ r9<- AA 4887 and r3, r0, #255 @ r3<- BB 4888 mov r0, r0, lsr #8 @ r0<- CC 4889 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4890 GET_VREG(r2, r0) @ r2<- vCC 4891 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4892 and r2, r2, #63 @ r0<- r0 & 0x3f 4893 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4894 4895 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4896 rsb r3, r2, #32 @ r3<- 32 - r2 4897 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4898 subs ip, r2, #32 @ ip<- r2 - 32 4899 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 4900 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4901 b .LOP_USHR_LONG_finish 4902 4903/* ------------------------------ */ 4904 .balign 64 4905.L_OP_ADD_FLOAT: /* 0xa6 */ 4906/* File: arm-vfp/OP_ADD_FLOAT.S */ 4907/* File: arm-vfp/fbinop.S */ 4908 /* 4909 * Generic 32-bit floating-point operation. Provide an "instr" line that 4910 * specifies an instruction that performs "s2 = s0 op s1". Because we 4911 * use the "softfp" ABI, this must be an instruction, not a function call. 4912 * 4913 * For: add-float, sub-float, mul-float, div-float 4914 */ 4915 /* floatop vAA, vBB, vCC */ 4916 FETCH(r0, 1) @ r0<- CCBB 4917 mov r9, rINST, lsr #8 @ r9<- AA 4918 mov r3, r0, lsr #8 @ r3<- CC 4919 and r2, r0, #255 @ r2<- BB 4920 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4921 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4922 flds s1, [r3] @ s1<- vCC 4923 flds s0, [r2] @ s0<- vBB 4924 4925 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4926 fadds s2, s0, s1 @ s2<- op 4927 GET_INST_OPCODE(ip) @ extract opcode from rINST 4928 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4929 fsts s2, [r9] @ vAA<- s2 4930 GOTO_OPCODE(ip) @ jump to next instruction 4931 4932 4933/* ------------------------------ */ 4934 .balign 64 4935.L_OP_SUB_FLOAT: /* 0xa7 */ 4936/* File: arm-vfp/OP_SUB_FLOAT.S */ 4937/* File: arm-vfp/fbinop.S */ 4938 /* 4939 * Generic 32-bit floating-point operation. Provide an "instr" line that 4940 * specifies an instruction that performs "s2 = s0 op s1". Because we 4941 * use the "softfp" ABI, this must be an instruction, not a function call. 4942 * 4943 * For: add-float, sub-float, mul-float, div-float 4944 */ 4945 /* floatop vAA, vBB, vCC */ 4946 FETCH(r0, 1) @ r0<- CCBB 4947 mov r9, rINST, lsr #8 @ r9<- AA 4948 mov r3, r0, lsr #8 @ r3<- CC 4949 and r2, r0, #255 @ r2<- BB 4950 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4951 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4952 flds s1, [r3] @ s1<- vCC 4953 flds s0, [r2] @ s0<- vBB 4954 4955 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4956 fsubs s2, s0, s1 @ s2<- op 4957 GET_INST_OPCODE(ip) @ extract opcode from rINST 4958 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4959 fsts s2, [r9] @ vAA<- s2 4960 GOTO_OPCODE(ip) @ jump to next instruction 4961 4962 4963/* ------------------------------ */ 4964 .balign 64 4965.L_OP_MUL_FLOAT: /* 0xa8 */ 4966/* File: arm-vfp/OP_MUL_FLOAT.S */ 4967/* File: arm-vfp/fbinop.S */ 4968 /* 4969 * Generic 32-bit floating-point operation. Provide an "instr" line that 4970 * specifies an instruction that performs "s2 = s0 op s1". Because we 4971 * use the "softfp" ABI, this must be an instruction, not a function call. 4972 * 4973 * For: add-float, sub-float, mul-float, div-float 4974 */ 4975 /* floatop vAA, vBB, vCC */ 4976 FETCH(r0, 1) @ r0<- CCBB 4977 mov r9, rINST, lsr #8 @ r9<- AA 4978 mov r3, r0, lsr #8 @ r3<- CC 4979 and r2, r0, #255 @ r2<- BB 4980 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4981 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4982 flds s1, [r3] @ s1<- vCC 4983 flds s0, [r2] @ s0<- vBB 4984 4985 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4986 fmuls s2, s0, s1 @ s2<- op 4987 GET_INST_OPCODE(ip) @ extract opcode from rINST 4988 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4989 fsts s2, [r9] @ vAA<- s2 4990 GOTO_OPCODE(ip) @ jump to next instruction 4991 4992 4993/* ------------------------------ */ 4994 .balign 64 4995.L_OP_DIV_FLOAT: /* 0xa9 */ 4996/* File: arm-vfp/OP_DIV_FLOAT.S */ 4997/* File: arm-vfp/fbinop.S */ 4998 /* 4999 * Generic 32-bit floating-point operation. Provide an "instr" line that 5000 * specifies an instruction that performs "s2 = s0 op s1". Because we 5001 * use the "softfp" ABI, this must be an instruction, not a function call. 5002 * 5003 * For: add-float, sub-float, mul-float, div-float 5004 */ 5005 /* floatop vAA, vBB, vCC */ 5006 FETCH(r0, 1) @ r0<- CCBB 5007 mov r9, rINST, lsr #8 @ r9<- AA 5008 mov r3, r0, lsr #8 @ r3<- CC 5009 and r2, r0, #255 @ r2<- BB 5010 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5011 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5012 flds s1, [r3] @ s1<- vCC 5013 flds s0, [r2] @ s0<- vBB 5014 5015 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5016 fdivs s2, s0, s1 @ s2<- op 5017 GET_INST_OPCODE(ip) @ extract opcode from rINST 5018 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5019 fsts s2, [r9] @ vAA<- s2 5020 GOTO_OPCODE(ip) @ jump to next instruction 5021 5022 5023/* ------------------------------ */ 5024 .balign 64 5025.L_OP_REM_FLOAT: /* 0xaa */ 5026/* File: armv5te/OP_REM_FLOAT.S */ 5027/* EABI doesn't define a float remainder function, but libm does */ 5028/* File: armv5te/binop.S */ 5029 /* 5030 * Generic 32-bit binary operation. Provide an "instr" line that 5031 * specifies an instruction that performs "result = r0 op r1". 5032 * This could be an ARM instruction or a function call. (If the result 5033 * comes back in a register other than r0, you can override "result".) 5034 * 5035 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5036 * vCC (r1). Useful for integer division and modulus. Note that we 5037 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5038 * handles it correctly. 5039 * 5040 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5041 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5042 * mul-float, div-float, rem-float 5043 */ 5044 /* binop vAA, vBB, vCC */ 5045 FETCH(r0, 1) @ r0<- CCBB 5046 mov r9, rINST, lsr #8 @ r9<- AA 5047 mov r3, r0, lsr #8 @ r3<- CC 5048 and r2, r0, #255 @ r2<- BB 5049 GET_VREG(r1, r3) @ r1<- vCC 5050 GET_VREG(r0, r2) @ r0<- vBB 5051 .if 0 5052 cmp r1, #0 @ is second operand zero? 5053 beq common_errDivideByZero 5054 .endif 5055 5056 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5057 @ optional op; may set condition codes 5058 bl fmodf @ r0<- op, r0-r3 changed 5059 GET_INST_OPCODE(ip) @ extract opcode from rINST 5060 SET_VREG(r0, r9) @ vAA<- r0 5061 GOTO_OPCODE(ip) @ jump to next instruction 5062 /* 11-14 instructions */ 5063 5064 5065/* ------------------------------ */ 5066 .balign 64 5067.L_OP_ADD_DOUBLE: /* 0xab */ 5068/* File: arm-vfp/OP_ADD_DOUBLE.S */ 5069/* File: arm-vfp/fbinopWide.S */ 5070 /* 5071 * Generic 64-bit double-precision floating point binary operation. 5072 * Provide an "instr" line that specifies an instruction that performs 5073 * "d2 = d0 op d1". 5074 * 5075 * for: add-double, sub-double, mul-double, div-double 5076 */ 5077 /* doubleop vAA, vBB, vCC */ 5078 FETCH(r0, 1) @ r0<- CCBB 5079 mov r9, rINST, lsr #8 @ r9<- AA 5080 mov r3, r0, lsr #8 @ r3<- CC 5081 and r2, r0, #255 @ r2<- BB 5082 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5083 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5084 fldd d1, [r3] @ d1<- vCC 5085 fldd d0, [r2] @ d0<- vBB 5086 5087 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5088 faddd d2, d0, d1 @ s2<- op 5089 GET_INST_OPCODE(ip) @ extract opcode from rINST 5090 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5091 fstd d2, [r9] @ vAA<- d2 5092 GOTO_OPCODE(ip) @ jump to next instruction 5093 5094 5095/* ------------------------------ */ 5096 .balign 64 5097.L_OP_SUB_DOUBLE: /* 0xac */ 5098/* File: arm-vfp/OP_SUB_DOUBLE.S */ 5099/* File: arm-vfp/fbinopWide.S */ 5100 /* 5101 * Generic 64-bit double-precision floating point binary operation. 5102 * Provide an "instr" line that specifies an instruction that performs 5103 * "d2 = d0 op d1". 5104 * 5105 * for: add-double, sub-double, mul-double, div-double 5106 */ 5107 /* doubleop vAA, vBB, vCC */ 5108 FETCH(r0, 1) @ r0<- CCBB 5109 mov r9, rINST, lsr #8 @ r9<- AA 5110 mov r3, r0, lsr #8 @ r3<- CC 5111 and r2, r0, #255 @ r2<- BB 5112 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5113 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5114 fldd d1, [r3] @ d1<- vCC 5115 fldd d0, [r2] @ d0<- vBB 5116 5117 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5118 fsubd d2, d0, d1 @ s2<- op 5119 GET_INST_OPCODE(ip) @ extract opcode from rINST 5120 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5121 fstd d2, [r9] @ vAA<- d2 5122 GOTO_OPCODE(ip) @ jump to next instruction 5123 5124 5125/* ------------------------------ */ 5126 .balign 64 5127.L_OP_MUL_DOUBLE: /* 0xad */ 5128/* File: arm-vfp/OP_MUL_DOUBLE.S */ 5129/* File: arm-vfp/fbinopWide.S */ 5130 /* 5131 * Generic 64-bit double-precision floating point binary operation. 5132 * Provide an "instr" line that specifies an instruction that performs 5133 * "d2 = d0 op d1". 5134 * 5135 * for: add-double, sub-double, mul-double, div-double 5136 */ 5137 /* doubleop vAA, vBB, vCC */ 5138 FETCH(r0, 1) @ r0<- CCBB 5139 mov r9, rINST, lsr #8 @ r9<- AA 5140 mov r3, r0, lsr #8 @ r3<- CC 5141 and r2, r0, #255 @ r2<- BB 5142 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5143 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5144 fldd d1, [r3] @ d1<- vCC 5145 fldd d0, [r2] @ d0<- vBB 5146 5147 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5148 fmuld d2, d0, d1 @ s2<- op 5149 GET_INST_OPCODE(ip) @ extract opcode from rINST 5150 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5151 fstd d2, [r9] @ vAA<- d2 5152 GOTO_OPCODE(ip) @ jump to next instruction 5153 5154 5155/* ------------------------------ */ 5156 .balign 64 5157.L_OP_DIV_DOUBLE: /* 0xae */ 5158/* File: arm-vfp/OP_DIV_DOUBLE.S */ 5159/* File: arm-vfp/fbinopWide.S */ 5160 /* 5161 * Generic 64-bit double-precision floating point binary operation. 5162 * Provide an "instr" line that specifies an instruction that performs 5163 * "d2 = d0 op d1". 5164 * 5165 * for: add-double, sub-double, mul-double, div-double 5166 */ 5167 /* doubleop vAA, vBB, vCC */ 5168 FETCH(r0, 1) @ r0<- CCBB 5169 mov r9, rINST, lsr #8 @ r9<- AA 5170 mov r3, r0, lsr #8 @ r3<- CC 5171 and r2, r0, #255 @ r2<- BB 5172 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5173 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5174 fldd d1, [r3] @ d1<- vCC 5175 fldd d0, [r2] @ d0<- vBB 5176 5177 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5178 fdivd d2, d0, d1 @ s2<- op 5179 GET_INST_OPCODE(ip) @ extract opcode from rINST 5180 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5181 fstd d2, [r9] @ vAA<- d2 5182 GOTO_OPCODE(ip) @ jump to next instruction 5183 5184 5185/* ------------------------------ */ 5186 .balign 64 5187.L_OP_REM_DOUBLE: /* 0xaf */ 5188/* File: armv5te/OP_REM_DOUBLE.S */ 5189/* EABI doesn't define a double remainder function, but libm does */ 5190/* File: armv5te/binopWide.S */ 5191 /* 5192 * Generic 64-bit binary operation. Provide an "instr" line that 5193 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5194 * This could be an ARM instruction or a function call. (If the result 5195 * comes back in a register other than r0, you can override "result".) 5196 * 5197 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5198 * vCC (r1). Useful for integer division and modulus. 5199 * 5200 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5201 * xor-long, add-double, sub-double, mul-double, div-double, 5202 * rem-double 5203 * 5204 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5205 */ 5206 /* binop vAA, vBB, vCC */ 5207 FETCH(r0, 1) @ r0<- CCBB 5208 mov r9, rINST, lsr #8 @ r9<- AA 5209 and r2, r0, #255 @ r2<- BB 5210 mov r3, r0, lsr #8 @ r3<- CC 5211 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5212 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5213 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5214 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5215 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5216 .if 0 5217 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5218 beq common_errDivideByZero 5219 .endif 5220 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5221 5222 @ optional op; may set condition codes 5223 bl fmod @ result<- op, r0-r3 changed 5224 GET_INST_OPCODE(ip) @ extract opcode from rINST 5225 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5226 GOTO_OPCODE(ip) @ jump to next instruction 5227 /* 14-17 instructions */ 5228 5229 5230/* ------------------------------ */ 5231 .balign 64 5232.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5233/* File: armv5te/OP_ADD_INT_2ADDR.S */ 5234/* File: armv5te/binop2addr.S */ 5235 /* 5236 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5237 * that specifies an instruction that performs "result = r0 op r1". 5238 * This could be an ARM instruction or a function call. (If the result 5239 * comes back in a register other than r0, you can override "result".) 5240 * 5241 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5242 * vCC (r1). Useful for integer division and modulus. 5243 * 5244 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5245 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5246 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5247 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5248 */ 5249 /* binop/2addr vA, vB */ 5250 mov r9, rINST, lsr #8 @ r9<- A+ 5251 mov r3, rINST, lsr #12 @ r3<- B 5252 and r9, r9, #15 5253 GET_VREG(r1, r3) @ r1<- vB 5254 GET_VREG(r0, r9) @ r0<- vA 5255 .if 0 5256 cmp r1, #0 @ is second operand zero? 5257 beq common_errDivideByZero 5258 .endif 5259 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5260 5261 @ optional op; may set condition codes 5262 add r0, r0, r1 @ r0<- op, r0-r3 changed 5263 GET_INST_OPCODE(ip) @ extract opcode from rINST 5264 SET_VREG(r0, r9) @ vAA<- r0 5265 GOTO_OPCODE(ip) @ jump to next instruction 5266 /* 10-13 instructions */ 5267 5268 5269/* ------------------------------ */ 5270 .balign 64 5271.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5272/* File: armv5te/OP_SUB_INT_2ADDR.S */ 5273/* File: armv5te/binop2addr.S */ 5274 /* 5275 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5276 * that specifies an instruction that performs "result = r0 op r1". 5277 * This could be an ARM instruction or a function call. (If the result 5278 * comes back in a register other than r0, you can override "result".) 5279 * 5280 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5281 * vCC (r1). Useful for integer division and modulus. 5282 * 5283 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5284 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5285 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5286 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5287 */ 5288 /* binop/2addr vA, vB */ 5289 mov r9, rINST, lsr #8 @ r9<- A+ 5290 mov r3, rINST, lsr #12 @ r3<- B 5291 and r9, r9, #15 5292 GET_VREG(r1, r3) @ r1<- vB 5293 GET_VREG(r0, r9) @ r0<- vA 5294 .if 0 5295 cmp r1, #0 @ is second operand zero? 5296 beq common_errDivideByZero 5297 .endif 5298 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5299 5300 @ optional op; may set condition codes 5301 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5302 GET_INST_OPCODE(ip) @ extract opcode from rINST 5303 SET_VREG(r0, r9) @ vAA<- r0 5304 GOTO_OPCODE(ip) @ jump to next instruction 5305 /* 10-13 instructions */ 5306 5307 5308/* ------------------------------ */ 5309 .balign 64 5310.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5311/* File: armv5te/OP_MUL_INT_2ADDR.S */ 5312/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5313/* File: armv5te/binop2addr.S */ 5314 /* 5315 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5316 * that specifies an instruction that performs "result = r0 op r1". 5317 * This could be an ARM instruction or a function call. (If the result 5318 * comes back in a register other than r0, you can override "result".) 5319 * 5320 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5321 * vCC (r1). Useful for integer division and modulus. 5322 * 5323 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5324 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5325 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5326 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5327 */ 5328 /* binop/2addr vA, vB */ 5329 mov r9, rINST, lsr #8 @ r9<- A+ 5330 mov r3, rINST, lsr #12 @ r3<- B 5331 and r9, r9, #15 5332 GET_VREG(r1, r3) @ r1<- vB 5333 GET_VREG(r0, r9) @ r0<- vA 5334 .if 0 5335 cmp r1, #0 @ is second operand zero? 5336 beq common_errDivideByZero 5337 .endif 5338 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5339 5340 @ optional op; may set condition codes 5341 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5342 GET_INST_OPCODE(ip) @ extract opcode from rINST 5343 SET_VREG(r0, r9) @ vAA<- r0 5344 GOTO_OPCODE(ip) @ jump to next instruction 5345 /* 10-13 instructions */ 5346 5347 5348/* ------------------------------ */ 5349 .balign 64 5350.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5351/* File: armv5te/OP_DIV_INT_2ADDR.S */ 5352/* File: armv5te/binop2addr.S */ 5353 /* 5354 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5355 * that specifies an instruction that performs "result = r0 op r1". 5356 * This could be an ARM instruction or a function call. (If the result 5357 * comes back in a register other than r0, you can override "result".) 5358 * 5359 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5360 * vCC (r1). Useful for integer division and modulus. 5361 * 5362 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5363 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5364 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5365 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5366 */ 5367 /* binop/2addr vA, vB */ 5368 mov r9, rINST, lsr #8 @ r9<- A+ 5369 mov r3, rINST, lsr #12 @ r3<- B 5370 and r9, r9, #15 5371 GET_VREG(r1, r3) @ r1<- vB 5372 GET_VREG(r0, r9) @ r0<- vA 5373 .if 1 5374 cmp r1, #0 @ is second operand zero? 5375 beq common_errDivideByZero 5376 .endif 5377 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5378 5379 @ optional op; may set condition codes 5380 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5381 GET_INST_OPCODE(ip) @ extract opcode from rINST 5382 SET_VREG(r0, r9) @ vAA<- r0 5383 GOTO_OPCODE(ip) @ jump to next instruction 5384 /* 10-13 instructions */ 5385 5386 5387/* ------------------------------ */ 5388 .balign 64 5389.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5390/* File: armv5te/OP_REM_INT_2ADDR.S */ 5391/* idivmod returns quotient in r0 and remainder in r1 */ 5392/* File: armv5te/binop2addr.S */ 5393 /* 5394 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5395 * that specifies an instruction that performs "result = r0 op r1". 5396 * This could be an ARM instruction or a function call. (If the result 5397 * comes back in a register other than r0, you can override "result".) 5398 * 5399 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5400 * vCC (r1). Useful for integer division and modulus. 5401 * 5402 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5403 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5404 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5405 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5406 */ 5407 /* binop/2addr vA, vB */ 5408 mov r9, rINST, lsr #8 @ r9<- A+ 5409 mov r3, rINST, lsr #12 @ r3<- B 5410 and r9, r9, #15 5411 GET_VREG(r1, r3) @ r1<- vB 5412 GET_VREG(r0, r9) @ r0<- vA 5413 .if 1 5414 cmp r1, #0 @ is second operand zero? 5415 beq common_errDivideByZero 5416 .endif 5417 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5418 5419 @ optional op; may set condition codes 5420 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5421 GET_INST_OPCODE(ip) @ extract opcode from rINST 5422 SET_VREG(r1, r9) @ vAA<- r1 5423 GOTO_OPCODE(ip) @ jump to next instruction 5424 /* 10-13 instructions */ 5425 5426 5427/* ------------------------------ */ 5428 .balign 64 5429.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5430/* File: armv5te/OP_AND_INT_2ADDR.S */ 5431/* File: armv5te/binop2addr.S */ 5432 /* 5433 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5434 * that specifies an instruction that performs "result = r0 op r1". 5435 * This could be an ARM instruction or a function call. (If the result 5436 * comes back in a register other than r0, you can override "result".) 5437 * 5438 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5439 * vCC (r1). Useful for integer division and modulus. 5440 * 5441 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5442 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5443 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5444 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5445 */ 5446 /* binop/2addr vA, vB */ 5447 mov r9, rINST, lsr #8 @ r9<- A+ 5448 mov r3, rINST, lsr #12 @ r3<- B 5449 and r9, r9, #15 5450 GET_VREG(r1, r3) @ r1<- vB 5451 GET_VREG(r0, r9) @ r0<- vA 5452 .if 0 5453 cmp r1, #0 @ is second operand zero? 5454 beq common_errDivideByZero 5455 .endif 5456 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5457 5458 @ optional op; may set condition codes 5459 and r0, r0, r1 @ r0<- op, r0-r3 changed 5460 GET_INST_OPCODE(ip) @ extract opcode from rINST 5461 SET_VREG(r0, r9) @ vAA<- r0 5462 GOTO_OPCODE(ip) @ jump to next instruction 5463 /* 10-13 instructions */ 5464 5465 5466/* ------------------------------ */ 5467 .balign 64 5468.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5469/* File: armv5te/OP_OR_INT_2ADDR.S */ 5470/* File: armv5te/binop2addr.S */ 5471 /* 5472 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5473 * that specifies an instruction that performs "result = r0 op r1". 5474 * This could be an ARM instruction or a function call. (If the result 5475 * comes back in a register other than r0, you can override "result".) 5476 * 5477 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5478 * vCC (r1). Useful for integer division and modulus. 5479 * 5480 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5481 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5482 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5483 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5484 */ 5485 /* binop/2addr vA, vB */ 5486 mov r9, rINST, lsr #8 @ r9<- A+ 5487 mov r3, rINST, lsr #12 @ r3<- B 5488 and r9, r9, #15 5489 GET_VREG(r1, r3) @ r1<- vB 5490 GET_VREG(r0, r9) @ r0<- vA 5491 .if 0 5492 cmp r1, #0 @ is second operand zero? 5493 beq common_errDivideByZero 5494 .endif 5495 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5496 5497 @ optional op; may set condition codes 5498 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5499 GET_INST_OPCODE(ip) @ extract opcode from rINST 5500 SET_VREG(r0, r9) @ vAA<- r0 5501 GOTO_OPCODE(ip) @ jump to next instruction 5502 /* 10-13 instructions */ 5503 5504 5505/* ------------------------------ */ 5506 .balign 64 5507.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5508/* File: armv5te/OP_XOR_INT_2ADDR.S */ 5509/* File: armv5te/binop2addr.S */ 5510 /* 5511 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5512 * that specifies an instruction that performs "result = r0 op r1". 5513 * This could be an ARM instruction or a function call. (If the result 5514 * comes back in a register other than r0, you can override "result".) 5515 * 5516 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5517 * vCC (r1). Useful for integer division and modulus. 5518 * 5519 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5520 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5521 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5522 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5523 */ 5524 /* binop/2addr vA, vB */ 5525 mov r9, rINST, lsr #8 @ r9<- A+ 5526 mov r3, rINST, lsr #12 @ r3<- B 5527 and r9, r9, #15 5528 GET_VREG(r1, r3) @ r1<- vB 5529 GET_VREG(r0, r9) @ r0<- vA 5530 .if 0 5531 cmp r1, #0 @ is second operand zero? 5532 beq common_errDivideByZero 5533 .endif 5534 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5535 5536 @ optional op; may set condition codes 5537 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5538 GET_INST_OPCODE(ip) @ extract opcode from rINST 5539 SET_VREG(r0, r9) @ vAA<- r0 5540 GOTO_OPCODE(ip) @ jump to next instruction 5541 /* 10-13 instructions */ 5542 5543 5544/* ------------------------------ */ 5545 .balign 64 5546.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5547/* File: armv5te/OP_SHL_INT_2ADDR.S */ 5548/* File: armv5te/binop2addr.S */ 5549 /* 5550 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5551 * that specifies an instruction that performs "result = r0 op r1". 5552 * This could be an ARM instruction or a function call. (If the result 5553 * comes back in a register other than r0, you can override "result".) 5554 * 5555 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5556 * vCC (r1). Useful for integer division and modulus. 5557 * 5558 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5559 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5560 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5561 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5562 */ 5563 /* binop/2addr vA, vB */ 5564 mov r9, rINST, lsr #8 @ r9<- A+ 5565 mov r3, rINST, lsr #12 @ r3<- B 5566 and r9, r9, #15 5567 GET_VREG(r1, r3) @ r1<- vB 5568 GET_VREG(r0, r9) @ r0<- vA 5569 .if 0 5570 cmp r1, #0 @ is second operand zero? 5571 beq common_errDivideByZero 5572 .endif 5573 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5574 5575 and r1, r1, #31 @ optional op; may set condition codes 5576 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5577 GET_INST_OPCODE(ip) @ extract opcode from rINST 5578 SET_VREG(r0, r9) @ vAA<- r0 5579 GOTO_OPCODE(ip) @ jump to next instruction 5580 /* 10-13 instructions */ 5581 5582 5583/* ------------------------------ */ 5584 .balign 64 5585.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5586/* File: armv5te/OP_SHR_INT_2ADDR.S */ 5587/* File: armv5te/binop2addr.S */ 5588 /* 5589 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5590 * that specifies an instruction that performs "result = r0 op r1". 5591 * This could be an ARM instruction or a function call. (If the result 5592 * comes back in a register other than r0, you can override "result".) 5593 * 5594 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5595 * vCC (r1). Useful for integer division and modulus. 5596 * 5597 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5598 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5599 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5600 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5601 */ 5602 /* binop/2addr vA, vB */ 5603 mov r9, rINST, lsr #8 @ r9<- A+ 5604 mov r3, rINST, lsr #12 @ r3<- B 5605 and r9, r9, #15 5606 GET_VREG(r1, r3) @ r1<- vB 5607 GET_VREG(r0, r9) @ r0<- vA 5608 .if 0 5609 cmp r1, #0 @ is second operand zero? 5610 beq common_errDivideByZero 5611 .endif 5612 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5613 5614 and r1, r1, #31 @ optional op; may set condition codes 5615 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5616 GET_INST_OPCODE(ip) @ extract opcode from rINST 5617 SET_VREG(r0, r9) @ vAA<- r0 5618 GOTO_OPCODE(ip) @ jump to next instruction 5619 /* 10-13 instructions */ 5620 5621 5622/* ------------------------------ */ 5623 .balign 64 5624.L_OP_USHR_INT_2ADDR: /* 0xba */ 5625/* File: armv5te/OP_USHR_INT_2ADDR.S */ 5626/* File: armv5te/binop2addr.S */ 5627 /* 5628 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5629 * that specifies an instruction that performs "result = r0 op r1". 5630 * This could be an ARM instruction or a function call. (If the result 5631 * comes back in a register other than r0, you can override "result".) 5632 * 5633 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5634 * vCC (r1). Useful for integer division and modulus. 5635 * 5636 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5637 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5638 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5639 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5640 */ 5641 /* binop/2addr vA, vB */ 5642 mov r9, rINST, lsr #8 @ r9<- A+ 5643 mov r3, rINST, lsr #12 @ r3<- B 5644 and r9, r9, #15 5645 GET_VREG(r1, r3) @ r1<- vB 5646 GET_VREG(r0, r9) @ r0<- vA 5647 .if 0 5648 cmp r1, #0 @ is second operand zero? 5649 beq common_errDivideByZero 5650 .endif 5651 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5652 5653 and r1, r1, #31 @ optional op; may set condition codes 5654 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5655 GET_INST_OPCODE(ip) @ extract opcode from rINST 5656 SET_VREG(r0, r9) @ vAA<- r0 5657 GOTO_OPCODE(ip) @ jump to next instruction 5658 /* 10-13 instructions */ 5659 5660 5661/* ------------------------------ */ 5662 .balign 64 5663.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5664/* File: armv5te/OP_ADD_LONG_2ADDR.S */ 5665/* File: armv5te/binopWide2addr.S */ 5666 /* 5667 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5668 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5669 * This could be an ARM instruction or a function call. (If the result 5670 * comes back in a register other than r0, you can override "result".) 5671 * 5672 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5673 * vCC (r1). Useful for integer division and modulus. 5674 * 5675 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5676 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5677 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5678 * rem-double/2addr 5679 */ 5680 /* binop/2addr vA, vB */ 5681 mov r9, rINST, lsr #8 @ r9<- A+ 5682 mov r1, rINST, lsr #12 @ r1<- B 5683 and r9, r9, #15 5684 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5685 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5686 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5687 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5688 .if 0 5689 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5690 beq common_errDivideByZero 5691 .endif 5692 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5693 5694 adds r0, r0, r2 @ optional op; may set condition codes 5695 adc r1, r1, r3 @ result<- op, r0-r3 changed 5696 GET_INST_OPCODE(ip) @ extract opcode from rINST 5697 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5698 GOTO_OPCODE(ip) @ jump to next instruction 5699 /* 12-15 instructions */ 5700 5701 5702/* ------------------------------ */ 5703 .balign 64 5704.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5705/* File: armv5te/OP_SUB_LONG_2ADDR.S */ 5706/* File: armv5te/binopWide2addr.S */ 5707 /* 5708 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5709 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5710 * This could be an ARM instruction or a function call. (If the result 5711 * comes back in a register other than r0, you can override "result".) 5712 * 5713 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5714 * vCC (r1). Useful for integer division and modulus. 5715 * 5716 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5717 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5718 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5719 * rem-double/2addr 5720 */ 5721 /* binop/2addr vA, vB */ 5722 mov r9, rINST, lsr #8 @ r9<- A+ 5723 mov r1, rINST, lsr #12 @ r1<- B 5724 and r9, r9, #15 5725 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5726 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5727 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5728 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5729 .if 0 5730 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5731 beq common_errDivideByZero 5732 .endif 5733 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5734 5735 subs r0, r0, r2 @ optional op; may set condition codes 5736 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5737 GET_INST_OPCODE(ip) @ extract opcode from rINST 5738 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5739 GOTO_OPCODE(ip) @ jump to next instruction 5740 /* 12-15 instructions */ 5741 5742 5743/* ------------------------------ */ 5744 .balign 64 5745.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 5746/* File: armv5te/OP_MUL_LONG_2ADDR.S */ 5747 /* 5748 * Signed 64-bit integer multiply, "/2addr" version. 5749 * 5750 * See OP_MUL_LONG for an explanation. 5751 * 5752 * We get a little tight on registers, so to avoid looking up &fp[A] 5753 * again we stuff it into rINST. 5754 */ 5755 /* mul-long/2addr vA, vB */ 5756 mov r9, rINST, lsr #8 @ r9<- A+ 5757 mov r1, rINST, lsr #12 @ r1<- B 5758 and r9, r9, #15 5759 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5760 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 5761 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5762 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 5763 mul ip, r2, r1 @ ip<- ZxW 5764 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 5765 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 5766 mov r0, rINST @ r0<- &fp[A] (free up rINST) 5767 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5768 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 5769 GET_INST_OPCODE(ip) @ extract opcode from rINST 5770 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 5771 GOTO_OPCODE(ip) @ jump to next instruction 5772 5773/* ------------------------------ */ 5774 .balign 64 5775.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 5776/* File: armv5te/OP_DIV_LONG_2ADDR.S */ 5777/* File: armv5te/binopWide2addr.S */ 5778 /* 5779 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5780 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5781 * This could be an ARM instruction or a function call. (If the result 5782 * comes back in a register other than r0, you can override "result".) 5783 * 5784 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5785 * vCC (r1). Useful for integer division and modulus. 5786 * 5787 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5788 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5789 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5790 * rem-double/2addr 5791 */ 5792 /* binop/2addr vA, vB */ 5793 mov r9, rINST, lsr #8 @ r9<- A+ 5794 mov r1, rINST, lsr #12 @ r1<- B 5795 and r9, r9, #15 5796 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5797 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5798 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5799 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5800 .if 1 5801 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5802 beq common_errDivideByZero 5803 .endif 5804 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5805 5806 @ optional op; may set condition codes 5807 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5808 GET_INST_OPCODE(ip) @ extract opcode from rINST 5809 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5810 GOTO_OPCODE(ip) @ jump to next instruction 5811 /* 12-15 instructions */ 5812 5813 5814/* ------------------------------ */ 5815 .balign 64 5816.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5817/* File: armv5te/OP_REM_LONG_2ADDR.S */ 5818/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 5819/* File: armv5te/binopWide2addr.S */ 5820 /* 5821 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5822 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5823 * This could be an ARM instruction or a function call. (If the result 5824 * comes back in a register other than r0, you can override "result".) 5825 * 5826 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5827 * vCC (r1). Useful for integer division and modulus. 5828 * 5829 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5830 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5831 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5832 * rem-double/2addr 5833 */ 5834 /* binop/2addr vA, vB */ 5835 mov r9, rINST, lsr #8 @ r9<- A+ 5836 mov r1, rINST, lsr #12 @ r1<- B 5837 and r9, r9, #15 5838 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5839 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5840 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5841 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5842 .if 1 5843 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5844 beq common_errDivideByZero 5845 .endif 5846 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5847 5848 @ optional op; may set condition codes 5849 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5850 GET_INST_OPCODE(ip) @ extract opcode from rINST 5851 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 5852 GOTO_OPCODE(ip) @ jump to next instruction 5853 /* 12-15 instructions */ 5854 5855 5856/* ------------------------------ */ 5857 .balign 64 5858.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 5859/* File: armv5te/OP_AND_LONG_2ADDR.S */ 5860/* File: armv5te/binopWide2addr.S */ 5861 /* 5862 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5863 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5864 * This could be an ARM instruction or a function call. (If the result 5865 * comes back in a register other than r0, you can override "result".) 5866 * 5867 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5868 * vCC (r1). Useful for integer division and modulus. 5869 * 5870 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5871 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5872 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5873 * rem-double/2addr 5874 */ 5875 /* binop/2addr vA, vB */ 5876 mov r9, rINST, lsr #8 @ r9<- A+ 5877 mov r1, rINST, lsr #12 @ r1<- B 5878 and r9, r9, #15 5879 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5880 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5881 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5882 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5883 .if 0 5884 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5885 beq common_errDivideByZero 5886 .endif 5887 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5888 5889 and r0, r0, r2 @ optional op; may set condition codes 5890 and r1, r1, r3 @ result<- op, r0-r3 changed 5891 GET_INST_OPCODE(ip) @ extract opcode from rINST 5892 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5893 GOTO_OPCODE(ip) @ jump to next instruction 5894 /* 12-15 instructions */ 5895 5896 5897/* ------------------------------ */ 5898 .balign 64 5899.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 5900/* File: armv5te/OP_OR_LONG_2ADDR.S */ 5901/* File: armv5te/binopWide2addr.S */ 5902 /* 5903 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5904 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5905 * This could be an ARM instruction or a function call. (If the result 5906 * comes back in a register other than r0, you can override "result".) 5907 * 5908 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5909 * vCC (r1). Useful for integer division and modulus. 5910 * 5911 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5912 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5913 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5914 * rem-double/2addr 5915 */ 5916 /* binop/2addr vA, vB */ 5917 mov r9, rINST, lsr #8 @ r9<- A+ 5918 mov r1, rINST, lsr #12 @ r1<- B 5919 and r9, r9, #15 5920 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5921 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5922 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5923 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5924 .if 0 5925 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5926 beq common_errDivideByZero 5927 .endif 5928 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5929 5930 orr r0, r0, r2 @ optional op; may set condition codes 5931 orr r1, r1, r3 @ result<- op, r0-r3 changed 5932 GET_INST_OPCODE(ip) @ extract opcode from rINST 5933 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5934 GOTO_OPCODE(ip) @ jump to next instruction 5935 /* 12-15 instructions */ 5936 5937 5938/* ------------------------------ */ 5939 .balign 64 5940.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 5941/* File: armv5te/OP_XOR_LONG_2ADDR.S */ 5942/* File: armv5te/binopWide2addr.S */ 5943 /* 5944 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5945 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5946 * This could be an ARM instruction or a function call. (If the result 5947 * comes back in a register other than r0, you can override "result".) 5948 * 5949 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5950 * vCC (r1). Useful for integer division and modulus. 5951 * 5952 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5953 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5954 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5955 * rem-double/2addr 5956 */ 5957 /* binop/2addr vA, vB */ 5958 mov r9, rINST, lsr #8 @ r9<- A+ 5959 mov r1, rINST, lsr #12 @ r1<- B 5960 and r9, r9, #15 5961 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5962 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5963 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5964 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5965 .if 0 5966 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5967 beq common_errDivideByZero 5968 .endif 5969 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5970 5971 eor r0, r0, r2 @ optional op; may set condition codes 5972 eor r1, r1, r3 @ result<- op, r0-r3 changed 5973 GET_INST_OPCODE(ip) @ extract opcode from rINST 5974 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5975 GOTO_OPCODE(ip) @ jump to next instruction 5976 /* 12-15 instructions */ 5977 5978 5979/* ------------------------------ */ 5980 .balign 64 5981.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 5982/* File: armv5te/OP_SHL_LONG_2ADDR.S */ 5983 /* 5984 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 5985 * 32-bit shift distance. 5986 */ 5987 /* shl-long/2addr vA, vB */ 5988 mov r9, rINST, lsr #8 @ r9<- A+ 5989 mov r3, rINST, lsr #12 @ r3<- B 5990 and r9, r9, #15 5991 GET_VREG(r2, r3) @ r2<- vB 5992 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5993 and r2, r2, #63 @ r2<- r2 & 0x3f 5994 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5995 5996 mov r1, r1, asl r2 @ r1<- r1 << r2 5997 rsb r3, r2, #32 @ r3<- 32 - r2 5998 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 5999 subs ip, r2, #32 @ ip<- r2 - 32 6000 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6001 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 6002 mov r0, r0, asl r2 @ r0<- r0 << r2 6003 b .LOP_SHL_LONG_2ADDR_finish 6004 6005/* ------------------------------ */ 6006 .balign 64 6007.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 6008/* File: armv5te/OP_SHR_LONG_2ADDR.S */ 6009 /* 6010 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6011 * 32-bit shift distance. 6012 */ 6013 /* shr-long/2addr vA, vB */ 6014 mov r9, rINST, lsr #8 @ r9<- A+ 6015 mov r3, rINST, lsr #12 @ r3<- B 6016 and r9, r9, #15 6017 GET_VREG(r2, r3) @ r2<- vB 6018 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6019 and r2, r2, #63 @ r2<- r2 & 0x3f 6020 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6021 6022 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6023 rsb r3, r2, #32 @ r3<- 32 - r2 6024 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6025 subs ip, r2, #32 @ ip<- r2 - 32 6026 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6027 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6028 mov r1, r1, asr r2 @ r1<- r1 >> r2 6029 b .LOP_SHR_LONG_2ADDR_finish 6030 6031/* ------------------------------ */ 6032 .balign 64 6033.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6034/* File: armv5te/OP_USHR_LONG_2ADDR.S */ 6035 /* 6036 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6037 * 32-bit shift distance. 6038 */ 6039 /* ushr-long/2addr vA, vB */ 6040 mov r9, rINST, lsr #8 @ r9<- A+ 6041 mov r3, rINST, lsr #12 @ r3<- B 6042 and r9, r9, #15 6043 GET_VREG(r2, r3) @ r2<- vB 6044 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6045 and r2, r2, #63 @ r2<- r2 & 0x3f 6046 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6047 6048 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6049 rsb r3, r2, #32 @ r3<- 32 - r2 6050 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6051 subs ip, r2, #32 @ ip<- r2 - 32 6052 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6053 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6054 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6055 b .LOP_USHR_LONG_2ADDR_finish 6056 6057/* ------------------------------ */ 6058 .balign 64 6059.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6060/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */ 6061/* File: arm-vfp/fbinop2addr.S */ 6062 /* 6063 * Generic 32-bit floating point "/2addr" binary operation. Provide 6064 * an "instr" line that specifies an instruction that performs 6065 * "s2 = s0 op s1". 6066 * 6067 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6068 */ 6069 /* binop/2addr vA, vB */ 6070 mov r3, rINST, lsr #12 @ r3<- B 6071 mov r9, rINST, lsr #8 @ r9<- A+ 6072 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6073 and r9, r9, #15 @ r9<- A 6074 flds s1, [r3] @ s1<- vB 6075 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6076 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6077 flds s0, [r9] @ s0<- vA 6078 6079 fadds s2, s0, s1 @ s2<- op 6080 GET_INST_OPCODE(ip) @ extract opcode from rINST 6081 fsts s2, [r9] @ vAA<- s2 6082 GOTO_OPCODE(ip) @ jump to next instruction 6083 6084 6085/* ------------------------------ */ 6086 .balign 64 6087.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6088/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */ 6089/* File: arm-vfp/fbinop2addr.S */ 6090 /* 6091 * Generic 32-bit floating point "/2addr" binary operation. Provide 6092 * an "instr" line that specifies an instruction that performs 6093 * "s2 = s0 op s1". 6094 * 6095 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6096 */ 6097 /* binop/2addr vA, vB */ 6098 mov r3, rINST, lsr #12 @ r3<- B 6099 mov r9, rINST, lsr #8 @ r9<- A+ 6100 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6101 and r9, r9, #15 @ r9<- A 6102 flds s1, [r3] @ s1<- vB 6103 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6104 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6105 flds s0, [r9] @ s0<- vA 6106 6107 fsubs s2, s0, s1 @ s2<- op 6108 GET_INST_OPCODE(ip) @ extract opcode from rINST 6109 fsts s2, [r9] @ vAA<- s2 6110 GOTO_OPCODE(ip) @ jump to next instruction 6111 6112 6113/* ------------------------------ */ 6114 .balign 64 6115.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6116/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */ 6117/* File: arm-vfp/fbinop2addr.S */ 6118 /* 6119 * Generic 32-bit floating point "/2addr" binary operation. Provide 6120 * an "instr" line that specifies an instruction that performs 6121 * "s2 = s0 op s1". 6122 * 6123 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6124 */ 6125 /* binop/2addr vA, vB */ 6126 mov r3, rINST, lsr #12 @ r3<- B 6127 mov r9, rINST, lsr #8 @ r9<- A+ 6128 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6129 and r9, r9, #15 @ r9<- A 6130 flds s1, [r3] @ s1<- vB 6131 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6132 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6133 flds s0, [r9] @ s0<- vA 6134 6135 fmuls s2, s0, s1 @ s2<- op 6136 GET_INST_OPCODE(ip) @ extract opcode from rINST 6137 fsts s2, [r9] @ vAA<- s2 6138 GOTO_OPCODE(ip) @ jump to next instruction 6139 6140 6141/* ------------------------------ */ 6142 .balign 64 6143.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6144/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */ 6145/* File: arm-vfp/fbinop2addr.S */ 6146 /* 6147 * Generic 32-bit floating point "/2addr" binary operation. Provide 6148 * an "instr" line that specifies an instruction that performs 6149 * "s2 = s0 op s1". 6150 * 6151 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6152 */ 6153 /* binop/2addr vA, vB */ 6154 mov r3, rINST, lsr #12 @ r3<- B 6155 mov r9, rINST, lsr #8 @ r9<- A+ 6156 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6157 and r9, r9, #15 @ r9<- A 6158 flds s1, [r3] @ s1<- vB 6159 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6160 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6161 flds s0, [r9] @ s0<- vA 6162 6163 fdivs s2, s0, s1 @ s2<- op 6164 GET_INST_OPCODE(ip) @ extract opcode from rINST 6165 fsts s2, [r9] @ vAA<- s2 6166 GOTO_OPCODE(ip) @ jump to next instruction 6167 6168 6169/* ------------------------------ */ 6170 .balign 64 6171.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6172/* File: armv5te/OP_REM_FLOAT_2ADDR.S */ 6173/* EABI doesn't define a float remainder function, but libm does */ 6174/* File: armv5te/binop2addr.S */ 6175 /* 6176 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6177 * that specifies an instruction that performs "result = r0 op r1". 6178 * This could be an ARM instruction or a function call. (If the result 6179 * comes back in a register other than r0, you can override "result".) 6180 * 6181 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6182 * vCC (r1). Useful for integer division and modulus. 6183 * 6184 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6185 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6186 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6187 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6188 */ 6189 /* binop/2addr vA, vB */ 6190 mov r9, rINST, lsr #8 @ r9<- A+ 6191 mov r3, rINST, lsr #12 @ r3<- B 6192 and r9, r9, #15 6193 GET_VREG(r1, r3) @ r1<- vB 6194 GET_VREG(r0, r9) @ r0<- vA 6195 .if 0 6196 cmp r1, #0 @ is second operand zero? 6197 beq common_errDivideByZero 6198 .endif 6199 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6200 6201 @ optional op; may set condition codes 6202 bl fmodf @ r0<- op, r0-r3 changed 6203 GET_INST_OPCODE(ip) @ extract opcode from rINST 6204 SET_VREG(r0, r9) @ vAA<- r0 6205 GOTO_OPCODE(ip) @ jump to next instruction 6206 /* 10-13 instructions */ 6207 6208 6209/* ------------------------------ */ 6210 .balign 64 6211.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6212/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */ 6213/* File: arm-vfp/fbinopWide2addr.S */ 6214 /* 6215 * Generic 64-bit floating point "/2addr" binary operation. Provide 6216 * an "instr" line that specifies an instruction that performs 6217 * "d2 = d0 op d1". 6218 * 6219 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6220 * div-double/2addr 6221 */ 6222 /* binop/2addr vA, vB */ 6223 mov r3, rINST, lsr #12 @ r3<- B 6224 mov r9, rINST, lsr #8 @ r9<- A+ 6225 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6226 and r9, r9, #15 @ r9<- A 6227 fldd d1, [r3] @ d1<- vB 6228 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6229 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6230 fldd d0, [r9] @ d0<- vA 6231 6232 faddd d2, d0, d1 @ d2<- op 6233 GET_INST_OPCODE(ip) @ extract opcode from rINST 6234 fstd d2, [r9] @ vAA<- d2 6235 GOTO_OPCODE(ip) @ jump to next instruction 6236 6237 6238/* ------------------------------ */ 6239 .balign 64 6240.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6241/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */ 6242/* File: arm-vfp/fbinopWide2addr.S */ 6243 /* 6244 * Generic 64-bit floating point "/2addr" binary operation. Provide 6245 * an "instr" line that specifies an instruction that performs 6246 * "d2 = d0 op d1". 6247 * 6248 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6249 * div-double/2addr 6250 */ 6251 /* binop/2addr vA, vB */ 6252 mov r3, rINST, lsr #12 @ r3<- B 6253 mov r9, rINST, lsr #8 @ r9<- A+ 6254 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6255 and r9, r9, #15 @ r9<- A 6256 fldd d1, [r3] @ d1<- vB 6257 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6258 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6259 fldd d0, [r9] @ d0<- vA 6260 6261 fsubd d2, d0, d1 @ d2<- op 6262 GET_INST_OPCODE(ip) @ extract opcode from rINST 6263 fstd d2, [r9] @ vAA<- d2 6264 GOTO_OPCODE(ip) @ jump to next instruction 6265 6266 6267/* ------------------------------ */ 6268 .balign 64 6269.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6270/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */ 6271/* File: arm-vfp/fbinopWide2addr.S */ 6272 /* 6273 * Generic 64-bit floating point "/2addr" binary operation. Provide 6274 * an "instr" line that specifies an instruction that performs 6275 * "d2 = d0 op d1". 6276 * 6277 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6278 * div-double/2addr 6279 */ 6280 /* binop/2addr vA, vB */ 6281 mov r3, rINST, lsr #12 @ r3<- B 6282 mov r9, rINST, lsr #8 @ r9<- A+ 6283 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6284 and r9, r9, #15 @ r9<- A 6285 fldd d1, [r3] @ d1<- vB 6286 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6287 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6288 fldd d0, [r9] @ d0<- vA 6289 6290 fmuld d2, d0, d1 @ d2<- op 6291 GET_INST_OPCODE(ip) @ extract opcode from rINST 6292 fstd d2, [r9] @ vAA<- d2 6293 GOTO_OPCODE(ip) @ jump to next instruction 6294 6295 6296/* ------------------------------ */ 6297 .balign 64 6298.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6299/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */ 6300/* File: arm-vfp/fbinopWide2addr.S */ 6301 /* 6302 * Generic 64-bit floating point "/2addr" binary operation. Provide 6303 * an "instr" line that specifies an instruction that performs 6304 * "d2 = d0 op d1". 6305 * 6306 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6307 * div-double/2addr 6308 */ 6309 /* binop/2addr vA, vB */ 6310 mov r3, rINST, lsr #12 @ r3<- B 6311 mov r9, rINST, lsr #8 @ r9<- A+ 6312 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6313 and r9, r9, #15 @ r9<- A 6314 fldd d1, [r3] @ d1<- vB 6315 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6316 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6317 fldd d0, [r9] @ d0<- vA 6318 6319 fdivd d2, d0, d1 @ d2<- op 6320 GET_INST_OPCODE(ip) @ extract opcode from rINST 6321 fstd d2, [r9] @ vAA<- d2 6322 GOTO_OPCODE(ip) @ jump to next instruction 6323 6324 6325/* ------------------------------ */ 6326 .balign 64 6327.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6328/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */ 6329/* EABI doesn't define a double remainder function, but libm does */ 6330/* File: armv5te/binopWide2addr.S */ 6331 /* 6332 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6333 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6334 * This could be an ARM instruction or a function call. (If the result 6335 * comes back in a register other than r0, you can override "result".) 6336 * 6337 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6338 * vCC (r1). Useful for integer division and modulus. 6339 * 6340 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6341 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6342 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6343 * rem-double/2addr 6344 */ 6345 /* binop/2addr vA, vB */ 6346 mov r9, rINST, lsr #8 @ r9<- A+ 6347 mov r1, rINST, lsr #12 @ r1<- B 6348 and r9, r9, #15 6349 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6350 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6351 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6352 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6353 .if 0 6354 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6355 beq common_errDivideByZero 6356 .endif 6357 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6358 6359 @ optional op; may set condition codes 6360 bl fmod @ result<- op, r0-r3 changed 6361 GET_INST_OPCODE(ip) @ extract opcode from rINST 6362 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6363 GOTO_OPCODE(ip) @ jump to next instruction 6364 /* 12-15 instructions */ 6365 6366 6367/* ------------------------------ */ 6368 .balign 64 6369.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6370/* File: armv5te/OP_ADD_INT_LIT16.S */ 6371/* File: armv5te/binopLit16.S */ 6372 /* 6373 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6374 * that specifies an instruction that performs "result = r0 op r1". 6375 * This could be an ARM instruction or a function call. (If the result 6376 * comes back in a register other than r0, you can override "result".) 6377 * 6378 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6379 * vCC (r1). Useful for integer division and modulus. 6380 * 6381 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6382 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6383 */ 6384 /* binop/lit16 vA, vB, #+CCCC */ 6385 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6386 mov r2, rINST, lsr #12 @ r2<- B 6387 mov r9, rINST, lsr #8 @ r9<- A+ 6388 GET_VREG(r0, r2) @ r0<- vB 6389 and r9, r9, #15 6390 .if 0 6391 cmp r1, #0 @ is second operand zero? 6392 beq common_errDivideByZero 6393 .endif 6394 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6395 6396 add r0, r0, r1 @ r0<- op, r0-r3 changed 6397 GET_INST_OPCODE(ip) @ extract opcode from rINST 6398 SET_VREG(r0, r9) @ vAA<- r0 6399 GOTO_OPCODE(ip) @ jump to next instruction 6400 /* 10-13 instructions */ 6401 6402 6403/* ------------------------------ */ 6404 .balign 64 6405.L_OP_RSUB_INT: /* 0xd1 */ 6406/* File: armv5te/OP_RSUB_INT.S */ 6407/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6408/* File: armv5te/binopLit16.S */ 6409 /* 6410 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6411 * that specifies an instruction that performs "result = r0 op r1". 6412 * This could be an ARM instruction or a function call. (If the result 6413 * comes back in a register other than r0, you can override "result".) 6414 * 6415 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6416 * vCC (r1). Useful for integer division and modulus. 6417 * 6418 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6419 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6420 */ 6421 /* binop/lit16 vA, vB, #+CCCC */ 6422 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6423 mov r2, rINST, lsr #12 @ r2<- B 6424 mov r9, rINST, lsr #8 @ r9<- A+ 6425 GET_VREG(r0, r2) @ r0<- vB 6426 and r9, r9, #15 6427 .if 0 6428 cmp r1, #0 @ is second operand zero? 6429 beq common_errDivideByZero 6430 .endif 6431 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6432 6433 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6434 GET_INST_OPCODE(ip) @ extract opcode from rINST 6435 SET_VREG(r0, r9) @ vAA<- r0 6436 GOTO_OPCODE(ip) @ jump to next instruction 6437 /* 10-13 instructions */ 6438 6439 6440/* ------------------------------ */ 6441 .balign 64 6442.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6443/* File: armv5te/OP_MUL_INT_LIT16.S */ 6444/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6445/* File: armv5te/binopLit16.S */ 6446 /* 6447 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6448 * that specifies an instruction that performs "result = r0 op r1". 6449 * This could be an ARM instruction or a function call. (If the result 6450 * comes back in a register other than r0, you can override "result".) 6451 * 6452 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6453 * vCC (r1). Useful for integer division and modulus. 6454 * 6455 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6456 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6457 */ 6458 /* binop/lit16 vA, vB, #+CCCC */ 6459 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6460 mov r2, rINST, lsr #12 @ r2<- B 6461 mov r9, rINST, lsr #8 @ r9<- A+ 6462 GET_VREG(r0, r2) @ r0<- vB 6463 and r9, r9, #15 6464 .if 0 6465 cmp r1, #0 @ is second operand zero? 6466 beq common_errDivideByZero 6467 .endif 6468 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6469 6470 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6471 GET_INST_OPCODE(ip) @ extract opcode from rINST 6472 SET_VREG(r0, r9) @ vAA<- r0 6473 GOTO_OPCODE(ip) @ jump to next instruction 6474 /* 10-13 instructions */ 6475 6476 6477/* ------------------------------ */ 6478 .balign 64 6479.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6480/* File: armv5te/OP_DIV_INT_LIT16.S */ 6481/* File: armv5te/binopLit16.S */ 6482 /* 6483 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6484 * that specifies an instruction that performs "result = r0 op r1". 6485 * This could be an ARM instruction or a function call. (If the result 6486 * comes back in a register other than r0, you can override "result".) 6487 * 6488 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6489 * vCC (r1). Useful for integer division and modulus. 6490 * 6491 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6492 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6493 */ 6494 /* binop/lit16 vA, vB, #+CCCC */ 6495 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6496 mov r2, rINST, lsr #12 @ r2<- B 6497 mov r9, rINST, lsr #8 @ r9<- A+ 6498 GET_VREG(r0, r2) @ r0<- vB 6499 and r9, r9, #15 6500 .if 1 6501 cmp r1, #0 @ is second operand zero? 6502 beq common_errDivideByZero 6503 .endif 6504 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6505 6506 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6507 GET_INST_OPCODE(ip) @ extract opcode from rINST 6508 SET_VREG(r0, r9) @ vAA<- r0 6509 GOTO_OPCODE(ip) @ jump to next instruction 6510 /* 10-13 instructions */ 6511 6512 6513/* ------------------------------ */ 6514 .balign 64 6515.L_OP_REM_INT_LIT16: /* 0xd4 */ 6516/* File: armv5te/OP_REM_INT_LIT16.S */ 6517/* idivmod returns quotient in r0 and remainder in r1 */ 6518/* File: armv5te/binopLit16.S */ 6519 /* 6520 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6521 * that specifies an instruction that performs "result = r0 op r1". 6522 * This could be an ARM instruction or a function call. (If the result 6523 * comes back in a register other than r0, you can override "result".) 6524 * 6525 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6526 * vCC (r1). Useful for integer division and modulus. 6527 * 6528 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6529 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6530 */ 6531 /* binop/lit16 vA, vB, #+CCCC */ 6532 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6533 mov r2, rINST, lsr #12 @ r2<- B 6534 mov r9, rINST, lsr #8 @ r9<- A+ 6535 GET_VREG(r0, r2) @ r0<- vB 6536 and r9, r9, #15 6537 .if 1 6538 cmp r1, #0 @ is second operand zero? 6539 beq common_errDivideByZero 6540 .endif 6541 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6542 6543 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6544 GET_INST_OPCODE(ip) @ extract opcode from rINST 6545 SET_VREG(r1, r9) @ vAA<- r1 6546 GOTO_OPCODE(ip) @ jump to next instruction 6547 /* 10-13 instructions */ 6548 6549 6550/* ------------------------------ */ 6551 .balign 64 6552.L_OP_AND_INT_LIT16: /* 0xd5 */ 6553/* File: armv5te/OP_AND_INT_LIT16.S */ 6554/* File: armv5te/binopLit16.S */ 6555 /* 6556 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6557 * that specifies an instruction that performs "result = r0 op r1". 6558 * This could be an ARM instruction or a function call. (If the result 6559 * comes back in a register other than r0, you can override "result".) 6560 * 6561 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6562 * vCC (r1). Useful for integer division and modulus. 6563 * 6564 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6565 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6566 */ 6567 /* binop/lit16 vA, vB, #+CCCC */ 6568 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6569 mov r2, rINST, lsr #12 @ r2<- B 6570 mov r9, rINST, lsr #8 @ r9<- A+ 6571 GET_VREG(r0, r2) @ r0<- vB 6572 and r9, r9, #15 6573 .if 0 6574 cmp r1, #0 @ is second operand zero? 6575 beq common_errDivideByZero 6576 .endif 6577 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6578 6579 and r0, r0, r1 @ r0<- op, r0-r3 changed 6580 GET_INST_OPCODE(ip) @ extract opcode from rINST 6581 SET_VREG(r0, r9) @ vAA<- r0 6582 GOTO_OPCODE(ip) @ jump to next instruction 6583 /* 10-13 instructions */ 6584 6585 6586/* ------------------------------ */ 6587 .balign 64 6588.L_OP_OR_INT_LIT16: /* 0xd6 */ 6589/* File: armv5te/OP_OR_INT_LIT16.S */ 6590/* File: armv5te/binopLit16.S */ 6591 /* 6592 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6593 * that specifies an instruction that performs "result = r0 op r1". 6594 * This could be an ARM instruction or a function call. (If the result 6595 * comes back in a register other than r0, you can override "result".) 6596 * 6597 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6598 * vCC (r1). Useful for integer division and modulus. 6599 * 6600 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6601 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6602 */ 6603 /* binop/lit16 vA, vB, #+CCCC */ 6604 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6605 mov r2, rINST, lsr #12 @ r2<- B 6606 mov r9, rINST, lsr #8 @ r9<- A+ 6607 GET_VREG(r0, r2) @ r0<- vB 6608 and r9, r9, #15 6609 .if 0 6610 cmp r1, #0 @ is second operand zero? 6611 beq common_errDivideByZero 6612 .endif 6613 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6614 6615 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6616 GET_INST_OPCODE(ip) @ extract opcode from rINST 6617 SET_VREG(r0, r9) @ vAA<- r0 6618 GOTO_OPCODE(ip) @ jump to next instruction 6619 /* 10-13 instructions */ 6620 6621 6622/* ------------------------------ */ 6623 .balign 64 6624.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6625/* File: armv5te/OP_XOR_INT_LIT16.S */ 6626/* File: armv5te/binopLit16.S */ 6627 /* 6628 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6629 * that specifies an instruction that performs "result = r0 op r1". 6630 * This could be an ARM instruction or a function call. (If the result 6631 * comes back in a register other than r0, you can override "result".) 6632 * 6633 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6634 * vCC (r1). Useful for integer division and modulus. 6635 * 6636 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6637 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6638 */ 6639 /* binop/lit16 vA, vB, #+CCCC */ 6640 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6641 mov r2, rINST, lsr #12 @ r2<- B 6642 mov r9, rINST, lsr #8 @ r9<- A+ 6643 GET_VREG(r0, r2) @ r0<- vB 6644 and r9, r9, #15 6645 .if 0 6646 cmp r1, #0 @ is second operand zero? 6647 beq common_errDivideByZero 6648 .endif 6649 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6650 6651 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6652 GET_INST_OPCODE(ip) @ extract opcode from rINST 6653 SET_VREG(r0, r9) @ vAA<- r0 6654 GOTO_OPCODE(ip) @ jump to next instruction 6655 /* 10-13 instructions */ 6656 6657 6658/* ------------------------------ */ 6659 .balign 64 6660.L_OP_ADD_INT_LIT8: /* 0xd8 */ 6661/* File: armv5te/OP_ADD_INT_LIT8.S */ 6662/* File: armv5te/binopLit8.S */ 6663 /* 6664 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6665 * that specifies an instruction that performs "result = r0 op r1". 6666 * This could be an ARM instruction or a function call. (If the result 6667 * comes back in a register other than r0, you can override "result".) 6668 * 6669 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6670 * vCC (r1). Useful for integer division and modulus. 6671 * 6672 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6673 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6674 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6675 */ 6676 /* binop/lit8 vAA, vBB, #+CC */ 6677 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6678 mov r9, rINST, lsr #8 @ r9<- AA 6679 and r2, r3, #255 @ r2<- BB 6680 GET_VREG(r0, r2) @ r0<- vBB 6681 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6682 .if 0 6683 @cmp r1, #0 @ is second operand zero? 6684 beq common_errDivideByZero 6685 .endif 6686 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6687 6688 @ optional op; may set condition codes 6689 add r0, r0, r1 @ r0<- op, r0-r3 changed 6690 GET_INST_OPCODE(ip) @ extract opcode from rINST 6691 SET_VREG(r0, r9) @ vAA<- r0 6692 GOTO_OPCODE(ip) @ jump to next instruction 6693 /* 10-12 instructions */ 6694 6695 6696/* ------------------------------ */ 6697 .balign 64 6698.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 6699/* File: armv5te/OP_RSUB_INT_LIT8.S */ 6700/* File: armv5te/binopLit8.S */ 6701 /* 6702 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6703 * that specifies an instruction that performs "result = r0 op r1". 6704 * This could be an ARM instruction or a function call. (If the result 6705 * comes back in a register other than r0, you can override "result".) 6706 * 6707 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6708 * vCC (r1). Useful for integer division and modulus. 6709 * 6710 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6711 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6712 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6713 */ 6714 /* binop/lit8 vAA, vBB, #+CC */ 6715 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6716 mov r9, rINST, lsr #8 @ r9<- AA 6717 and r2, r3, #255 @ r2<- BB 6718 GET_VREG(r0, r2) @ r0<- vBB 6719 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6720 .if 0 6721 @cmp r1, #0 @ is second operand zero? 6722 beq common_errDivideByZero 6723 .endif 6724 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6725 6726 @ optional op; may set condition codes 6727 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6728 GET_INST_OPCODE(ip) @ extract opcode from rINST 6729 SET_VREG(r0, r9) @ vAA<- r0 6730 GOTO_OPCODE(ip) @ jump to next instruction 6731 /* 10-12 instructions */ 6732 6733 6734/* ------------------------------ */ 6735 .balign 64 6736.L_OP_MUL_INT_LIT8: /* 0xda */ 6737/* File: armv5te/OP_MUL_INT_LIT8.S */ 6738/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6739/* File: armv5te/binopLit8.S */ 6740 /* 6741 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6742 * that specifies an instruction that performs "result = r0 op r1". 6743 * This could be an ARM instruction or a function call. (If the result 6744 * comes back in a register other than r0, you can override "result".) 6745 * 6746 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6747 * vCC (r1). Useful for integer division and modulus. 6748 * 6749 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6750 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6751 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6752 */ 6753 /* binop/lit8 vAA, vBB, #+CC */ 6754 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6755 mov r9, rINST, lsr #8 @ r9<- AA 6756 and r2, r3, #255 @ r2<- BB 6757 GET_VREG(r0, r2) @ r0<- vBB 6758 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6759 .if 0 6760 @cmp r1, #0 @ is second operand zero? 6761 beq common_errDivideByZero 6762 .endif 6763 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6764 6765 @ optional op; may set condition codes 6766 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6767 GET_INST_OPCODE(ip) @ extract opcode from rINST 6768 SET_VREG(r0, r9) @ vAA<- r0 6769 GOTO_OPCODE(ip) @ jump to next instruction 6770 /* 10-12 instructions */ 6771 6772 6773/* ------------------------------ */ 6774 .balign 64 6775.L_OP_DIV_INT_LIT8: /* 0xdb */ 6776/* File: armv5te/OP_DIV_INT_LIT8.S */ 6777/* File: armv5te/binopLit8.S */ 6778 /* 6779 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6780 * that specifies an instruction that performs "result = r0 op r1". 6781 * This could be an ARM instruction or a function call. (If the result 6782 * comes back in a register other than r0, you can override "result".) 6783 * 6784 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6785 * vCC (r1). Useful for integer division and modulus. 6786 * 6787 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6788 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6789 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6790 */ 6791 /* binop/lit8 vAA, vBB, #+CC */ 6792 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6793 mov r9, rINST, lsr #8 @ r9<- AA 6794 and r2, r3, #255 @ r2<- BB 6795 GET_VREG(r0, r2) @ r0<- vBB 6796 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6797 .if 1 6798 @cmp r1, #0 @ is second operand zero? 6799 beq common_errDivideByZero 6800 .endif 6801 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6802 6803 @ optional op; may set condition codes 6804 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6805 GET_INST_OPCODE(ip) @ extract opcode from rINST 6806 SET_VREG(r0, r9) @ vAA<- r0 6807 GOTO_OPCODE(ip) @ jump to next instruction 6808 /* 10-12 instructions */ 6809 6810 6811/* ------------------------------ */ 6812 .balign 64 6813.L_OP_REM_INT_LIT8: /* 0xdc */ 6814/* File: armv5te/OP_REM_INT_LIT8.S */ 6815/* idivmod returns quotient in r0 and remainder in r1 */ 6816/* File: armv5te/binopLit8.S */ 6817 /* 6818 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6819 * that specifies an instruction that performs "result = r0 op r1". 6820 * This could be an ARM instruction or a function call. (If the result 6821 * comes back in a register other than r0, you can override "result".) 6822 * 6823 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6824 * vCC (r1). Useful for integer division and modulus. 6825 * 6826 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6827 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6828 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6829 */ 6830 /* binop/lit8 vAA, vBB, #+CC */ 6831 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6832 mov r9, rINST, lsr #8 @ r9<- AA 6833 and r2, r3, #255 @ r2<- BB 6834 GET_VREG(r0, r2) @ r0<- vBB 6835 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6836 .if 1 6837 @cmp r1, #0 @ is second operand zero? 6838 beq common_errDivideByZero 6839 .endif 6840 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6841 6842 @ optional op; may set condition codes 6843 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6844 GET_INST_OPCODE(ip) @ extract opcode from rINST 6845 SET_VREG(r1, r9) @ vAA<- r1 6846 GOTO_OPCODE(ip) @ jump to next instruction 6847 /* 10-12 instructions */ 6848 6849 6850/* ------------------------------ */ 6851 .balign 64 6852.L_OP_AND_INT_LIT8: /* 0xdd */ 6853/* File: armv5te/OP_AND_INT_LIT8.S */ 6854/* File: armv5te/binopLit8.S */ 6855 /* 6856 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6857 * that specifies an instruction that performs "result = r0 op r1". 6858 * This could be an ARM instruction or a function call. (If the result 6859 * comes back in a register other than r0, you can override "result".) 6860 * 6861 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6862 * vCC (r1). Useful for integer division and modulus. 6863 * 6864 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6865 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6866 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6867 */ 6868 /* binop/lit8 vAA, vBB, #+CC */ 6869 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6870 mov r9, rINST, lsr #8 @ r9<- AA 6871 and r2, r3, #255 @ r2<- BB 6872 GET_VREG(r0, r2) @ r0<- vBB 6873 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6874 .if 0 6875 @cmp r1, #0 @ is second operand zero? 6876 beq common_errDivideByZero 6877 .endif 6878 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6879 6880 @ optional op; may set condition codes 6881 and r0, r0, r1 @ r0<- op, r0-r3 changed 6882 GET_INST_OPCODE(ip) @ extract opcode from rINST 6883 SET_VREG(r0, r9) @ vAA<- r0 6884 GOTO_OPCODE(ip) @ jump to next instruction 6885 /* 10-12 instructions */ 6886 6887 6888/* ------------------------------ */ 6889 .balign 64 6890.L_OP_OR_INT_LIT8: /* 0xde */ 6891/* File: armv5te/OP_OR_INT_LIT8.S */ 6892/* File: armv5te/binopLit8.S */ 6893 /* 6894 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6895 * that specifies an instruction that performs "result = r0 op r1". 6896 * This could be an ARM instruction or a function call. (If the result 6897 * comes back in a register other than r0, you can override "result".) 6898 * 6899 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6900 * vCC (r1). Useful for integer division and modulus. 6901 * 6902 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6903 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6904 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6905 */ 6906 /* binop/lit8 vAA, vBB, #+CC */ 6907 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6908 mov r9, rINST, lsr #8 @ r9<- AA 6909 and r2, r3, #255 @ r2<- BB 6910 GET_VREG(r0, r2) @ r0<- vBB 6911 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6912 .if 0 6913 @cmp r1, #0 @ is second operand zero? 6914 beq common_errDivideByZero 6915 .endif 6916 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6917 6918 @ optional op; may set condition codes 6919 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6920 GET_INST_OPCODE(ip) @ extract opcode from rINST 6921 SET_VREG(r0, r9) @ vAA<- r0 6922 GOTO_OPCODE(ip) @ jump to next instruction 6923 /* 10-12 instructions */ 6924 6925 6926/* ------------------------------ */ 6927 .balign 64 6928.L_OP_XOR_INT_LIT8: /* 0xdf */ 6929/* File: armv5te/OP_XOR_INT_LIT8.S */ 6930/* File: armv5te/binopLit8.S */ 6931 /* 6932 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6933 * that specifies an instruction that performs "result = r0 op r1". 6934 * This could be an ARM instruction or a function call. (If the result 6935 * comes back in a register other than r0, you can override "result".) 6936 * 6937 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6938 * vCC (r1). Useful for integer division and modulus. 6939 * 6940 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6941 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6942 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6943 */ 6944 /* binop/lit8 vAA, vBB, #+CC */ 6945 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6946 mov r9, rINST, lsr #8 @ r9<- AA 6947 and r2, r3, #255 @ r2<- BB 6948 GET_VREG(r0, r2) @ r0<- vBB 6949 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6950 .if 0 6951 @cmp r1, #0 @ is second operand zero? 6952 beq common_errDivideByZero 6953 .endif 6954 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6955 6956 @ optional op; may set condition codes 6957 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6958 GET_INST_OPCODE(ip) @ extract opcode from rINST 6959 SET_VREG(r0, r9) @ vAA<- r0 6960 GOTO_OPCODE(ip) @ jump to next instruction 6961 /* 10-12 instructions */ 6962 6963 6964/* ------------------------------ */ 6965 .balign 64 6966.L_OP_SHL_INT_LIT8: /* 0xe0 */ 6967/* File: armv5te/OP_SHL_INT_LIT8.S */ 6968/* File: armv5te/binopLit8.S */ 6969 /* 6970 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6971 * that specifies an instruction that performs "result = r0 op r1". 6972 * This could be an ARM instruction or a function call. (If the result 6973 * comes back in a register other than r0, you can override "result".) 6974 * 6975 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6976 * vCC (r1). Useful for integer division and modulus. 6977 * 6978 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6979 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6980 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6981 */ 6982 /* binop/lit8 vAA, vBB, #+CC */ 6983 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6984 mov r9, rINST, lsr #8 @ r9<- AA 6985 and r2, r3, #255 @ r2<- BB 6986 GET_VREG(r0, r2) @ r0<- vBB 6987 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6988 .if 0 6989 @cmp r1, #0 @ is second operand zero? 6990 beq common_errDivideByZero 6991 .endif 6992 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6993 6994 and r1, r1, #31 @ optional op; may set condition codes 6995 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 6996 GET_INST_OPCODE(ip) @ extract opcode from rINST 6997 SET_VREG(r0, r9) @ vAA<- r0 6998 GOTO_OPCODE(ip) @ jump to next instruction 6999 /* 10-12 instructions */ 7000 7001 7002/* ------------------------------ */ 7003 .balign 64 7004.L_OP_SHR_INT_LIT8: /* 0xe1 */ 7005/* File: armv5te/OP_SHR_INT_LIT8.S */ 7006/* File: armv5te/binopLit8.S */ 7007 /* 7008 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7009 * that specifies an instruction that performs "result = r0 op r1". 7010 * This could be an ARM instruction or a function call. (If the result 7011 * comes back in a register other than r0, you can override "result".) 7012 * 7013 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7014 * vCC (r1). Useful for integer division and modulus. 7015 * 7016 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7017 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7018 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7019 */ 7020 /* binop/lit8 vAA, vBB, #+CC */ 7021 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7022 mov r9, rINST, lsr #8 @ r9<- AA 7023 and r2, r3, #255 @ r2<- BB 7024 GET_VREG(r0, r2) @ r0<- vBB 7025 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7026 .if 0 7027 @cmp r1, #0 @ is second operand zero? 7028 beq common_errDivideByZero 7029 .endif 7030 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7031 7032 and r1, r1, #31 @ optional op; may set condition codes 7033 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7034 GET_INST_OPCODE(ip) @ extract opcode from rINST 7035 SET_VREG(r0, r9) @ vAA<- r0 7036 GOTO_OPCODE(ip) @ jump to next instruction 7037 /* 10-12 instructions */ 7038 7039 7040/* ------------------------------ */ 7041 .balign 64 7042.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7043/* File: armv5te/OP_USHR_INT_LIT8.S */ 7044/* File: armv5te/binopLit8.S */ 7045 /* 7046 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7047 * that specifies an instruction that performs "result = r0 op r1". 7048 * This could be an ARM instruction or a function call. (If the result 7049 * comes back in a register other than r0, you can override "result".) 7050 * 7051 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7052 * vCC (r1). Useful for integer division and modulus. 7053 * 7054 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7055 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7056 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7057 */ 7058 /* binop/lit8 vAA, vBB, #+CC */ 7059 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7060 mov r9, rINST, lsr #8 @ r9<- AA 7061 and r2, r3, #255 @ r2<- BB 7062 GET_VREG(r0, r2) @ r0<- vBB 7063 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7064 .if 0 7065 @cmp r1, #0 @ is second operand zero? 7066 beq common_errDivideByZero 7067 .endif 7068 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7069 7070 and r1, r1, #31 @ optional op; may set condition codes 7071 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7072 GET_INST_OPCODE(ip) @ extract opcode from rINST 7073 SET_VREG(r0, r9) @ vAA<- r0 7074 GOTO_OPCODE(ip) @ jump to next instruction 7075 /* 10-12 instructions */ 7076 7077 7078/* ------------------------------ */ 7079 .balign 64 7080.L_OP_IGET_VOLATILE: /* 0xe3 */ 7081/* File: armv5te/OP_IGET_VOLATILE.S */ 7082/* File: armv5te/OP_IGET.S */ 7083 /* 7084 * General 32-bit instance field get. 7085 * 7086 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7087 */ 7088 /* op vA, vB, field@CCCC */ 7089 mov r0, rINST, lsr #12 @ r0<- B 7090 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7091 FETCH(r1, 1) @ r1<- field ref CCCC 7092 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7093 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7094 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7095 cmp r0, #0 @ is resolved entry null? 7096 bne .LOP_IGET_VOLATILE_finish @ no, already resolved 70978: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7098 EXPORT_PC() @ resolve() could throw 7099 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7100 bl dvmResolveInstField @ r0<- resolved InstField ptr 7101 cmp r0, #0 7102 bne .LOP_IGET_VOLATILE_finish 7103 b common_exceptionThrown 7104 7105 7106/* ------------------------------ */ 7107 .balign 64 7108.L_OP_IPUT_VOLATILE: /* 0xe4 */ 7109/* File: armv5te/OP_IPUT_VOLATILE.S */ 7110/* File: armv5te/OP_IPUT.S */ 7111 /* 7112 * General 32-bit instance field put. 7113 * 7114 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 7115 */ 7116 /* op vA, vB, field@CCCC */ 7117 mov r0, rINST, lsr #12 @ r0<- B 7118 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7119 FETCH(r1, 1) @ r1<- field ref CCCC 7120 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7121 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7122 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7123 cmp r0, #0 @ is resolved entry null? 7124 bne .LOP_IPUT_VOLATILE_finish @ no, already resolved 71258: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7126 EXPORT_PC() @ resolve() could throw 7127 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7128 bl dvmResolveInstField @ r0<- resolved InstField ptr 7129 cmp r0, #0 @ success? 7130 bne .LOP_IPUT_VOLATILE_finish @ yes, finish up 7131 b common_exceptionThrown 7132 7133 7134/* ------------------------------ */ 7135 .balign 64 7136.L_OP_SGET_VOLATILE: /* 0xe5 */ 7137/* File: armv5te/OP_SGET_VOLATILE.S */ 7138/* File: armv5te/OP_SGET.S */ 7139 /* 7140 * General 32-bit SGET handler. 7141 * 7142 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7143 */ 7144 /* op vAA, field@BBBB */ 7145 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7146 FETCH(r1, 1) @ r1<- field ref BBBB 7147 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7148 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7149 cmp r0, #0 @ is resolved entry null? 7150 beq .LOP_SGET_VOLATILE_resolve @ yes, do resolve 7151.LOP_SGET_VOLATILE_finish: @ field ptr in r0 7152 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7153 SMP_DMB @ acquiring load 7154 mov r2, rINST, lsr #8 @ r2<- AA 7155 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7156 SET_VREG(r1, r2) @ fp[AA]<- r1 7157 GET_INST_OPCODE(ip) @ extract opcode from rINST 7158 GOTO_OPCODE(ip) @ jump to next instruction 7159 7160 7161/* ------------------------------ */ 7162 .balign 64 7163.L_OP_SPUT_VOLATILE: /* 0xe6 */ 7164/* File: armv5te/OP_SPUT_VOLATILE.S */ 7165/* File: armv5te/OP_SPUT.S */ 7166 /* 7167 * General 32-bit SPUT handler. 7168 * 7169 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 7170 */ 7171 /* op vAA, field@BBBB */ 7172 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7173 FETCH(r1, 1) @ r1<- field ref BBBB 7174 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7175 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7176 cmp r0, #0 @ is resolved entry null? 7177 beq .LOP_SPUT_VOLATILE_resolve @ yes, do resolve 7178.LOP_SPUT_VOLATILE_finish: @ field ptr in r0 7179 mov r2, rINST, lsr #8 @ r2<- AA 7180 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7181 GET_VREG(r1, r2) @ r1<- fp[AA] 7182 GET_INST_OPCODE(ip) @ extract opcode from rINST 7183 SMP_DMB @ releasing store 7184 str r1, [r0, #offStaticField_value] @ field<- vAA 7185 GOTO_OPCODE(ip) @ jump to next instruction 7186 7187 7188/* ------------------------------ */ 7189 .balign 64 7190.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ 7191/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */ 7192/* File: armv5te/OP_IGET.S */ 7193 /* 7194 * General 32-bit instance field get. 7195 * 7196 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7197 */ 7198 /* op vA, vB, field@CCCC */ 7199 mov r0, rINST, lsr #12 @ r0<- B 7200 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7201 FETCH(r1, 1) @ r1<- field ref CCCC 7202 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7203 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7204 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7205 cmp r0, #0 @ is resolved entry null? 7206 bne .LOP_IGET_OBJECT_VOLATILE_finish @ no, already resolved 72078: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7208 EXPORT_PC() @ resolve() could throw 7209 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7210 bl dvmResolveInstField @ r0<- resolved InstField ptr 7211 cmp r0, #0 7212 bne .LOP_IGET_OBJECT_VOLATILE_finish 7213 b common_exceptionThrown 7214 7215 7216/* ------------------------------ */ 7217 .balign 64 7218.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */ 7219/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */ 7220/* File: armv5te/OP_IGET_WIDE.S */ 7221 /* 7222 * Wide 32-bit instance field get. 7223 */ 7224 /* iget-wide vA, vB, field@CCCC */ 7225 mov r0, rINST, lsr #12 @ r0<- B 7226 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7227 FETCH(r1, 1) @ r1<- field ref CCCC 7228 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7229 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7230 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7231 cmp r0, #0 @ is resolved entry null? 7232 bne .LOP_IGET_WIDE_VOLATILE_finish @ no, already resolved 72338: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7234 EXPORT_PC() @ resolve() could throw 7235 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7236 bl dvmResolveInstField @ r0<- resolved InstField ptr 7237 cmp r0, #0 7238 bne .LOP_IGET_WIDE_VOLATILE_finish 7239 b common_exceptionThrown 7240 7241 7242/* ------------------------------ */ 7243 .balign 64 7244.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */ 7245/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */ 7246/* File: armv5te/OP_IPUT_WIDE.S */ 7247 /* iput-wide vA, vB, field@CCCC */ 7248 mov r0, rINST, lsr #12 @ r0<- B 7249 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7250 FETCH(r1, 1) @ r1<- field ref CCCC 7251 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7252 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7253 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7254 cmp r0, #0 @ is resolved entry null? 7255 bne .LOP_IPUT_WIDE_VOLATILE_finish @ no, already resolved 72568: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7257 EXPORT_PC() @ resolve() could throw 7258 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7259 bl dvmResolveInstField @ r0<- resolved InstField ptr 7260 cmp r0, #0 @ success? 7261 bne .LOP_IPUT_WIDE_VOLATILE_finish @ yes, finish up 7262 b common_exceptionThrown 7263 7264 7265/* ------------------------------ */ 7266 .balign 64 7267.L_OP_SGET_WIDE_VOLATILE: /* 0xea */ 7268/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */ 7269/* File: armv5te/OP_SGET_WIDE.S */ 7270 /* 7271 * 64-bit SGET handler. 7272 */ 7273 /* sget-wide vAA, field@BBBB */ 7274 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7275 FETCH(r1, 1) @ r1<- field ref BBBB 7276 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7277 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7278 cmp r0, #0 @ is resolved entry null? 7279 beq .LOP_SGET_WIDE_VOLATILE_resolve @ yes, do resolve 7280.LOP_SGET_WIDE_VOLATILE_finish: 7281 mov r9, rINST, lsr #8 @ r9<- AA 7282 .if 1 7283 add r0, r0, #offStaticField_value @ r0<- pointer to data 7284 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 7285 .else 7286 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 7287 .endif 7288 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7289 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7290 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 7291 GET_INST_OPCODE(ip) @ extract opcode from rINST 7292 GOTO_OPCODE(ip) @ jump to next instruction 7293 7294 7295/* ------------------------------ */ 7296 .balign 64 7297.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */ 7298/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */ 7299/* File: armv5te/OP_SPUT_WIDE.S */ 7300 /* 7301 * 64-bit SPUT handler. 7302 */ 7303 /* sput-wide vAA, field@BBBB */ 7304 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 7305 FETCH(r1, 1) @ r1<- field ref BBBB 7306 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 7307 mov r9, rINST, lsr #8 @ r9<- AA 7308 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 7309 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7310 cmp r2, #0 @ is resolved entry null? 7311 beq .LOP_SPUT_WIDE_VOLATILE_resolve @ yes, do resolve 7312.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9 7313 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7314 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 7315 GET_INST_OPCODE(r10) @ extract opcode from rINST 7316 .if 1 7317 add r2, r2, #offStaticField_value @ r2<- pointer to data 7318 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 7319 .else 7320 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 7321 .endif 7322 GOTO_OPCODE(r10) @ jump to next instruction 7323 7324 7325/* ------------------------------ */ 7326 .balign 64 7327.L_OP_BREAKPOINT: /* 0xec */ 7328/* File: armv5te/OP_BREAKPOINT.S */ 7329/* File: armv5te/unused.S */ 7330 bl common_abort 7331 7332 7333/* ------------------------------ */ 7334 .balign 64 7335.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7336/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7337 /* 7338 * Handle a throw-verification-error instruction. This throws an 7339 * exception for an error discovered during verification. The 7340 * exception is indicated by AA, with some detail provided by BBBB. 7341 */ 7342 /* op AA, ref@BBBB */ 7343 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7344 FETCH(r2, 1) @ r2<- BBBB 7345 EXPORT_PC() @ export the PC 7346 mov r1, rINST, lsr #8 @ r1<- AA 7347 bl dvmThrowVerificationError @ always throws 7348 b common_exceptionThrown @ handle exception 7349 7350/* ------------------------------ */ 7351 .balign 64 7352.L_OP_EXECUTE_INLINE: /* 0xee */ 7353/* File: armv5te/OP_EXECUTE_INLINE.S */ 7354 /* 7355 * Execute a "native inline" instruction. 7356 * 7357 * We need to call an InlineOp4Func: 7358 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7359 * 7360 * The first four args are in r0-r3, pointer to return value storage 7361 * is on the stack. The function's return value is a flag that tells 7362 * us if an exception was thrown. 7363 */ 7364 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7365 FETCH(r10, 1) @ r10<- BBBB 7366 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7367 EXPORT_PC() @ can throw 7368 sub sp, sp, #8 @ make room for arg, +64 bit align 7369 mov r0, rINST, lsr #12 @ r0<- B 7370 str r1, [sp] @ push &glue->retval 7371 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7372 add sp, sp, #8 @ pop stack 7373 cmp r0, #0 @ test boolean result of inline 7374 beq common_exceptionThrown @ returned false, handle exception 7375 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7376 GET_INST_OPCODE(ip) @ extract opcode from rINST 7377 GOTO_OPCODE(ip) @ jump to next instruction 7378 7379/* ------------------------------ */ 7380 .balign 64 7381.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ 7382/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */ 7383 /* 7384 * Execute a "native inline" instruction, using "/range" semantics. 7385 * Same idea as execute-inline, but we get the args differently. 7386 * 7387 * We need to call an InlineOp4Func: 7388 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7389 * 7390 * The first four args are in r0-r3, pointer to return value storage 7391 * is on the stack. The function's return value is a flag that tells 7392 * us if an exception was thrown. 7393 */ 7394 /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */ 7395 FETCH(r10, 1) @ r10<- BBBB 7396 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7397 EXPORT_PC() @ can throw 7398 sub sp, sp, #8 @ make room for arg, +64 bit align 7399 mov r0, rINST, lsr #8 @ r0<- AA 7400 str r1, [sp] @ push &glue->retval 7401 bl .LOP_EXECUTE_INLINE_RANGE_continue @ make call; will return after 7402 add sp, sp, #8 @ pop stack 7403 cmp r0, #0 @ test boolean result of inline 7404 beq common_exceptionThrown @ returned false, handle exception 7405 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7406 GET_INST_OPCODE(ip) @ extract opcode from rINST 7407 GOTO_OPCODE(ip) @ jump to next instruction 7408 7409/* ------------------------------ */ 7410 .balign 64 7411.L_OP_INVOKE_OBJECT_INIT: /* 0xf0 */ 7412/* File: armv5te/OP_INVOKE_OBJECT_INIT.S */ 7413 /* 7414 * invoke-object-init is a no-op in a "standard" interpreter. 7415 */ 7416 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7417 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7418 GOTO_OPCODE(ip) @ execute it 7419 7420/* ------------------------------ */ 7421 .balign 64 7422.L_OP_RETURN_VOID_BARRIER: /* 0xf1 */ 7423/* File: armv5te/OP_RETURN_VOID_BARRIER.S */ 7424 SMP_DMB_ST 7425 b common_returnFromMethod 7426 7427/* ------------------------------ */ 7428 .balign 64 7429.L_OP_IGET_QUICK: /* 0xf2 */ 7430/* File: armv5te/OP_IGET_QUICK.S */ 7431 /* For: iget-quick, iget-object-quick */ 7432 /* op vA, vB, offset@CCCC */ 7433 mov r2, rINST, lsr #12 @ r2<- B 7434 GET_VREG(r3, r2) @ r3<- object we're operating on 7435 FETCH(r1, 1) @ r1<- field byte offset 7436 cmp r3, #0 @ check object for null 7437 mov r2, rINST, lsr #8 @ r2<- A(+) 7438 beq common_errNullObject @ object was null 7439 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7440 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7441 and r2, r2, #15 7442 GET_INST_OPCODE(ip) @ extract opcode from rINST 7443 SET_VREG(r0, r2) @ fp[A]<- r0 7444 GOTO_OPCODE(ip) @ jump to next instruction 7445 7446/* ------------------------------ */ 7447 .balign 64 7448.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7449/* File: armv5te/OP_IGET_WIDE_QUICK.S */ 7450 /* iget-wide-quick vA, vB, offset@CCCC */ 7451 mov r2, rINST, lsr #12 @ r2<- B 7452 GET_VREG(r3, r2) @ r3<- object we're operating on 7453 FETCH(ip, 1) @ ip<- field byte offset 7454 cmp r3, #0 @ check object for null 7455 mov r2, rINST, lsr #8 @ r2<- A(+) 7456 beq common_errNullObject @ object was null 7457 ldrd r0, [r3, ip] @ r0<- obj.field (64 bits, aligned) 7458 and r2, r2, #15 7459 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7460 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7461 GET_INST_OPCODE(ip) @ extract opcode from rINST 7462 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7463 GOTO_OPCODE(ip) @ jump to next instruction 7464 7465/* ------------------------------ */ 7466 .balign 64 7467.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7468/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7469/* File: armv5te/OP_IGET_QUICK.S */ 7470 /* For: iget-quick, iget-object-quick */ 7471 /* op vA, vB, offset@CCCC */ 7472 mov r2, rINST, lsr #12 @ r2<- B 7473 GET_VREG(r3, r2) @ r3<- object we're operating on 7474 FETCH(r1, 1) @ r1<- field byte offset 7475 cmp r3, #0 @ check object for null 7476 mov r2, rINST, lsr #8 @ r2<- A(+) 7477 beq common_errNullObject @ object was null 7478 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7479 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7480 and r2, r2, #15 7481 GET_INST_OPCODE(ip) @ extract opcode from rINST 7482 SET_VREG(r0, r2) @ fp[A]<- r0 7483 GOTO_OPCODE(ip) @ jump to next instruction 7484 7485 7486/* ------------------------------ */ 7487 .balign 64 7488.L_OP_IPUT_QUICK: /* 0xf5 */ 7489/* File: armv5te/OP_IPUT_QUICK.S */ 7490 /* For: iput-quick */ 7491 /* op vA, vB, offset@CCCC */ 7492 mov r2, rINST, lsr #12 @ r2<- B 7493 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7494 FETCH(r1, 1) @ r1<- field byte offset 7495 cmp r3, #0 @ check object for null 7496 mov r2, rINST, lsr #8 @ r2<- A(+) 7497 beq common_errNullObject @ object was null 7498 and r2, r2, #15 7499 GET_VREG(r0, r2) @ r0<- fp[A] 7500 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7501 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7502 GET_INST_OPCODE(ip) @ extract opcode from rINST 7503 GOTO_OPCODE(ip) @ jump to next instruction 7504 7505/* ------------------------------ */ 7506 .balign 64 7507.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7508/* File: armv5te/OP_IPUT_WIDE_QUICK.S */ 7509 /* iput-wide-quick vA, vB, offset@CCCC */ 7510 mov r0, rINST, lsr #8 @ r0<- A(+) 7511 mov r1, rINST, lsr #12 @ r1<- B 7512 and r0, r0, #15 7513 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7514 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7515 cmp r2, #0 @ check object for null 7516 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7517 beq common_errNullObject @ object was null 7518 FETCH(r3, 1) @ r3<- field byte offset 7519 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7520 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7521 GET_INST_OPCODE(ip) @ extract opcode from rINST 7522 GOTO_OPCODE(ip) @ jump to next instruction 7523 7524/* ------------------------------ */ 7525 .balign 64 7526.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7527/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7528 /* For: iput-object-quick */ 7529 /* op vA, vB, offset@CCCC */ 7530 mov r2, rINST, lsr #12 @ r2<- B 7531 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7532 FETCH(r1, 1) @ r1<- field byte offset 7533 cmp r3, #0 @ check object for null 7534 mov r2, rINST, lsr #8 @ r2<- A(+) 7535 beq common_errNullObject @ object was null 7536 and r2, r2, #15 7537 GET_VREG(r0, r2) @ r0<- fp[A] 7538 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 7539 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7540 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7541 cmp r0, #0 7542 strneb r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head 7543 GET_INST_OPCODE(ip) @ extract opcode from rINST 7544 GOTO_OPCODE(ip) @ jump to next instruction 7545 7546/* ------------------------------ */ 7547 .balign 64 7548.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7549/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7550 /* 7551 * Handle an optimized virtual method call. 7552 * 7553 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7554 */ 7555 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7556 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7557 FETCH(r3, 2) @ r3<- FEDC or CCCC 7558 FETCH(r1, 1) @ r1<- BBBB 7559 .if (!0) 7560 and r3, r3, #15 @ r3<- C (or stays CCCC) 7561 .endif 7562 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7563 cmp r2, #0 @ is "this" null? 7564 beq common_errNullObject @ null "this", throw exception 7565 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7566 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7567 EXPORT_PC() @ invoke must export 7568 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7569 bl common_invokeMethodNoRange @ continue on 7570 7571/* ------------------------------ */ 7572 .balign 64 7573.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7574/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7575/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7576 /* 7577 * Handle an optimized virtual method call. 7578 * 7579 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7580 */ 7581 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7582 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7583 FETCH(r3, 2) @ r3<- FEDC or CCCC 7584 FETCH(r1, 1) @ r1<- BBBB 7585 .if (!1) 7586 and r3, r3, #15 @ r3<- C (or stays CCCC) 7587 .endif 7588 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7589 cmp r2, #0 @ is "this" null? 7590 beq common_errNullObject @ null "this", throw exception 7591 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7592 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7593 EXPORT_PC() @ invoke must export 7594 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7595 bl common_invokeMethodRange @ continue on 7596 7597 7598/* ------------------------------ */ 7599 .balign 64 7600.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7601/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7602 /* 7603 * Handle an optimized "super" method call. 7604 * 7605 * for: [opt] invoke-super-quick, invoke-super-quick/range 7606 */ 7607 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7608 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7609 FETCH(r10, 2) @ r10<- GFED or CCCC 7610 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7611 .if (!0) 7612 and r10, r10, #15 @ r10<- D (or stays CCCC) 7613 .endif 7614 FETCH(r1, 1) @ r1<- BBBB 7615 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7616 EXPORT_PC() @ must export for invoke 7617 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7618 GET_VREG(r3, r10) @ r3<- "this" 7619 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7620 cmp r3, #0 @ null "this" ref? 7621 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7622 beq common_errNullObject @ "this" is null, throw exception 7623 bl common_invokeMethodNoRange @ continue on 7624 7625/* ------------------------------ */ 7626 .balign 64 7627.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7628/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7629/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7630 /* 7631 * Handle an optimized "super" method call. 7632 * 7633 * for: [opt] invoke-super-quick, invoke-super-quick/range 7634 */ 7635 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7636 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7637 FETCH(r10, 2) @ r10<- GFED or CCCC 7638 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7639 .if (!1) 7640 and r10, r10, #15 @ r10<- D (or stays CCCC) 7641 .endif 7642 FETCH(r1, 1) @ r1<- BBBB 7643 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7644 EXPORT_PC() @ must export for invoke 7645 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7646 GET_VREG(r3, r10) @ r3<- "this" 7647 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7648 cmp r3, #0 @ null "this" ref? 7649 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7650 beq common_errNullObject @ "this" is null, throw exception 7651 bl common_invokeMethodRange @ continue on 7652 7653 7654/* ------------------------------ */ 7655 .balign 64 7656.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ 7657/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */ 7658/* File: armv5te/OP_IPUT_OBJECT.S */ 7659 /* 7660 * 32-bit instance field put. 7661 * 7662 * for: iput-object, iput-object-volatile 7663 */ 7664 /* op vA, vB, field@CCCC */ 7665 mov r0, rINST, lsr #12 @ r0<- B 7666 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7667 FETCH(r1, 1) @ r1<- field ref CCCC 7668 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7669 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7670 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7671 cmp r0, #0 @ is resolved entry null? 7672 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ no, already resolved 76738: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7674 EXPORT_PC() @ resolve() could throw 7675 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7676 bl dvmResolveInstField @ r0<- resolved InstField ptr 7677 cmp r0, #0 @ success? 7678 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ yes, finish up 7679 b common_exceptionThrown 7680 7681 7682/* ------------------------------ */ 7683 .balign 64 7684.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ 7685/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */ 7686/* File: armv5te/OP_SGET.S */ 7687 /* 7688 * General 32-bit SGET handler. 7689 * 7690 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7691 */ 7692 /* op vAA, field@BBBB */ 7693 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7694 FETCH(r1, 1) @ r1<- field ref BBBB 7695 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7696 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7697 cmp r0, #0 @ is resolved entry null? 7698 beq .LOP_SGET_OBJECT_VOLATILE_resolve @ yes, do resolve 7699.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0 7700 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7701 SMP_DMB @ acquiring load 7702 mov r2, rINST, lsr #8 @ r2<- AA 7703 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7704 SET_VREG(r1, r2) @ fp[AA]<- r1 7705 GET_INST_OPCODE(ip) @ extract opcode from rINST 7706 GOTO_OPCODE(ip) @ jump to next instruction 7707 7708 7709/* ------------------------------ */ 7710 .balign 64 7711.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ 7712/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */ 7713/* File: armv5te/OP_SPUT_OBJECT.S */ 7714 /* 7715 * 32-bit SPUT handler for objects 7716 * 7717 * for: sput-object, sput-object-volatile 7718 */ 7719 /* op vAA, field@BBBB */ 7720 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7721 FETCH(r1, 1) @ r1<- field ref BBBB 7722 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7723 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7724 cmp r0, #0 @ is resolved entry null? 7725 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ no, continue 7726 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 7727 EXPORT_PC() @ resolve() could throw, so export now 7728 ldr r0, [r9, #offMethod_clazz] @ r0<- method->clazz 7729 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 7730 cmp r0, #0 @ success? 7731 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish 7732 b common_exceptionThrown @ no, handle exception 7733 7734 7735 7736/* ------------------------------ */ 7737 .balign 64 7738.L_OP_DISPATCH_FF: /* 0xff */ 7739/* File: armv5te/OP_DISPATCH_FF.S */ 7740 mov ip, rINST, lsr #8 @ r9<- extended opcode 7741 add ip, ip, #256 @ add offset for extended opcodes 7742 GOTO_OPCODE(ip) @ go to proper extended handler 7743 7744 7745/* ------------------------------ */ 7746 .balign 64 7747.L_OP_CONST_CLASS_JUMBO: /* 0x100 */ 7748/* File: armv5te/OP_CONST_CLASS_JUMBO.S */ 7749 /* const-class/jumbo vBBBB, Class@AAAAAAAA */ 7750 FETCH(r0, 1) @ r0<- aaaa (lo) 7751 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 7752 FETCH(r1, 2) @ r1<- AAAA (hi) 7753 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 7754 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 7755 FETCH(r9, 3) @ r9<- BBBB 7756 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[AAAAaaaa] 7757 cmp r0, #0 @ not yet resolved? 7758 beq .LOP_CONST_CLASS_JUMBO_resolve 7759 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 7760 GET_INST_OPCODE(ip) @ extract opcode from rINST 7761 SET_VREG(r0, r9) @ vBBBB<- r0 7762 GOTO_OPCODE(ip) @ jump to next instruction 7763 7764/* ------------------------------ */ 7765 .balign 64 7766.L_OP_CHECK_CAST_JUMBO: /* 0x101 */ 7767/* File: armv5te/OP_CHECK_CAST_JUMBO.S */ 7768 /* 7769 * Check to see if a cast from one class to another is allowed. 7770 */ 7771 /* check-cast/jumbo vBBBB, class@AAAAAAAA */ 7772 FETCH(r0, 1) @ r0<- aaaa (lo) 7773 FETCH(r2, 2) @ r2<- AAAA (hi) 7774 FETCH(r3, 3) @ r3<- BBBB 7775 orr r2, r0, r2, lsl #16 @ r2<- AAAAaaaa 7776 GET_VREG(r9, r3) @ r9<- object 7777 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 7778 cmp r9, #0 @ is object null? 7779 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 7780 beq .LOP_CHECK_CAST_JUMBO_okay @ null obj, cast always succeeds 7781 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 7782 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7783 cmp r1, #0 @ have we resolved this before? 7784 beq .LOP_CHECK_CAST_JUMBO_resolve @ not resolved, do it now 7785.LOP_CHECK_CAST_JUMBO_resolved: 7786 cmp r0, r1 @ same class (trivial success)? 7787 bne .LOP_CHECK_CAST_JUMBO_fullcheck @ no, do full check 7788 b .LOP_CHECK_CAST_JUMBO_okay @ yes, finish up 7789 7790/* ------------------------------ */ 7791 .balign 64 7792.L_OP_INSTANCE_OF_JUMBO: /* 0x102 */ 7793/* File: armv5te/OP_INSTANCE_OF_JUMBO.S */ 7794 /* 7795 * Check to see if an object reference is an instance of a class. 7796 * 7797 * Most common situation is a non-null object, being compared against 7798 * an already-resolved class. 7799 * 7800 * TODO: convert most of this into a common subroutine, shared with 7801 * OP_INSTANCE_OF.S. 7802 */ 7803 /* instance-of/jumbo vBBBB, vCCCC, class@AAAAAAAA */ 7804 FETCH(r3, 4) @ r3<- vCCCC 7805 FETCH(r9, 3) @ r9<- vBBBB 7806 GET_VREG(r0, r3) @ r0<- vCCCC (object) 7807 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 7808 cmp r0, #0 @ is object null? 7809 beq .LOP_INSTANCE_OF_JUMBO_store @ null obj, not an instance, store r0 7810 FETCH(r1, 1) @ r1<- aaaa (lo) 7811 FETCH(r3, 2) @ r3<- AAAA (hi) 7812 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 7813 orr r3, r1, r3, lsl #16 @ r3<- AAAAaaaa 7814 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 7815 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7816 cmp r1, #0 @ have we resolved this before? 7817 beq .LOP_INSTANCE_OF_JUMBO_resolve @ not resolved, do it now 7818 b .LOP_INSTANCE_OF_JUMBO_resolved @ resolved, continue 7819 7820/* ------------------------------ */ 7821 .balign 64 7822.L_OP_NEW_INSTANCE_JUMBO: /* 0x103 */ 7823/* File: armv5te/OP_NEW_INSTANCE_JUMBO.S */ 7824 /* 7825 * Create a new instance of a class. 7826 */ 7827 /* new-instance/jumbo vBBBB, class@AAAAAAAA */ 7828 FETCH(r0, 1) @ r0<- aaaa (lo) 7829 FETCH(r1, 2) @ r1<- AAAA (hi) 7830 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 7831 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 7832 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 7833 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 7834 EXPORT_PC() @ req'd for init, resolve, alloc 7835 cmp r0, #0 @ already resolved? 7836 beq .LOP_NEW_INSTANCE_JUMBO_resolve @ no, resolve it now 7837.LOP_NEW_INSTANCE_JUMBO_resolved: @ r0=class 7838 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 7839 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 7840 bne .LOP_NEW_INSTANCE_JUMBO_needinit @ no, init class now 7841.LOP_NEW_INSTANCE_JUMBO_initialized: @ r0=class 7842 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 7843 bl dvmAllocObject @ r0<- new object 7844 b .LOP_NEW_INSTANCE_JUMBO_finish @ continue 7845 7846/* ------------------------------ */ 7847 .balign 64 7848.L_OP_NEW_ARRAY_JUMBO: /* 0x104 */ 7849/* File: armv5te/OP_NEW_ARRAY_JUMBO.S */ 7850 /* 7851 * Allocate an array of objects, specified with the array class 7852 * and a count. 7853 * 7854 * The verifier guarantees that this is an array class, so we don't 7855 * check for it here. 7856 */ 7857 /* new-array/jumbo vBBBB, vCCCC, class@AAAAAAAA */ 7858 FETCH(r2, 1) @ r2<- aaaa (lo) 7859 FETCH(r3, 2) @ r3<- AAAA (hi) 7860 FETCH(r0, 4) @ r0<- vCCCC 7861 orr r2, r2, r3, lsl #16 @ r2<- AAAAaaaa 7862 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 7863 GET_VREG(r1, r0) @ r1<- vCCCC (array length) 7864 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 7865 cmp r1, #0 @ check length 7866 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 7867 bmi common_errNegativeArraySize @ negative length, bail 7868 cmp r0, #0 @ already resolved? 7869 EXPORT_PC() @ req'd for resolve, alloc 7870 bne .LOP_NEW_ARRAY_JUMBO_finish @ resolved, continue 7871 b .LOP_NEW_ARRAY_JUMBO_resolve @ do resolve now 7872 7873/* ------------------------------ */ 7874 .balign 64 7875.L_OP_FILLED_NEW_ARRAY_JUMBO: /* 0x105 */ 7876/* File: armv5te/OP_FILLED_NEW_ARRAY_JUMBO.S */ 7877 /* 7878 * Create a new array with elements filled from registers. 7879 * 7880 * TODO: convert most of this into a common subroutine, shared with 7881 * OP_FILLED_NEW_ARRAY.S. 7882 */ 7883 /* filled-new-array/jumbo {vCCCC..v(CCCC+BBBB-1)}, type@AAAAAAAA */ 7884 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 7885 FETCH(r0, 1) @ r0<- aaaa (lo) 7886 FETCH(r1, 2) @ r1<- AAAA (hi) 7887 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 7888 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 7889 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 7890 EXPORT_PC() @ need for resolve and alloc 7891 cmp r0, #0 @ already resolved? 7892 bne .LOP_FILLED_NEW_ARRAY_JUMBO_continue @ yes, continue on 78938: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7894 mov r2, #0 @ r2<- false 7895 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7896 bl dvmResolveClass @ r0<- call(clazz, ref) 7897 cmp r0, #0 @ got null? 7898 beq common_exceptionThrown @ yes, handle exception 7899 b .LOP_FILLED_NEW_ARRAY_JUMBO_continue 7900 7901/* ------------------------------ */ 7902 .balign 64 7903.L_OP_IGET_JUMBO: /* 0x106 */ 7904/* File: armv5te/OP_IGET_JUMBO.S */ 7905 /* 7906 * Jumbo 32-bit instance field get. 7907 * 7908 * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo, 7909 * iget-char/jumbo, iget-short/jumbo 7910 */ 7911 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 7912 FETCH(r1, 1) @ r1<- aaaa (lo) 7913 FETCH(r2, 2) @ r2<- AAAA (hi) 7914 FETCH(r0, 4) @ r0<- CCCC 7915 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7916 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 7917 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7918 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 7919 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7920 cmp r0, #0 @ is resolved entry null? 7921 bne .LOP_IGET_JUMBO_finish @ no, already resolved 79228: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7923 EXPORT_PC() @ resolve() could throw 7924 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7925 bl dvmResolveInstField @ r0<- resolved InstField ptr 7926 b .LOP_IGET_JUMBO_resolved @ resolved, continue 7927 7928/* ------------------------------ */ 7929 .balign 64 7930.L_OP_IGET_WIDE_JUMBO: /* 0x107 */ 7931/* File: armv5te/OP_IGET_WIDE_JUMBO.S */ 7932 /* 7933 * Jumbo 64-bit instance field get. 7934 */ 7935 /* iget-wide/jumbo vBBBB, vCCCC, field@AAAAAAAA */ 7936 FETCH(r1, 1) @ r1<- aaaa (lo) 7937 FETCH(r2, 2) @ r2<- AAAA (hi) 7938 FETCH(r0, 4) @ r0<- CCCC 7939 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7940 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 7941 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7942 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 7943 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7944 cmp r0, #0 @ is resolved entry null? 7945 bne .LOP_IGET_WIDE_JUMBO_finish @ no, already resolved 79468: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7947 EXPORT_PC() @ resolve() could throw 7948 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7949 bl dvmResolveInstField @ r0<- resolved InstField ptr 7950 b .LOP_IGET_WIDE_JUMBO_resolved @ resolved, continue 7951 7952/* ------------------------------ */ 7953 .balign 64 7954.L_OP_IGET_OBJECT_JUMBO: /* 0x108 */ 7955/* File: armv5te/OP_IGET_OBJECT_JUMBO.S */ 7956/* File: armv5te/OP_IGET_JUMBO.S */ 7957 /* 7958 * Jumbo 32-bit instance field get. 7959 * 7960 * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo, 7961 * iget-char/jumbo, iget-short/jumbo 7962 */ 7963 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 7964 FETCH(r1, 1) @ r1<- aaaa (lo) 7965 FETCH(r2, 2) @ r2<- AAAA (hi) 7966 FETCH(r0, 4) @ r0<- CCCC 7967 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7968 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 7969 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7970 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 7971 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7972 cmp r0, #0 @ is resolved entry null? 7973 bne .LOP_IGET_OBJECT_JUMBO_finish @ no, already resolved 79748: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7975 EXPORT_PC() @ resolve() could throw 7976 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7977 bl dvmResolveInstField @ r0<- resolved InstField ptr 7978 b .LOP_IGET_OBJECT_JUMBO_resolved @ resolved, continue 7979 7980 7981/* ------------------------------ */ 7982 .balign 64 7983.L_OP_IGET_BOOLEAN_JUMBO: /* 0x109 */ 7984/* File: armv5te/OP_IGET_BOOLEAN_JUMBO.S */ 7985@include "armv5te/OP_IGET_JUMBO.S" { "load":"ldrb", "sqnum":"1" } 7986/* File: armv5te/OP_IGET_JUMBO.S */ 7987 /* 7988 * Jumbo 32-bit instance field get. 7989 * 7990 * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo, 7991 * iget-char/jumbo, iget-short/jumbo 7992 */ 7993 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 7994 FETCH(r1, 1) @ r1<- aaaa (lo) 7995 FETCH(r2, 2) @ r2<- AAAA (hi) 7996 FETCH(r0, 4) @ r0<- CCCC 7997 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7998 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 7999 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8000 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8001 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8002 cmp r0, #0 @ is resolved entry null? 8003 bne .LOP_IGET_BOOLEAN_JUMBO_finish @ no, already resolved 80048: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8005 EXPORT_PC() @ resolve() could throw 8006 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8007 bl dvmResolveInstField @ r0<- resolved InstField ptr 8008 b .LOP_IGET_BOOLEAN_JUMBO_resolved @ resolved, continue 8009 8010 8011/* ------------------------------ */ 8012 .balign 64 8013.L_OP_IGET_BYTE_JUMBO: /* 0x10a */ 8014/* File: armv5te/OP_IGET_BYTE_JUMBO.S */ 8015@include "armv5te/OP_IGET_JUMBO.S" { "load":"ldrsb", "sqnum":"2" } 8016/* File: armv5te/OP_IGET_JUMBO.S */ 8017 /* 8018 * Jumbo 32-bit instance field get. 8019 * 8020 * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo, 8021 * iget-char/jumbo, iget-short/jumbo 8022 */ 8023 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8024 FETCH(r1, 1) @ r1<- aaaa (lo) 8025 FETCH(r2, 2) @ r2<- AAAA (hi) 8026 FETCH(r0, 4) @ r0<- CCCC 8027 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8028 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8029 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8030 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8031 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8032 cmp r0, #0 @ is resolved entry null? 8033 bne .LOP_IGET_BYTE_JUMBO_finish @ no, already resolved 80348: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8035 EXPORT_PC() @ resolve() could throw 8036 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8037 bl dvmResolveInstField @ r0<- resolved InstField ptr 8038 b .LOP_IGET_BYTE_JUMBO_resolved @ resolved, continue 8039 8040 8041/* ------------------------------ */ 8042 .balign 64 8043.L_OP_IGET_CHAR_JUMBO: /* 0x10b */ 8044/* File: armv5te/OP_IGET_CHAR_JUMBO.S */ 8045@include "armv5te/OP_IGET_JUMBO.S" { "load":"ldrh", "sqnum":"3" } 8046/* File: armv5te/OP_IGET_JUMBO.S */ 8047 /* 8048 * Jumbo 32-bit instance field get. 8049 * 8050 * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo, 8051 * iget-char/jumbo, iget-short/jumbo 8052 */ 8053 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8054 FETCH(r1, 1) @ r1<- aaaa (lo) 8055 FETCH(r2, 2) @ r2<- AAAA (hi) 8056 FETCH(r0, 4) @ r0<- CCCC 8057 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8058 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8059 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8060 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8061 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8062 cmp r0, #0 @ is resolved entry null? 8063 bne .LOP_IGET_CHAR_JUMBO_finish @ no, already resolved 80648: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8065 EXPORT_PC() @ resolve() could throw 8066 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8067 bl dvmResolveInstField @ r0<- resolved InstField ptr 8068 b .LOP_IGET_CHAR_JUMBO_resolved @ resolved, continue 8069 8070 8071/* ------------------------------ */ 8072 .balign 64 8073.L_OP_IGET_SHORT_JUMBO: /* 0x10c */ 8074/* File: armv5te/OP_IGET_SHORT_JUMBO.S */ 8075@include "armv5te/OP_IGET_JUMBO.S" { "load":"ldrsh", "sqnum":"4" } 8076/* File: armv5te/OP_IGET_JUMBO.S */ 8077 /* 8078 * Jumbo 32-bit instance field get. 8079 * 8080 * for: iget/jumbo, iget-object/jumbo, iget-boolean/jumbo, iget-byte/jumbo, 8081 * iget-char/jumbo, iget-short/jumbo 8082 */ 8083 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8084 FETCH(r1, 1) @ r1<- aaaa (lo) 8085 FETCH(r2, 2) @ r2<- AAAA (hi) 8086 FETCH(r0, 4) @ r0<- CCCC 8087 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8088 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8089 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8090 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8091 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8092 cmp r0, #0 @ is resolved entry null? 8093 bne .LOP_IGET_SHORT_JUMBO_finish @ no, already resolved 80948: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8095 EXPORT_PC() @ resolve() could throw 8096 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8097 bl dvmResolveInstField @ r0<- resolved InstField ptr 8098 b .LOP_IGET_SHORT_JUMBO_resolved @ resolved, continue 8099 8100 8101/* ------------------------------ */ 8102 .balign 64 8103.L_OP_IPUT_JUMBO: /* 0x10d */ 8104/* File: armv5te/OP_IPUT_JUMBO.S */ 8105 /* 8106 * Jumbo 32-bit instance field put. 8107 * 8108 * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo, 8109 * iput-short/jumbo 8110 */ 8111 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8112 FETCH(r1, 1) @ r1<- aaaa (lo) 8113 FETCH(r2, 2) @ r2<- AAAA (hi) 8114 FETCH(r0, 4) @ r0<- CCCC 8115 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8116 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8117 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8118 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8119 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8120 cmp r0, #0 @ is resolved entry null? 8121 bne .LOP_IPUT_JUMBO_finish @ no, already resolved 81228: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8123 EXPORT_PC() @ resolve() could throw 8124 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8125 bl dvmResolveInstField @ r0<- resolved InstField ptr 8126 b .LOP_IPUT_JUMBO_resolved @ resolved, continue 8127 8128/* ------------------------------ */ 8129 .balign 64 8130.L_OP_IPUT_WIDE_JUMBO: /* 0x10e */ 8131/* File: armv5te/OP_IPUT_WIDE_JUMBO.S */ 8132 /* iput-wide/jumbo vBBBB, vCCCC, field@AAAAAAAA */ 8133 FETCH(r1, 1) @ r1<- aaaa (lo) 8134 FETCH(r2, 2) @ r2<- AAAA (hi) 8135 FETCH(r0, 4) @ r0<- CCCC 8136 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8137 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8138 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 8139 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 8140 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8141 cmp r0, #0 @ is resolved entry null? 8142 bne .LOP_IPUT_WIDE_JUMBO_finish @ no, already resolved 81438: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8144 EXPORT_PC() @ resolve() could throw 8145 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8146 bl dvmResolveInstField @ r0<- resolved InstField ptr 8147 b .LOP_IPUT_WIDE_JUMBO_resolved @ resolved, continue 8148 8149/* ------------------------------ */ 8150 .balign 64 8151.L_OP_IPUT_OBJECT_JUMBO: /* 0x10f */ 8152/* File: armv5te/OP_IPUT_OBJECT_JUMBO.S */ 8153 /* 8154 * Jumbo 32-bit instance field put. 8155 */ 8156 /* iput-object/jumbo vBBBB, vCCCC, field@AAAAAAAA */ 8157 FETCH(r1, 1) @ r1<- aaaa (lo) 8158 FETCH(r2, 2) @ r2<- AAAA (hi) 8159 FETCH(r0, 4) @ r0<- CCCC 8160 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8161 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8162 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8163 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8164 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8165 cmp r0, #0 @ is resolved entry null? 8166 bne .LOP_IPUT_OBJECT_JUMBO_finish @ no, already resolved 81678: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8168 EXPORT_PC() @ resolve() could throw 8169 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8170 bl dvmResolveInstField @ r0<- resolved InstField ptr 8171 b .LOP_IPUT_OBJECT_JUMBO_resolved @ resolved, continue 8172 8173/* ------------------------------ */ 8174 .balign 64 8175.L_OP_IPUT_BOOLEAN_JUMBO: /* 0x110 */ 8176/* File: armv5te/OP_IPUT_BOOLEAN_JUMBO.S */ 8177@include "armv5te/OP_IPUT_JUMBO.S" { "store":"strb", "sqnum":"1" } 8178/* File: armv5te/OP_IPUT_JUMBO.S */ 8179 /* 8180 * Jumbo 32-bit instance field put. 8181 * 8182 * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo, 8183 * iput-short/jumbo 8184 */ 8185 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8186 FETCH(r1, 1) @ r1<- aaaa (lo) 8187 FETCH(r2, 2) @ r2<- AAAA (hi) 8188 FETCH(r0, 4) @ r0<- CCCC 8189 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8190 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8191 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8192 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8193 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8194 cmp r0, #0 @ is resolved entry null? 8195 bne .LOP_IPUT_BOOLEAN_JUMBO_finish @ no, already resolved 81968: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8197 EXPORT_PC() @ resolve() could throw 8198 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8199 bl dvmResolveInstField @ r0<- resolved InstField ptr 8200 b .LOP_IPUT_BOOLEAN_JUMBO_resolved @ resolved, continue 8201 8202 8203/* ------------------------------ */ 8204 .balign 64 8205.L_OP_IPUT_BYTE_JUMBO: /* 0x111 */ 8206/* File: armv5te/OP_IPUT_BYTE_JUMBO.S */ 8207@include "armv5te/OP_IPUT_JUMBO.S" { "store":"strb", "sqnum":"2" } 8208/* File: armv5te/OP_IPUT_JUMBO.S */ 8209 /* 8210 * Jumbo 32-bit instance field put. 8211 * 8212 * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo, 8213 * iput-short/jumbo 8214 */ 8215 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8216 FETCH(r1, 1) @ r1<- aaaa (lo) 8217 FETCH(r2, 2) @ r2<- AAAA (hi) 8218 FETCH(r0, 4) @ r0<- CCCC 8219 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8220 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8221 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8222 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8223 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8224 cmp r0, #0 @ is resolved entry null? 8225 bne .LOP_IPUT_BYTE_JUMBO_finish @ no, already resolved 82268: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8227 EXPORT_PC() @ resolve() could throw 8228 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8229 bl dvmResolveInstField @ r0<- resolved InstField ptr 8230 b .LOP_IPUT_BYTE_JUMBO_resolved @ resolved, continue 8231 8232 8233/* ------------------------------ */ 8234 .balign 64 8235.L_OP_IPUT_CHAR_JUMBO: /* 0x112 */ 8236/* File: armv5te/OP_IPUT_CHAR_JUMBO.S */ 8237@include "armv5te/OP_IPUT_JUMBO.S" { "store":"strh", "sqnum":"3" } 8238/* File: armv5te/OP_IPUT_JUMBO.S */ 8239 /* 8240 * Jumbo 32-bit instance field put. 8241 * 8242 * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo, 8243 * iput-short/jumbo 8244 */ 8245 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8246 FETCH(r1, 1) @ r1<- aaaa (lo) 8247 FETCH(r2, 2) @ r2<- AAAA (hi) 8248 FETCH(r0, 4) @ r0<- CCCC 8249 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8250 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8251 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8252 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8253 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8254 cmp r0, #0 @ is resolved entry null? 8255 bne .LOP_IPUT_CHAR_JUMBO_finish @ no, already resolved 82568: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8257 EXPORT_PC() @ resolve() could throw 8258 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8259 bl dvmResolveInstField @ r0<- resolved InstField ptr 8260 b .LOP_IPUT_CHAR_JUMBO_resolved @ resolved, continue 8261 8262 8263/* ------------------------------ */ 8264 .balign 64 8265.L_OP_IPUT_SHORT_JUMBO: /* 0x113 */ 8266/* File: armv5te/OP_IPUT_SHORT_JUMBO.S */ 8267@include "armv5te/OP_IPUT_JUMBO.S" { "store":"strh", "sqnum":"4" } 8268/* File: armv5te/OP_IPUT_JUMBO.S */ 8269 /* 8270 * Jumbo 32-bit instance field put. 8271 * 8272 * for: iput/jumbo, iput-boolean/jumbo, iput-byte/jumbo, iput-char/jumbo, 8273 * iput-short/jumbo 8274 */ 8275 /* exop vBBBB, vCCCC, field@AAAAAAAA */ 8276 FETCH(r1, 1) @ r1<- aaaa (lo) 8277 FETCH(r2, 2) @ r2<- AAAA (hi) 8278 FETCH(r0, 4) @ r0<- CCCC 8279 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 8280 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8281 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 8282 GET_VREG(r9, r0) @ r9<- fp[CCCC], the object pointer 8283 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 8284 cmp r0, #0 @ is resolved entry null? 8285 bne .LOP_IPUT_SHORT_JUMBO_finish @ no, already resolved 82868: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8287 EXPORT_PC() @ resolve() could throw 8288 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8289 bl dvmResolveInstField @ r0<- resolved InstField ptr 8290 b .LOP_IPUT_SHORT_JUMBO_resolved @ resolved, continue 8291 8292 8293/* ------------------------------ */ 8294 .balign 64 8295.L_OP_SGET_JUMBO: /* 0x114 */ 8296/* File: armv5te/OP_SGET_JUMBO.S */ 8297 /* 8298 * Jumbo 32-bit SGET handler. 8299 * 8300 * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo, 8301 * sget-char/jumbo, sget-short/jumbo 8302 */ 8303 /* exop vBBBB, field@AAAAAAAA */ 8304 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8305 FETCH(r0, 1) @ r0<- aaaa (lo) 8306 FETCH(r1, 2) @ r1<- AAAA (hi) 8307 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8308 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8309 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8310 cmp r0, #0 @ is resolved entry null? 8311 beq .LOP_SGET_JUMBO_resolve @ yes, do resolve 8312.LOP_SGET_JUMBO_finish: @ field ptr in r0 8313 ldr r1, [r0, #offStaticField_value] @ r1<- field value 8314 @ no-op @ acquiring load 8315 FETCH(r2, 3) @ r2<- BBBB 8316 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8317 SET_VREG(r1, r2) @ fp[BBBB]<- r1 8318 GET_INST_OPCODE(ip) @ extract opcode from rINST 8319 GOTO_OPCODE(ip) @ jump to next instruction 8320 8321/* ------------------------------ */ 8322 .balign 64 8323.L_OP_SGET_WIDE_JUMBO: /* 0x115 */ 8324/* File: armv5te/OP_SGET_WIDE_JUMBO.S */ 8325 /* 8326 * Jumbo 64-bit SGET handler. 8327 */ 8328 /* sget-wide/jumbo vBBBB, field@AAAAAAAA */ 8329 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8330 FETCH(r0, 1) @ r0<- aaaa (lo) 8331 FETCH(r1, 2) @ r1<- AAAA (hi) 8332 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8333 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8334 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8335 cmp r0, #0 @ is resolved entry null? 8336 beq .LOP_SGET_WIDE_JUMBO_resolve @ yes, do resolve 8337.LOP_SGET_WIDE_JUMBO_finish: 8338 FETCH(r9, 3) @ r9<- BBBB 8339 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 8340 add r9, rFP, r9, lsl #2 @ r9<- &fp[BBBB] 8341 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8342 stmia r9, {r0-r1} @ vBBBB/vBBBB+1<- r0/r1 8343 GET_INST_OPCODE(ip) @ extract opcode from rINST 8344 GOTO_OPCODE(ip) @ jump to next instruction 8345 8346/* ------------------------------ */ 8347 .balign 64 8348.L_OP_SGET_OBJECT_JUMBO: /* 0x116 */ 8349/* File: armv5te/OP_SGET_OBJECT_JUMBO.S */ 8350/* File: armv5te/OP_SGET_JUMBO.S */ 8351 /* 8352 * Jumbo 32-bit SGET handler. 8353 * 8354 * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo, 8355 * sget-char/jumbo, sget-short/jumbo 8356 */ 8357 /* exop vBBBB, field@AAAAAAAA */ 8358 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8359 FETCH(r0, 1) @ r0<- aaaa (lo) 8360 FETCH(r1, 2) @ r1<- AAAA (hi) 8361 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8362 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8363 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8364 cmp r0, #0 @ is resolved entry null? 8365 beq .LOP_SGET_OBJECT_JUMBO_resolve @ yes, do resolve 8366.LOP_SGET_OBJECT_JUMBO_finish: @ field ptr in r0 8367 ldr r1, [r0, #offStaticField_value] @ r1<- field value 8368 @ no-op @ acquiring load 8369 FETCH(r2, 3) @ r2<- BBBB 8370 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8371 SET_VREG(r1, r2) @ fp[BBBB]<- r1 8372 GET_INST_OPCODE(ip) @ extract opcode from rINST 8373 GOTO_OPCODE(ip) @ jump to next instruction 8374 8375 8376/* ------------------------------ */ 8377 .balign 64 8378.L_OP_SGET_BOOLEAN_JUMBO: /* 0x117 */ 8379/* File: armv5te/OP_SGET_BOOLEAN_JUMBO.S */ 8380/* File: armv5te/OP_SGET_JUMBO.S */ 8381 /* 8382 * Jumbo 32-bit SGET handler. 8383 * 8384 * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo, 8385 * sget-char/jumbo, sget-short/jumbo 8386 */ 8387 /* exop vBBBB, field@AAAAAAAA */ 8388 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8389 FETCH(r0, 1) @ r0<- aaaa (lo) 8390 FETCH(r1, 2) @ r1<- AAAA (hi) 8391 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8392 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8393 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8394 cmp r0, #0 @ is resolved entry null? 8395 beq .LOP_SGET_BOOLEAN_JUMBO_resolve @ yes, do resolve 8396.LOP_SGET_BOOLEAN_JUMBO_finish: @ field ptr in r0 8397 ldr r1, [r0, #offStaticField_value] @ r1<- field value 8398 @ no-op @ acquiring load 8399 FETCH(r2, 3) @ r2<- BBBB 8400 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8401 SET_VREG(r1, r2) @ fp[BBBB]<- r1 8402 GET_INST_OPCODE(ip) @ extract opcode from rINST 8403 GOTO_OPCODE(ip) @ jump to next instruction 8404 8405 8406/* ------------------------------ */ 8407 .balign 64 8408.L_OP_SGET_BYTE_JUMBO: /* 0x118 */ 8409/* File: armv5te/OP_SGET_BYTE_JUMBO.S */ 8410/* File: armv5te/OP_SGET_JUMBO.S */ 8411 /* 8412 * Jumbo 32-bit SGET handler. 8413 * 8414 * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo, 8415 * sget-char/jumbo, sget-short/jumbo 8416 */ 8417 /* exop vBBBB, field@AAAAAAAA */ 8418 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8419 FETCH(r0, 1) @ r0<- aaaa (lo) 8420 FETCH(r1, 2) @ r1<- AAAA (hi) 8421 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8422 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8423 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8424 cmp r0, #0 @ is resolved entry null? 8425 beq .LOP_SGET_BYTE_JUMBO_resolve @ yes, do resolve 8426.LOP_SGET_BYTE_JUMBO_finish: @ field ptr in r0 8427 ldr r1, [r0, #offStaticField_value] @ r1<- field value 8428 @ no-op @ acquiring load 8429 FETCH(r2, 3) @ r2<- BBBB 8430 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8431 SET_VREG(r1, r2) @ fp[BBBB]<- r1 8432 GET_INST_OPCODE(ip) @ extract opcode from rINST 8433 GOTO_OPCODE(ip) @ jump to next instruction 8434 8435 8436/* ------------------------------ */ 8437 .balign 64 8438.L_OP_SGET_CHAR_JUMBO: /* 0x119 */ 8439/* File: armv5te/OP_SGET_CHAR_JUMBO.S */ 8440/* File: armv5te/OP_SGET_JUMBO.S */ 8441 /* 8442 * Jumbo 32-bit SGET handler. 8443 * 8444 * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo, 8445 * sget-char/jumbo, sget-short/jumbo 8446 */ 8447 /* exop vBBBB, field@AAAAAAAA */ 8448 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8449 FETCH(r0, 1) @ r0<- aaaa (lo) 8450 FETCH(r1, 2) @ r1<- AAAA (hi) 8451 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8452 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8453 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8454 cmp r0, #0 @ is resolved entry null? 8455 beq .LOP_SGET_CHAR_JUMBO_resolve @ yes, do resolve 8456.LOP_SGET_CHAR_JUMBO_finish: @ field ptr in r0 8457 ldr r1, [r0, #offStaticField_value] @ r1<- field value 8458 @ no-op @ acquiring load 8459 FETCH(r2, 3) @ r2<- BBBB 8460 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8461 SET_VREG(r1, r2) @ fp[BBBB]<- r1 8462 GET_INST_OPCODE(ip) @ extract opcode from rINST 8463 GOTO_OPCODE(ip) @ jump to next instruction 8464 8465 8466/* ------------------------------ */ 8467 .balign 64 8468.L_OP_SGET_SHORT_JUMBO: /* 0x11a */ 8469/* File: armv5te/OP_SGET_SHORT_JUMBO.S */ 8470/* File: armv5te/OP_SGET_JUMBO.S */ 8471 /* 8472 * Jumbo 32-bit SGET handler. 8473 * 8474 * for: sget/jumbo, sget-object/jumbo, sget-boolean/jumbo, sget-byte/jumbo, 8475 * sget-char/jumbo, sget-short/jumbo 8476 */ 8477 /* exop vBBBB, field@AAAAAAAA */ 8478 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8479 FETCH(r0, 1) @ r0<- aaaa (lo) 8480 FETCH(r1, 2) @ r1<- AAAA (hi) 8481 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8482 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8483 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8484 cmp r0, #0 @ is resolved entry null? 8485 beq .LOP_SGET_SHORT_JUMBO_resolve @ yes, do resolve 8486.LOP_SGET_SHORT_JUMBO_finish: @ field ptr in r0 8487 ldr r1, [r0, #offStaticField_value] @ r1<- field value 8488 @ no-op @ acquiring load 8489 FETCH(r2, 3) @ r2<- BBBB 8490 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8491 SET_VREG(r1, r2) @ fp[BBBB]<- r1 8492 GET_INST_OPCODE(ip) @ extract opcode from rINST 8493 GOTO_OPCODE(ip) @ jump to next instruction 8494 8495 8496/* ------------------------------ */ 8497 .balign 64 8498.L_OP_SPUT_JUMBO: /* 0x11b */ 8499/* File: armv5te/OP_SPUT_JUMBO.S */ 8500 /* 8501 * Jumbo 32-bit SPUT handler. 8502 * 8503 * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo, 8504 * sput-short/jumbo 8505 */ 8506 /* exop vBBBB, field@AAAAAAAA */ 8507 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8508 FETCH(r0, 1) @ r0<- aaaa (lo) 8509 FETCH(r1, 2) @ r1<- AAAA (hi) 8510 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8511 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8512 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8513 cmp r0, #0 @ is resolved entry null? 8514 beq .LOP_SPUT_JUMBO_resolve @ yes, do resolve 8515.LOP_SPUT_JUMBO_finish: @ field ptr in r0 8516 FETCH(r2, 3) @ r2<- BBBB 8517 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8518 GET_VREG(r1, r2) @ r1<- fp[BBBB] 8519 GET_INST_OPCODE(ip) @ extract opcode from rINST 8520 @ no-op @ releasing store 8521 str r1, [r0, #offStaticField_value] @ field<- vBBBB 8522 GOTO_OPCODE(ip) @ jump to next instruction 8523 8524/* ------------------------------ */ 8525 .balign 64 8526.L_OP_SPUT_WIDE_JUMBO: /* 0x11c */ 8527/* File: armv5te/OP_SPUT_WIDE_JUMBO.S */ 8528 /* 8529 * Jumbo 64-bit SPUT handler. 8530 */ 8531 /* sput-wide/jumbo vBBBB, field@AAAAAAAA */ 8532 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 8533 FETCH(r1, 1) @ r1<- aaaa (lo) 8534 FETCH(r2, 2) @ r2<- AAAA (hi) 8535 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 8536 orr r1, r1, r2, lsl #16 @ r1<- AAAAaaaa 8537 FETCH(r9, 3) @ r9<- BBBB 8538 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 8539 add r9, rFP, r9, lsl #2 @ r9<- &fp[BBBB] 8540 cmp r2, #0 @ is resolved entry null? 8541 beq .LOP_SPUT_WIDE_JUMBO_resolve @ yes, do resolve 8542.LOP_SPUT_WIDE_JUMBO_finish: @ field ptr in r2, BBBB in r9 8543 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8544 ldmia r9, {r0-r1} @ r0/r1<- vBBBB/vBBBB+1 8545 GET_INST_OPCODE(r10) @ extract opcode from rINST 8546 strd r0, [r2, #offStaticField_value] @ field<- vBBBB/vBBBB+1 8547 GOTO_OPCODE(r10) @ jump to next instruction 8548 8549/* ------------------------------ */ 8550 .balign 64 8551.L_OP_SPUT_OBJECT_JUMBO: /* 0x11d */ 8552/* File: armv5te/OP_SPUT_OBJECT_JUMBO.S */ 8553 /* 8554 * Jumbo 32-bit SPUT handler for objects 8555 */ 8556 /* sput-object/jumbo vBBBB, field@AAAAAAAA */ 8557 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8558 FETCH(r0, 1) @ r0<- aaaa (lo) 8559 FETCH(r1, 2) @ r1<- AAAA (hi) 8560 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8561 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8562 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8563 cmp r0, #0 @ is resolved entry null? 8564 bne .LOP_SPUT_OBJECT_JUMBO_finish @ no, continue 8565 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 8566 EXPORT_PC() @ resolve() could throw, so export now 8567 ldr r0, [r9, #offMethod_clazz] @ r0<- method->clazz 8568 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8569 cmp r0, #0 @ success? 8570 bne .LOP_SPUT_OBJECT_JUMBO_finish @ yes, finish 8571 b common_exceptionThrown @ no, handle exception 8572 8573/* ------------------------------ */ 8574 .balign 64 8575.L_OP_SPUT_BOOLEAN_JUMBO: /* 0x11e */ 8576/* File: armv5te/OP_SPUT_BOOLEAN_JUMBO.S */ 8577/* File: armv5te/OP_SPUT_JUMBO.S */ 8578 /* 8579 * Jumbo 32-bit SPUT handler. 8580 * 8581 * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo, 8582 * sput-short/jumbo 8583 */ 8584 /* exop vBBBB, field@AAAAAAAA */ 8585 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8586 FETCH(r0, 1) @ r0<- aaaa (lo) 8587 FETCH(r1, 2) @ r1<- AAAA (hi) 8588 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8589 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8590 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8591 cmp r0, #0 @ is resolved entry null? 8592 beq .LOP_SPUT_BOOLEAN_JUMBO_resolve @ yes, do resolve 8593.LOP_SPUT_BOOLEAN_JUMBO_finish: @ field ptr in r0 8594 FETCH(r2, 3) @ r2<- BBBB 8595 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8596 GET_VREG(r1, r2) @ r1<- fp[BBBB] 8597 GET_INST_OPCODE(ip) @ extract opcode from rINST 8598 @ no-op @ releasing store 8599 str r1, [r0, #offStaticField_value] @ field<- vBBBB 8600 GOTO_OPCODE(ip) @ jump to next instruction 8601 8602 8603/* ------------------------------ */ 8604 .balign 64 8605.L_OP_SPUT_BYTE_JUMBO: /* 0x11f */ 8606/* File: armv5te/OP_SPUT_BYTE_JUMBO.S */ 8607/* File: armv5te/OP_SPUT_JUMBO.S */ 8608 /* 8609 * Jumbo 32-bit SPUT handler. 8610 * 8611 * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo, 8612 * sput-short/jumbo 8613 */ 8614 /* exop vBBBB, field@AAAAAAAA */ 8615 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8616 FETCH(r0, 1) @ r0<- aaaa (lo) 8617 FETCH(r1, 2) @ r1<- AAAA (hi) 8618 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8619 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8620 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8621 cmp r0, #0 @ is resolved entry null? 8622 beq .LOP_SPUT_BYTE_JUMBO_resolve @ yes, do resolve 8623.LOP_SPUT_BYTE_JUMBO_finish: @ field ptr in r0 8624 FETCH(r2, 3) @ r2<- BBBB 8625 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8626 GET_VREG(r1, r2) @ r1<- fp[BBBB] 8627 GET_INST_OPCODE(ip) @ extract opcode from rINST 8628 @ no-op @ releasing store 8629 str r1, [r0, #offStaticField_value] @ field<- vBBBB 8630 GOTO_OPCODE(ip) @ jump to next instruction 8631 8632 8633/* ------------------------------ */ 8634 .balign 64 8635.L_OP_SPUT_CHAR_JUMBO: /* 0x120 */ 8636/* File: armv5te/OP_SPUT_CHAR_JUMBO.S */ 8637/* File: armv5te/OP_SPUT_JUMBO.S */ 8638 /* 8639 * Jumbo 32-bit SPUT handler. 8640 * 8641 * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo, 8642 * sput-short/jumbo 8643 */ 8644 /* exop vBBBB, field@AAAAAAAA */ 8645 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8646 FETCH(r0, 1) @ r0<- aaaa (lo) 8647 FETCH(r1, 2) @ r1<- AAAA (hi) 8648 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8649 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8650 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8651 cmp r0, #0 @ is resolved entry null? 8652 beq .LOP_SPUT_CHAR_JUMBO_resolve @ yes, do resolve 8653.LOP_SPUT_CHAR_JUMBO_finish: @ field ptr in r0 8654 FETCH(r2, 3) @ r2<- BBBB 8655 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8656 GET_VREG(r1, r2) @ r1<- fp[BBBB] 8657 GET_INST_OPCODE(ip) @ extract opcode from rINST 8658 @ no-op @ releasing store 8659 str r1, [r0, #offStaticField_value] @ field<- vBBBB 8660 GOTO_OPCODE(ip) @ jump to next instruction 8661 8662 8663/* ------------------------------ */ 8664 .balign 64 8665.L_OP_SPUT_SHORT_JUMBO: /* 0x121 */ 8666/* File: armv5te/OP_SPUT_SHORT_JUMBO.S */ 8667/* File: armv5te/OP_SPUT_JUMBO.S */ 8668 /* 8669 * Jumbo 32-bit SPUT handler. 8670 * 8671 * for: sput/jumbo, sput-boolean/jumbo, sput-byte/jumbo, sput-char/jumbo, 8672 * sput-short/jumbo 8673 */ 8674 /* exop vBBBB, field@AAAAAAAA */ 8675 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 8676 FETCH(r0, 1) @ r0<- aaaa (lo) 8677 FETCH(r1, 2) @ r1<- AAAA (hi) 8678 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 8679 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8680 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 8681 cmp r0, #0 @ is resolved entry null? 8682 beq .LOP_SPUT_SHORT_JUMBO_resolve @ yes, do resolve 8683.LOP_SPUT_SHORT_JUMBO_finish: @ field ptr in r0 8684 FETCH(r2, 3) @ r2<- BBBB 8685 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 8686 GET_VREG(r1, r2) @ r1<- fp[BBBB] 8687 GET_INST_OPCODE(ip) @ extract opcode from rINST 8688 @ no-op @ releasing store 8689 str r1, [r0, #offStaticField_value] @ field<- vBBBB 8690 GOTO_OPCODE(ip) @ jump to next instruction 8691 8692 8693/* ------------------------------ */ 8694 .balign 64 8695.L_OP_INVOKE_VIRTUAL_JUMBO: /* 0x122 */ 8696/* File: armv5te/OP_INVOKE_VIRTUAL_JUMBO.S */ 8697 /* 8698 * Handle a virtual method call. 8699 */ 8700 /* invoke-virtual/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */ 8701 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 8702 FETCH(r0, 1) @ r1<- aaaa (lo) 8703 FETCH(r1, 2) @ r1<- AAAA (hi) 8704 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 8705 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8706 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 8707 cmp r0, #0 @ already resolved? 8708 EXPORT_PC() @ must export for invoke 8709 bne .LOP_INVOKE_VIRTUAL_JUMBO_continue @ yes, continue on 8710 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8711 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8712 mov r2, #METHOD_VIRTUAL @ resolver method type 8713 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8714 cmp r0, #0 @ got null? 8715 bne .LOP_INVOKE_VIRTUAL_JUMBO_continue @ no, continue 8716 b common_exceptionThrown @ yes, handle exception 8717 8718/* ------------------------------ */ 8719 .balign 64 8720.L_OP_INVOKE_SUPER_JUMBO: /* 0x123 */ 8721/* File: armv5te/OP_INVOKE_SUPER_JUMBO.S */ 8722 /* 8723 * Handle a "super" method call. 8724 */ 8725 /* invoke-super/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */ 8726 FETCH(r10, 4) @ r10<- CCCC 8727 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 8728 FETCH(r0, 1) @ r1<- aaaa (lo) 8729 FETCH(r1, 2) @ r1<- AAAA (hi) 8730 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 8731 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8732 GET_VREG(r2, r10) @ r2<- "this" ptr 8733 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 8734 cmp r2, #0 @ null "this"? 8735 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 8736 beq common_errNullObject @ null "this", throw exception 8737 cmp r0, #0 @ already resolved? 8738 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 8739 EXPORT_PC() @ must export for invoke 8740 bne .LOP_INVOKE_SUPER_JUMBO_continue @ resolved, continue on 8741 b .LOP_INVOKE_SUPER_JUMBO_resolve @ do resolve now 8742 8743/* ------------------------------ */ 8744 .balign 64 8745.L_OP_INVOKE_DIRECT_JUMBO: /* 0x124 */ 8746/* File: armv5te/OP_INVOKE_DIRECT_JUMBO.S */ 8747 /* 8748 * Handle a direct method call. 8749 * 8750 * (We could defer the "is 'this' pointer null" test to the common 8751 * method invocation code, and use a flag to indicate that static 8752 * calls don't count. If we do this as part of copying the arguments 8753 * out we could avoiding loading the first arg twice.) 8754 * 8755 */ 8756 /* invoke-direct/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */ 8757 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 8758 FETCH(r0, 1) @ r1<- aaaa (lo) 8759 FETCH(r1, 2) @ r1<- AAAA (hi) 8760 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 8761 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8762 FETCH(r10, 4) @ r10<- CCCC 8763 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 8764 cmp r0, #0 @ already resolved? 8765 EXPORT_PC() @ must export for invoke 8766 GET_VREG(r2, r10) @ r2<- "this" ptr 8767 beq .LOP_INVOKE_DIRECT_JUMBO_resolve @ not resolved, do it now 8768.LOP_INVOKE_DIRECT_JUMBO_finish: 8769 cmp r2, #0 @ null "this" ref? 8770 bne common_invokeMethodJumbo @ no, continue on 8771 b common_errNullObject @ yes, throw exception 8772 8773/* ------------------------------ */ 8774 .balign 64 8775.L_OP_INVOKE_STATIC_JUMBO: /* 0x125 */ 8776/* File: armv5te/OP_INVOKE_STATIC_JUMBO.S */ 8777 /* 8778 * Handle a static method call. 8779 */ 8780 /* invoke-static/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */ 8781 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 8782 FETCH(r0, 1) @ r1<- aaaa (lo) 8783 FETCH(r1, 2) @ r1<- AAAA (hi) 8784 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 8785 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8786 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 8787 cmp r0, #0 @ already resolved? 8788 EXPORT_PC() @ must export for invoke 8789 bne common_invokeMethodJumbo @ yes, continue on 87900: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8791 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8792 mov r2, #METHOD_STATIC @ resolver method type 8793 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8794 cmp r0, #0 @ got null? 8795 bne common_invokeMethodJumbo @ no, continue 8796 b common_exceptionThrown @ yes, handle exception 8797 8798/* ------------------------------ */ 8799 .balign 64 8800.L_OP_INVOKE_INTERFACE_JUMBO: /* 0x126 */ 8801/* File: armv5te/OP_INVOKE_INTERFACE_JUMBO.S */ 8802 /* 8803 * Handle an interface method call. 8804 */ 8805 /* invoke-interface/jumbo {vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA */ 8806 FETCH(r2, 4) @ r2<- CCCC 8807 FETCH(r0, 1) @ r0<- aaaa (lo) 8808 FETCH(r1, 2) @ r1<- AAAA (hi) 8809 EXPORT_PC() @ must export for invoke 8810 orr r1, r0, r1, lsl #16 @ r1<- AAAAaaaa 8811 GET_VREG(r0, r2) @ r0<- first arg ("this") 8812 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 8813 cmp r0, #0 @ null obj? 8814 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 8815 beq common_errNullObject @ yes, fail 8816 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 8817 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 8818 cmp r0, #0 @ failed? 8819 beq common_exceptionThrown @ yes, handle exception 8820 b common_invokeMethodJumbo @ jump to common handler 8821 8822/* ------------------------------ */ 8823 .balign 64 8824.L_OP_UNUSED_27FF: /* 0x127 */ 8825/* File: armv5te/OP_UNUSED_27FF.S */ 8826/* File: armv5te/unused.S */ 8827 bl common_abort 8828 8829 8830/* ------------------------------ */ 8831 .balign 64 8832.L_OP_UNUSED_28FF: /* 0x128 */ 8833/* File: armv5te/OP_UNUSED_28FF.S */ 8834/* File: armv5te/unused.S */ 8835 bl common_abort 8836 8837 8838/* ------------------------------ */ 8839 .balign 64 8840.L_OP_UNUSED_29FF: /* 0x129 */ 8841/* File: armv5te/OP_UNUSED_29FF.S */ 8842/* File: armv5te/unused.S */ 8843 bl common_abort 8844 8845 8846/* ------------------------------ */ 8847 .balign 64 8848.L_OP_UNUSED_2AFF: /* 0x12a */ 8849/* File: armv5te/OP_UNUSED_2AFF.S */ 8850/* File: armv5te/unused.S */ 8851 bl common_abort 8852 8853 8854/* ------------------------------ */ 8855 .balign 64 8856.L_OP_UNUSED_2BFF: /* 0x12b */ 8857/* File: armv5te/OP_UNUSED_2BFF.S */ 8858/* File: armv5te/unused.S */ 8859 bl common_abort 8860 8861 8862/* ------------------------------ */ 8863 .balign 64 8864.L_OP_UNUSED_2CFF: /* 0x12c */ 8865/* File: armv5te/OP_UNUSED_2CFF.S */ 8866/* File: armv5te/unused.S */ 8867 bl common_abort 8868 8869 8870/* ------------------------------ */ 8871 .balign 64 8872.L_OP_UNUSED_2DFF: /* 0x12d */ 8873/* File: armv5te/OP_UNUSED_2DFF.S */ 8874/* File: armv5te/unused.S */ 8875 bl common_abort 8876 8877 8878/* ------------------------------ */ 8879 .balign 64 8880.L_OP_UNUSED_2EFF: /* 0x12e */ 8881/* File: armv5te/OP_UNUSED_2EFF.S */ 8882/* File: armv5te/unused.S */ 8883 bl common_abort 8884 8885 8886/* ------------------------------ */ 8887 .balign 64 8888.L_OP_UNUSED_2FFF: /* 0x12f */ 8889/* File: armv5te/OP_UNUSED_2FFF.S */ 8890/* File: armv5te/unused.S */ 8891 bl common_abort 8892 8893 8894/* ------------------------------ */ 8895 .balign 64 8896.L_OP_UNUSED_30FF: /* 0x130 */ 8897/* File: armv5te/OP_UNUSED_30FF.S */ 8898/* File: armv5te/unused.S */ 8899 bl common_abort 8900 8901 8902/* ------------------------------ */ 8903 .balign 64 8904.L_OP_UNUSED_31FF: /* 0x131 */ 8905/* File: armv5te/OP_UNUSED_31FF.S */ 8906/* File: armv5te/unused.S */ 8907 bl common_abort 8908 8909 8910/* ------------------------------ */ 8911 .balign 64 8912.L_OP_UNUSED_32FF: /* 0x132 */ 8913/* File: armv5te/OP_UNUSED_32FF.S */ 8914/* File: armv5te/unused.S */ 8915 bl common_abort 8916 8917 8918/* ------------------------------ */ 8919 .balign 64 8920.L_OP_UNUSED_33FF: /* 0x133 */ 8921/* File: armv5te/OP_UNUSED_33FF.S */ 8922/* File: armv5te/unused.S */ 8923 bl common_abort 8924 8925 8926/* ------------------------------ */ 8927 .balign 64 8928.L_OP_UNUSED_34FF: /* 0x134 */ 8929/* File: armv5te/OP_UNUSED_34FF.S */ 8930/* File: armv5te/unused.S */ 8931 bl common_abort 8932 8933 8934/* ------------------------------ */ 8935 .balign 64 8936.L_OP_UNUSED_35FF: /* 0x135 */ 8937/* File: armv5te/OP_UNUSED_35FF.S */ 8938/* File: armv5te/unused.S */ 8939 bl common_abort 8940 8941 8942/* ------------------------------ */ 8943 .balign 64 8944.L_OP_UNUSED_36FF: /* 0x136 */ 8945/* File: armv5te/OP_UNUSED_36FF.S */ 8946/* File: armv5te/unused.S */ 8947 bl common_abort 8948 8949 8950/* ------------------------------ */ 8951 .balign 64 8952.L_OP_UNUSED_37FF: /* 0x137 */ 8953/* File: armv5te/OP_UNUSED_37FF.S */ 8954/* File: armv5te/unused.S */ 8955 bl common_abort 8956 8957 8958/* ------------------------------ */ 8959 .balign 64 8960.L_OP_UNUSED_38FF: /* 0x138 */ 8961/* File: armv5te/OP_UNUSED_38FF.S */ 8962/* File: armv5te/unused.S */ 8963 bl common_abort 8964 8965 8966/* ------------------------------ */ 8967 .balign 64 8968.L_OP_UNUSED_39FF: /* 0x139 */ 8969/* File: armv5te/OP_UNUSED_39FF.S */ 8970/* File: armv5te/unused.S */ 8971 bl common_abort 8972 8973 8974/* ------------------------------ */ 8975 .balign 64 8976.L_OP_UNUSED_3AFF: /* 0x13a */ 8977/* File: armv5te/OP_UNUSED_3AFF.S */ 8978/* File: armv5te/unused.S */ 8979 bl common_abort 8980 8981 8982/* ------------------------------ */ 8983 .balign 64 8984.L_OP_UNUSED_3BFF: /* 0x13b */ 8985/* File: armv5te/OP_UNUSED_3BFF.S */ 8986/* File: armv5te/unused.S */ 8987 bl common_abort 8988 8989 8990/* ------------------------------ */ 8991 .balign 64 8992.L_OP_UNUSED_3CFF: /* 0x13c */ 8993/* File: armv5te/OP_UNUSED_3CFF.S */ 8994/* File: armv5te/unused.S */ 8995 bl common_abort 8996 8997 8998/* ------------------------------ */ 8999 .balign 64 9000.L_OP_UNUSED_3DFF: /* 0x13d */ 9001/* File: armv5te/OP_UNUSED_3DFF.S */ 9002/* File: armv5te/unused.S */ 9003 bl common_abort 9004 9005 9006/* ------------------------------ */ 9007 .balign 64 9008.L_OP_UNUSED_3EFF: /* 0x13e */ 9009/* File: armv5te/OP_UNUSED_3EFF.S */ 9010/* File: armv5te/unused.S */ 9011 bl common_abort 9012 9013 9014/* ------------------------------ */ 9015 .balign 64 9016.L_OP_UNUSED_3FFF: /* 0x13f */ 9017/* File: armv5te/OP_UNUSED_3FFF.S */ 9018/* File: armv5te/unused.S */ 9019 bl common_abort 9020 9021 9022/* ------------------------------ */ 9023 .balign 64 9024.L_OP_UNUSED_40FF: /* 0x140 */ 9025/* File: armv5te/OP_UNUSED_40FF.S */ 9026/* File: armv5te/unused.S */ 9027 bl common_abort 9028 9029 9030/* ------------------------------ */ 9031 .balign 64 9032.L_OP_UNUSED_41FF: /* 0x141 */ 9033/* File: armv5te/OP_UNUSED_41FF.S */ 9034/* File: armv5te/unused.S */ 9035 bl common_abort 9036 9037 9038/* ------------------------------ */ 9039 .balign 64 9040.L_OP_UNUSED_42FF: /* 0x142 */ 9041/* File: armv5te/OP_UNUSED_42FF.S */ 9042/* File: armv5te/unused.S */ 9043 bl common_abort 9044 9045 9046/* ------------------------------ */ 9047 .balign 64 9048.L_OP_UNUSED_43FF: /* 0x143 */ 9049/* File: armv5te/OP_UNUSED_43FF.S */ 9050/* File: armv5te/unused.S */ 9051 bl common_abort 9052 9053 9054/* ------------------------------ */ 9055 .balign 64 9056.L_OP_UNUSED_44FF: /* 0x144 */ 9057/* File: armv5te/OP_UNUSED_44FF.S */ 9058/* File: armv5te/unused.S */ 9059 bl common_abort 9060 9061 9062/* ------------------------------ */ 9063 .balign 64 9064.L_OP_UNUSED_45FF: /* 0x145 */ 9065/* File: armv5te/OP_UNUSED_45FF.S */ 9066/* File: armv5te/unused.S */ 9067 bl common_abort 9068 9069 9070/* ------------------------------ */ 9071 .balign 64 9072.L_OP_UNUSED_46FF: /* 0x146 */ 9073/* File: armv5te/OP_UNUSED_46FF.S */ 9074/* File: armv5te/unused.S */ 9075 bl common_abort 9076 9077 9078/* ------------------------------ */ 9079 .balign 64 9080.L_OP_UNUSED_47FF: /* 0x147 */ 9081/* File: armv5te/OP_UNUSED_47FF.S */ 9082/* File: armv5te/unused.S */ 9083 bl common_abort 9084 9085 9086/* ------------------------------ */ 9087 .balign 64 9088.L_OP_UNUSED_48FF: /* 0x148 */ 9089/* File: armv5te/OP_UNUSED_48FF.S */ 9090/* File: armv5te/unused.S */ 9091 bl common_abort 9092 9093 9094/* ------------------------------ */ 9095 .balign 64 9096.L_OP_UNUSED_49FF: /* 0x149 */ 9097/* File: armv5te/OP_UNUSED_49FF.S */ 9098/* File: armv5te/unused.S */ 9099 bl common_abort 9100 9101 9102/* ------------------------------ */ 9103 .balign 64 9104.L_OP_UNUSED_4AFF: /* 0x14a */ 9105/* File: armv5te/OP_UNUSED_4AFF.S */ 9106/* File: armv5te/unused.S */ 9107 bl common_abort 9108 9109 9110/* ------------------------------ */ 9111 .balign 64 9112.L_OP_UNUSED_4BFF: /* 0x14b */ 9113/* File: armv5te/OP_UNUSED_4BFF.S */ 9114/* File: armv5te/unused.S */ 9115 bl common_abort 9116 9117 9118/* ------------------------------ */ 9119 .balign 64 9120.L_OP_UNUSED_4CFF: /* 0x14c */ 9121/* File: armv5te/OP_UNUSED_4CFF.S */ 9122/* File: armv5te/unused.S */ 9123 bl common_abort 9124 9125 9126/* ------------------------------ */ 9127 .balign 64 9128.L_OP_UNUSED_4DFF: /* 0x14d */ 9129/* File: armv5te/OP_UNUSED_4DFF.S */ 9130/* File: armv5te/unused.S */ 9131 bl common_abort 9132 9133 9134/* ------------------------------ */ 9135 .balign 64 9136.L_OP_UNUSED_4EFF: /* 0x14e */ 9137/* File: armv5te/OP_UNUSED_4EFF.S */ 9138/* File: armv5te/unused.S */ 9139 bl common_abort 9140 9141 9142/* ------------------------------ */ 9143 .balign 64 9144.L_OP_UNUSED_4FFF: /* 0x14f */ 9145/* File: armv5te/OP_UNUSED_4FFF.S */ 9146/* File: armv5te/unused.S */ 9147 bl common_abort 9148 9149 9150/* ------------------------------ */ 9151 .balign 64 9152.L_OP_UNUSED_50FF: /* 0x150 */ 9153/* File: armv5te/OP_UNUSED_50FF.S */ 9154/* File: armv5te/unused.S */ 9155 bl common_abort 9156 9157 9158/* ------------------------------ */ 9159 .balign 64 9160.L_OP_UNUSED_51FF: /* 0x151 */ 9161/* File: armv5te/OP_UNUSED_51FF.S */ 9162/* File: armv5te/unused.S */ 9163 bl common_abort 9164 9165 9166/* ------------------------------ */ 9167 .balign 64 9168.L_OP_UNUSED_52FF: /* 0x152 */ 9169/* File: armv5te/OP_UNUSED_52FF.S */ 9170/* File: armv5te/unused.S */ 9171 bl common_abort 9172 9173 9174/* ------------------------------ */ 9175 .balign 64 9176.L_OP_UNUSED_53FF: /* 0x153 */ 9177/* File: armv5te/OP_UNUSED_53FF.S */ 9178/* File: armv5te/unused.S */ 9179 bl common_abort 9180 9181 9182/* ------------------------------ */ 9183 .balign 64 9184.L_OP_UNUSED_54FF: /* 0x154 */ 9185/* File: armv5te/OP_UNUSED_54FF.S */ 9186/* File: armv5te/unused.S */ 9187 bl common_abort 9188 9189 9190/* ------------------------------ */ 9191 .balign 64 9192.L_OP_UNUSED_55FF: /* 0x155 */ 9193/* File: armv5te/OP_UNUSED_55FF.S */ 9194/* File: armv5te/unused.S */ 9195 bl common_abort 9196 9197 9198/* ------------------------------ */ 9199 .balign 64 9200.L_OP_UNUSED_56FF: /* 0x156 */ 9201/* File: armv5te/OP_UNUSED_56FF.S */ 9202/* File: armv5te/unused.S */ 9203 bl common_abort 9204 9205 9206/* ------------------------------ */ 9207 .balign 64 9208.L_OP_UNUSED_57FF: /* 0x157 */ 9209/* File: armv5te/OP_UNUSED_57FF.S */ 9210/* File: armv5te/unused.S */ 9211 bl common_abort 9212 9213 9214/* ------------------------------ */ 9215 .balign 64 9216.L_OP_UNUSED_58FF: /* 0x158 */ 9217/* File: armv5te/OP_UNUSED_58FF.S */ 9218/* File: armv5te/unused.S */ 9219 bl common_abort 9220 9221 9222/* ------------------------------ */ 9223 .balign 64 9224.L_OP_UNUSED_59FF: /* 0x159 */ 9225/* File: armv5te/OP_UNUSED_59FF.S */ 9226/* File: armv5te/unused.S */ 9227 bl common_abort 9228 9229 9230/* ------------------------------ */ 9231 .balign 64 9232.L_OP_UNUSED_5AFF: /* 0x15a */ 9233/* File: armv5te/OP_UNUSED_5AFF.S */ 9234/* File: armv5te/unused.S */ 9235 bl common_abort 9236 9237 9238/* ------------------------------ */ 9239 .balign 64 9240.L_OP_UNUSED_5BFF: /* 0x15b */ 9241/* File: armv5te/OP_UNUSED_5BFF.S */ 9242/* File: armv5te/unused.S */ 9243 bl common_abort 9244 9245 9246/* ------------------------------ */ 9247 .balign 64 9248.L_OP_UNUSED_5CFF: /* 0x15c */ 9249/* File: armv5te/OP_UNUSED_5CFF.S */ 9250/* File: armv5te/unused.S */ 9251 bl common_abort 9252 9253 9254/* ------------------------------ */ 9255 .balign 64 9256.L_OP_UNUSED_5DFF: /* 0x15d */ 9257/* File: armv5te/OP_UNUSED_5DFF.S */ 9258/* File: armv5te/unused.S */ 9259 bl common_abort 9260 9261 9262/* ------------------------------ */ 9263 .balign 64 9264.L_OP_UNUSED_5EFF: /* 0x15e */ 9265/* File: armv5te/OP_UNUSED_5EFF.S */ 9266/* File: armv5te/unused.S */ 9267 bl common_abort 9268 9269 9270/* ------------------------------ */ 9271 .balign 64 9272.L_OP_UNUSED_5FFF: /* 0x15f */ 9273/* File: armv5te/OP_UNUSED_5FFF.S */ 9274/* File: armv5te/unused.S */ 9275 bl common_abort 9276 9277 9278/* ------------------------------ */ 9279 .balign 64 9280.L_OP_UNUSED_60FF: /* 0x160 */ 9281/* File: armv5te/OP_UNUSED_60FF.S */ 9282/* File: armv5te/unused.S */ 9283 bl common_abort 9284 9285 9286/* ------------------------------ */ 9287 .balign 64 9288.L_OP_UNUSED_61FF: /* 0x161 */ 9289/* File: armv5te/OP_UNUSED_61FF.S */ 9290/* File: armv5te/unused.S */ 9291 bl common_abort 9292 9293 9294/* ------------------------------ */ 9295 .balign 64 9296.L_OP_UNUSED_62FF: /* 0x162 */ 9297/* File: armv5te/OP_UNUSED_62FF.S */ 9298/* File: armv5te/unused.S */ 9299 bl common_abort 9300 9301 9302/* ------------------------------ */ 9303 .balign 64 9304.L_OP_UNUSED_63FF: /* 0x163 */ 9305/* File: armv5te/OP_UNUSED_63FF.S */ 9306/* File: armv5te/unused.S */ 9307 bl common_abort 9308 9309 9310/* ------------------------------ */ 9311 .balign 64 9312.L_OP_UNUSED_64FF: /* 0x164 */ 9313/* File: armv5te/OP_UNUSED_64FF.S */ 9314/* File: armv5te/unused.S */ 9315 bl common_abort 9316 9317 9318/* ------------------------------ */ 9319 .balign 64 9320.L_OP_UNUSED_65FF: /* 0x165 */ 9321/* File: armv5te/OP_UNUSED_65FF.S */ 9322/* File: armv5te/unused.S */ 9323 bl common_abort 9324 9325 9326/* ------------------------------ */ 9327 .balign 64 9328.L_OP_UNUSED_66FF: /* 0x166 */ 9329/* File: armv5te/OP_UNUSED_66FF.S */ 9330/* File: armv5te/unused.S */ 9331 bl common_abort 9332 9333 9334/* ------------------------------ */ 9335 .balign 64 9336.L_OP_UNUSED_67FF: /* 0x167 */ 9337/* File: armv5te/OP_UNUSED_67FF.S */ 9338/* File: armv5te/unused.S */ 9339 bl common_abort 9340 9341 9342/* ------------------------------ */ 9343 .balign 64 9344.L_OP_UNUSED_68FF: /* 0x168 */ 9345/* File: armv5te/OP_UNUSED_68FF.S */ 9346/* File: armv5te/unused.S */ 9347 bl common_abort 9348 9349 9350/* ------------------------------ */ 9351 .balign 64 9352.L_OP_UNUSED_69FF: /* 0x169 */ 9353/* File: armv5te/OP_UNUSED_69FF.S */ 9354/* File: armv5te/unused.S */ 9355 bl common_abort 9356 9357 9358/* ------------------------------ */ 9359 .balign 64 9360.L_OP_UNUSED_6AFF: /* 0x16a */ 9361/* File: armv5te/OP_UNUSED_6AFF.S */ 9362/* File: armv5te/unused.S */ 9363 bl common_abort 9364 9365 9366/* ------------------------------ */ 9367 .balign 64 9368.L_OP_UNUSED_6BFF: /* 0x16b */ 9369/* File: armv5te/OP_UNUSED_6BFF.S */ 9370/* File: armv5te/unused.S */ 9371 bl common_abort 9372 9373 9374/* ------------------------------ */ 9375 .balign 64 9376.L_OP_UNUSED_6CFF: /* 0x16c */ 9377/* File: armv5te/OP_UNUSED_6CFF.S */ 9378/* File: armv5te/unused.S */ 9379 bl common_abort 9380 9381 9382/* ------------------------------ */ 9383 .balign 64 9384.L_OP_UNUSED_6DFF: /* 0x16d */ 9385/* File: armv5te/OP_UNUSED_6DFF.S */ 9386/* File: armv5te/unused.S */ 9387 bl common_abort 9388 9389 9390/* ------------------------------ */ 9391 .balign 64 9392.L_OP_UNUSED_6EFF: /* 0x16e */ 9393/* File: armv5te/OP_UNUSED_6EFF.S */ 9394/* File: armv5te/unused.S */ 9395 bl common_abort 9396 9397 9398/* ------------------------------ */ 9399 .balign 64 9400.L_OP_UNUSED_6FFF: /* 0x16f */ 9401/* File: armv5te/OP_UNUSED_6FFF.S */ 9402/* File: armv5te/unused.S */ 9403 bl common_abort 9404 9405 9406/* ------------------------------ */ 9407 .balign 64 9408.L_OP_UNUSED_70FF: /* 0x170 */ 9409/* File: armv5te/OP_UNUSED_70FF.S */ 9410/* File: armv5te/unused.S */ 9411 bl common_abort 9412 9413 9414/* ------------------------------ */ 9415 .balign 64 9416.L_OP_UNUSED_71FF: /* 0x171 */ 9417/* File: armv5te/OP_UNUSED_71FF.S */ 9418/* File: armv5te/unused.S */ 9419 bl common_abort 9420 9421 9422/* ------------------------------ */ 9423 .balign 64 9424.L_OP_UNUSED_72FF: /* 0x172 */ 9425/* File: armv5te/OP_UNUSED_72FF.S */ 9426/* File: armv5te/unused.S */ 9427 bl common_abort 9428 9429 9430/* ------------------------------ */ 9431 .balign 64 9432.L_OP_UNUSED_73FF: /* 0x173 */ 9433/* File: armv5te/OP_UNUSED_73FF.S */ 9434/* File: armv5te/unused.S */ 9435 bl common_abort 9436 9437 9438/* ------------------------------ */ 9439 .balign 64 9440.L_OP_UNUSED_74FF: /* 0x174 */ 9441/* File: armv5te/OP_UNUSED_74FF.S */ 9442/* File: armv5te/unused.S */ 9443 bl common_abort 9444 9445 9446/* ------------------------------ */ 9447 .balign 64 9448.L_OP_UNUSED_75FF: /* 0x175 */ 9449/* File: armv5te/OP_UNUSED_75FF.S */ 9450/* File: armv5te/unused.S */ 9451 bl common_abort 9452 9453 9454/* ------------------------------ */ 9455 .balign 64 9456.L_OP_UNUSED_76FF: /* 0x176 */ 9457/* File: armv5te/OP_UNUSED_76FF.S */ 9458/* File: armv5te/unused.S */ 9459 bl common_abort 9460 9461 9462/* ------------------------------ */ 9463 .balign 64 9464.L_OP_UNUSED_77FF: /* 0x177 */ 9465/* File: armv5te/OP_UNUSED_77FF.S */ 9466/* File: armv5te/unused.S */ 9467 bl common_abort 9468 9469 9470/* ------------------------------ */ 9471 .balign 64 9472.L_OP_UNUSED_78FF: /* 0x178 */ 9473/* File: armv5te/OP_UNUSED_78FF.S */ 9474/* File: armv5te/unused.S */ 9475 bl common_abort 9476 9477 9478/* ------------------------------ */ 9479 .balign 64 9480.L_OP_UNUSED_79FF: /* 0x179 */ 9481/* File: armv5te/OP_UNUSED_79FF.S */ 9482/* File: armv5te/unused.S */ 9483 bl common_abort 9484 9485 9486/* ------------------------------ */ 9487 .balign 64 9488.L_OP_UNUSED_7AFF: /* 0x17a */ 9489/* File: armv5te/OP_UNUSED_7AFF.S */ 9490/* File: armv5te/unused.S */ 9491 bl common_abort 9492 9493 9494/* ------------------------------ */ 9495 .balign 64 9496.L_OP_UNUSED_7BFF: /* 0x17b */ 9497/* File: armv5te/OP_UNUSED_7BFF.S */ 9498/* File: armv5te/unused.S */ 9499 bl common_abort 9500 9501 9502/* ------------------------------ */ 9503 .balign 64 9504.L_OP_UNUSED_7CFF: /* 0x17c */ 9505/* File: armv5te/OP_UNUSED_7CFF.S */ 9506/* File: armv5te/unused.S */ 9507 bl common_abort 9508 9509 9510/* ------------------------------ */ 9511 .balign 64 9512.L_OP_UNUSED_7DFF: /* 0x17d */ 9513/* File: armv5te/OP_UNUSED_7DFF.S */ 9514/* File: armv5te/unused.S */ 9515 bl common_abort 9516 9517 9518/* ------------------------------ */ 9519 .balign 64 9520.L_OP_UNUSED_7EFF: /* 0x17e */ 9521/* File: armv5te/OP_UNUSED_7EFF.S */ 9522/* File: armv5te/unused.S */ 9523 bl common_abort 9524 9525 9526/* ------------------------------ */ 9527 .balign 64 9528.L_OP_UNUSED_7FFF: /* 0x17f */ 9529/* File: armv5te/OP_UNUSED_7FFF.S */ 9530/* File: armv5te/unused.S */ 9531 bl common_abort 9532 9533 9534/* ------------------------------ */ 9535 .balign 64 9536.L_OP_UNUSED_80FF: /* 0x180 */ 9537/* File: armv5te/OP_UNUSED_80FF.S */ 9538/* File: armv5te/unused.S */ 9539 bl common_abort 9540 9541 9542/* ------------------------------ */ 9543 .balign 64 9544.L_OP_UNUSED_81FF: /* 0x181 */ 9545/* File: armv5te/OP_UNUSED_81FF.S */ 9546/* File: armv5te/unused.S */ 9547 bl common_abort 9548 9549 9550/* ------------------------------ */ 9551 .balign 64 9552.L_OP_UNUSED_82FF: /* 0x182 */ 9553/* File: armv5te/OP_UNUSED_82FF.S */ 9554/* File: armv5te/unused.S */ 9555 bl common_abort 9556 9557 9558/* ------------------------------ */ 9559 .balign 64 9560.L_OP_UNUSED_83FF: /* 0x183 */ 9561/* File: armv5te/OP_UNUSED_83FF.S */ 9562/* File: armv5te/unused.S */ 9563 bl common_abort 9564 9565 9566/* ------------------------------ */ 9567 .balign 64 9568.L_OP_UNUSED_84FF: /* 0x184 */ 9569/* File: armv5te/OP_UNUSED_84FF.S */ 9570/* File: armv5te/unused.S */ 9571 bl common_abort 9572 9573 9574/* ------------------------------ */ 9575 .balign 64 9576.L_OP_UNUSED_85FF: /* 0x185 */ 9577/* File: armv5te/OP_UNUSED_85FF.S */ 9578/* File: armv5te/unused.S */ 9579 bl common_abort 9580 9581 9582/* ------------------------------ */ 9583 .balign 64 9584.L_OP_UNUSED_86FF: /* 0x186 */ 9585/* File: armv5te/OP_UNUSED_86FF.S */ 9586/* File: armv5te/unused.S */ 9587 bl common_abort 9588 9589 9590/* ------------------------------ */ 9591 .balign 64 9592.L_OP_UNUSED_87FF: /* 0x187 */ 9593/* File: armv5te/OP_UNUSED_87FF.S */ 9594/* File: armv5te/unused.S */ 9595 bl common_abort 9596 9597 9598/* ------------------------------ */ 9599 .balign 64 9600.L_OP_UNUSED_88FF: /* 0x188 */ 9601/* File: armv5te/OP_UNUSED_88FF.S */ 9602/* File: armv5te/unused.S */ 9603 bl common_abort 9604 9605 9606/* ------------------------------ */ 9607 .balign 64 9608.L_OP_UNUSED_89FF: /* 0x189 */ 9609/* File: armv5te/OP_UNUSED_89FF.S */ 9610/* File: armv5te/unused.S */ 9611 bl common_abort 9612 9613 9614/* ------------------------------ */ 9615 .balign 64 9616.L_OP_UNUSED_8AFF: /* 0x18a */ 9617/* File: armv5te/OP_UNUSED_8AFF.S */ 9618/* File: armv5te/unused.S */ 9619 bl common_abort 9620 9621 9622/* ------------------------------ */ 9623 .balign 64 9624.L_OP_UNUSED_8BFF: /* 0x18b */ 9625/* File: armv5te/OP_UNUSED_8BFF.S */ 9626/* File: armv5te/unused.S */ 9627 bl common_abort 9628 9629 9630/* ------------------------------ */ 9631 .balign 64 9632.L_OP_UNUSED_8CFF: /* 0x18c */ 9633/* File: armv5te/OP_UNUSED_8CFF.S */ 9634/* File: armv5te/unused.S */ 9635 bl common_abort 9636 9637 9638/* ------------------------------ */ 9639 .balign 64 9640.L_OP_UNUSED_8DFF: /* 0x18d */ 9641/* File: armv5te/OP_UNUSED_8DFF.S */ 9642/* File: armv5te/unused.S */ 9643 bl common_abort 9644 9645 9646/* ------------------------------ */ 9647 .balign 64 9648.L_OP_UNUSED_8EFF: /* 0x18e */ 9649/* File: armv5te/OP_UNUSED_8EFF.S */ 9650/* File: armv5te/unused.S */ 9651 bl common_abort 9652 9653 9654/* ------------------------------ */ 9655 .balign 64 9656.L_OP_UNUSED_8FFF: /* 0x18f */ 9657/* File: armv5te/OP_UNUSED_8FFF.S */ 9658/* File: armv5te/unused.S */ 9659 bl common_abort 9660 9661 9662/* ------------------------------ */ 9663 .balign 64 9664.L_OP_UNUSED_90FF: /* 0x190 */ 9665/* File: armv5te/OP_UNUSED_90FF.S */ 9666/* File: armv5te/unused.S */ 9667 bl common_abort 9668 9669 9670/* ------------------------------ */ 9671 .balign 64 9672.L_OP_UNUSED_91FF: /* 0x191 */ 9673/* File: armv5te/OP_UNUSED_91FF.S */ 9674/* File: armv5te/unused.S */ 9675 bl common_abort 9676 9677 9678/* ------------------------------ */ 9679 .balign 64 9680.L_OP_UNUSED_92FF: /* 0x192 */ 9681/* File: armv5te/OP_UNUSED_92FF.S */ 9682/* File: armv5te/unused.S */ 9683 bl common_abort 9684 9685 9686/* ------------------------------ */ 9687 .balign 64 9688.L_OP_UNUSED_93FF: /* 0x193 */ 9689/* File: armv5te/OP_UNUSED_93FF.S */ 9690/* File: armv5te/unused.S */ 9691 bl common_abort 9692 9693 9694/* ------------------------------ */ 9695 .balign 64 9696.L_OP_UNUSED_94FF: /* 0x194 */ 9697/* File: armv5te/OP_UNUSED_94FF.S */ 9698/* File: armv5te/unused.S */ 9699 bl common_abort 9700 9701 9702/* ------------------------------ */ 9703 .balign 64 9704.L_OP_UNUSED_95FF: /* 0x195 */ 9705/* File: armv5te/OP_UNUSED_95FF.S */ 9706/* File: armv5te/unused.S */ 9707 bl common_abort 9708 9709 9710/* ------------------------------ */ 9711 .balign 64 9712.L_OP_UNUSED_96FF: /* 0x196 */ 9713/* File: armv5te/OP_UNUSED_96FF.S */ 9714/* File: armv5te/unused.S */ 9715 bl common_abort 9716 9717 9718/* ------------------------------ */ 9719 .balign 64 9720.L_OP_UNUSED_97FF: /* 0x197 */ 9721/* File: armv5te/OP_UNUSED_97FF.S */ 9722/* File: armv5te/unused.S */ 9723 bl common_abort 9724 9725 9726/* ------------------------------ */ 9727 .balign 64 9728.L_OP_UNUSED_98FF: /* 0x198 */ 9729/* File: armv5te/OP_UNUSED_98FF.S */ 9730/* File: armv5te/unused.S */ 9731 bl common_abort 9732 9733 9734/* ------------------------------ */ 9735 .balign 64 9736.L_OP_UNUSED_99FF: /* 0x199 */ 9737/* File: armv5te/OP_UNUSED_99FF.S */ 9738/* File: armv5te/unused.S */ 9739 bl common_abort 9740 9741 9742/* ------------------------------ */ 9743 .balign 64 9744.L_OP_UNUSED_9AFF: /* 0x19a */ 9745/* File: armv5te/OP_UNUSED_9AFF.S */ 9746/* File: armv5te/unused.S */ 9747 bl common_abort 9748 9749 9750/* ------------------------------ */ 9751 .balign 64 9752.L_OP_UNUSED_9BFF: /* 0x19b */ 9753/* File: armv5te/OP_UNUSED_9BFF.S */ 9754/* File: armv5te/unused.S */ 9755 bl common_abort 9756 9757 9758/* ------------------------------ */ 9759 .balign 64 9760.L_OP_UNUSED_9CFF: /* 0x19c */ 9761/* File: armv5te/OP_UNUSED_9CFF.S */ 9762/* File: armv5te/unused.S */ 9763 bl common_abort 9764 9765 9766/* ------------------------------ */ 9767 .balign 64 9768.L_OP_UNUSED_9DFF: /* 0x19d */ 9769/* File: armv5te/OP_UNUSED_9DFF.S */ 9770/* File: armv5te/unused.S */ 9771 bl common_abort 9772 9773 9774/* ------------------------------ */ 9775 .balign 64 9776.L_OP_UNUSED_9EFF: /* 0x19e */ 9777/* File: armv5te/OP_UNUSED_9EFF.S */ 9778/* File: armv5te/unused.S */ 9779 bl common_abort 9780 9781 9782/* ------------------------------ */ 9783 .balign 64 9784.L_OP_UNUSED_9FFF: /* 0x19f */ 9785/* File: armv5te/OP_UNUSED_9FFF.S */ 9786/* File: armv5te/unused.S */ 9787 bl common_abort 9788 9789 9790/* ------------------------------ */ 9791 .balign 64 9792.L_OP_UNUSED_A0FF: /* 0x1a0 */ 9793/* File: armv5te/OP_UNUSED_A0FF.S */ 9794/* File: armv5te/unused.S */ 9795 bl common_abort 9796 9797 9798/* ------------------------------ */ 9799 .balign 64 9800.L_OP_UNUSED_A1FF: /* 0x1a1 */ 9801/* File: armv5te/OP_UNUSED_A1FF.S */ 9802/* File: armv5te/unused.S */ 9803 bl common_abort 9804 9805 9806/* ------------------------------ */ 9807 .balign 64 9808.L_OP_UNUSED_A2FF: /* 0x1a2 */ 9809/* File: armv5te/OP_UNUSED_A2FF.S */ 9810/* File: armv5te/unused.S */ 9811 bl common_abort 9812 9813 9814/* ------------------------------ */ 9815 .balign 64 9816.L_OP_UNUSED_A3FF: /* 0x1a3 */ 9817/* File: armv5te/OP_UNUSED_A3FF.S */ 9818/* File: armv5te/unused.S */ 9819 bl common_abort 9820 9821 9822/* ------------------------------ */ 9823 .balign 64 9824.L_OP_UNUSED_A4FF: /* 0x1a4 */ 9825/* File: armv5te/OP_UNUSED_A4FF.S */ 9826/* File: armv5te/unused.S */ 9827 bl common_abort 9828 9829 9830/* ------------------------------ */ 9831 .balign 64 9832.L_OP_UNUSED_A5FF: /* 0x1a5 */ 9833/* File: armv5te/OP_UNUSED_A5FF.S */ 9834/* File: armv5te/unused.S */ 9835 bl common_abort 9836 9837 9838/* ------------------------------ */ 9839 .balign 64 9840.L_OP_UNUSED_A6FF: /* 0x1a6 */ 9841/* File: armv5te/OP_UNUSED_A6FF.S */ 9842/* File: armv5te/unused.S */ 9843 bl common_abort 9844 9845 9846/* ------------------------------ */ 9847 .balign 64 9848.L_OP_UNUSED_A7FF: /* 0x1a7 */ 9849/* File: armv5te/OP_UNUSED_A7FF.S */ 9850/* File: armv5te/unused.S */ 9851 bl common_abort 9852 9853 9854/* ------------------------------ */ 9855 .balign 64 9856.L_OP_UNUSED_A8FF: /* 0x1a8 */ 9857/* File: armv5te/OP_UNUSED_A8FF.S */ 9858/* File: armv5te/unused.S */ 9859 bl common_abort 9860 9861 9862/* ------------------------------ */ 9863 .balign 64 9864.L_OP_UNUSED_A9FF: /* 0x1a9 */ 9865/* File: armv5te/OP_UNUSED_A9FF.S */ 9866/* File: armv5te/unused.S */ 9867 bl common_abort 9868 9869 9870/* ------------------------------ */ 9871 .balign 64 9872.L_OP_UNUSED_AAFF: /* 0x1aa */ 9873/* File: armv5te/OP_UNUSED_AAFF.S */ 9874/* File: armv5te/unused.S */ 9875 bl common_abort 9876 9877 9878/* ------------------------------ */ 9879 .balign 64 9880.L_OP_UNUSED_ABFF: /* 0x1ab */ 9881/* File: armv5te/OP_UNUSED_ABFF.S */ 9882/* File: armv5te/unused.S */ 9883 bl common_abort 9884 9885 9886/* ------------------------------ */ 9887 .balign 64 9888.L_OP_UNUSED_ACFF: /* 0x1ac */ 9889/* File: armv5te/OP_UNUSED_ACFF.S */ 9890/* File: armv5te/unused.S */ 9891 bl common_abort 9892 9893 9894/* ------------------------------ */ 9895 .balign 64 9896.L_OP_UNUSED_ADFF: /* 0x1ad */ 9897/* File: armv5te/OP_UNUSED_ADFF.S */ 9898/* File: armv5te/unused.S */ 9899 bl common_abort 9900 9901 9902/* ------------------------------ */ 9903 .balign 64 9904.L_OP_UNUSED_AEFF: /* 0x1ae */ 9905/* File: armv5te/OP_UNUSED_AEFF.S */ 9906/* File: armv5te/unused.S */ 9907 bl common_abort 9908 9909 9910/* ------------------------------ */ 9911 .balign 64 9912.L_OP_UNUSED_AFFF: /* 0x1af */ 9913/* File: armv5te/OP_UNUSED_AFFF.S */ 9914/* File: armv5te/unused.S */ 9915 bl common_abort 9916 9917 9918/* ------------------------------ */ 9919 .balign 64 9920.L_OP_UNUSED_B0FF: /* 0x1b0 */ 9921/* File: armv5te/OP_UNUSED_B0FF.S */ 9922/* File: armv5te/unused.S */ 9923 bl common_abort 9924 9925 9926/* ------------------------------ */ 9927 .balign 64 9928.L_OP_UNUSED_B1FF: /* 0x1b1 */ 9929/* File: armv5te/OP_UNUSED_B1FF.S */ 9930/* File: armv5te/unused.S */ 9931 bl common_abort 9932 9933 9934/* ------------------------------ */ 9935 .balign 64 9936.L_OP_UNUSED_B2FF: /* 0x1b2 */ 9937/* File: armv5te/OP_UNUSED_B2FF.S */ 9938/* File: armv5te/unused.S */ 9939 bl common_abort 9940 9941 9942/* ------------------------------ */ 9943 .balign 64 9944.L_OP_UNUSED_B3FF: /* 0x1b3 */ 9945/* File: armv5te/OP_UNUSED_B3FF.S */ 9946/* File: armv5te/unused.S */ 9947 bl common_abort 9948 9949 9950/* ------------------------------ */ 9951 .balign 64 9952.L_OP_UNUSED_B4FF: /* 0x1b4 */ 9953/* File: armv5te/OP_UNUSED_B4FF.S */ 9954/* File: armv5te/unused.S */ 9955 bl common_abort 9956 9957 9958/* ------------------------------ */ 9959 .balign 64 9960.L_OP_UNUSED_B5FF: /* 0x1b5 */ 9961/* File: armv5te/OP_UNUSED_B5FF.S */ 9962/* File: armv5te/unused.S */ 9963 bl common_abort 9964 9965 9966/* ------------------------------ */ 9967 .balign 64 9968.L_OP_UNUSED_B6FF: /* 0x1b6 */ 9969/* File: armv5te/OP_UNUSED_B6FF.S */ 9970/* File: armv5te/unused.S */ 9971 bl common_abort 9972 9973 9974/* ------------------------------ */ 9975 .balign 64 9976.L_OP_UNUSED_B7FF: /* 0x1b7 */ 9977/* File: armv5te/OP_UNUSED_B7FF.S */ 9978/* File: armv5te/unused.S */ 9979 bl common_abort 9980 9981 9982/* ------------------------------ */ 9983 .balign 64 9984.L_OP_UNUSED_B8FF: /* 0x1b8 */ 9985/* File: armv5te/OP_UNUSED_B8FF.S */ 9986/* File: armv5te/unused.S */ 9987 bl common_abort 9988 9989 9990/* ------------------------------ */ 9991 .balign 64 9992.L_OP_UNUSED_B9FF: /* 0x1b9 */ 9993/* File: armv5te/OP_UNUSED_B9FF.S */ 9994/* File: armv5te/unused.S */ 9995 bl common_abort 9996 9997 9998/* ------------------------------ */ 9999 .balign 64 10000.L_OP_UNUSED_BAFF: /* 0x1ba */ 10001/* File: armv5te/OP_UNUSED_BAFF.S */ 10002/* File: armv5te/unused.S */ 10003 bl common_abort 10004 10005 10006/* ------------------------------ */ 10007 .balign 64 10008.L_OP_UNUSED_BBFF: /* 0x1bb */ 10009/* File: armv5te/OP_UNUSED_BBFF.S */ 10010/* File: armv5te/unused.S */ 10011 bl common_abort 10012 10013 10014/* ------------------------------ */ 10015 .balign 64 10016.L_OP_UNUSED_BCFF: /* 0x1bc */ 10017/* File: armv5te/OP_UNUSED_BCFF.S */ 10018/* File: armv5te/unused.S */ 10019 bl common_abort 10020 10021 10022/* ------------------------------ */ 10023 .balign 64 10024.L_OP_UNUSED_BDFF: /* 0x1bd */ 10025/* File: armv5te/OP_UNUSED_BDFF.S */ 10026/* File: armv5te/unused.S */ 10027 bl common_abort 10028 10029 10030/* ------------------------------ */ 10031 .balign 64 10032.L_OP_UNUSED_BEFF: /* 0x1be */ 10033/* File: armv5te/OP_UNUSED_BEFF.S */ 10034/* File: armv5te/unused.S */ 10035 bl common_abort 10036 10037 10038/* ------------------------------ */ 10039 .balign 64 10040.L_OP_UNUSED_BFFF: /* 0x1bf */ 10041/* File: armv5te/OP_UNUSED_BFFF.S */ 10042/* File: armv5te/unused.S */ 10043 bl common_abort 10044 10045 10046/* ------------------------------ */ 10047 .balign 64 10048.L_OP_UNUSED_C0FF: /* 0x1c0 */ 10049/* File: armv5te/OP_UNUSED_C0FF.S */ 10050/* File: armv5te/unused.S */ 10051 bl common_abort 10052 10053 10054/* ------------------------------ */ 10055 .balign 64 10056.L_OP_UNUSED_C1FF: /* 0x1c1 */ 10057/* File: armv5te/OP_UNUSED_C1FF.S */ 10058/* File: armv5te/unused.S */ 10059 bl common_abort 10060 10061 10062/* ------------------------------ */ 10063 .balign 64 10064.L_OP_UNUSED_C2FF: /* 0x1c2 */ 10065/* File: armv5te/OP_UNUSED_C2FF.S */ 10066/* File: armv5te/unused.S */ 10067 bl common_abort 10068 10069 10070/* ------------------------------ */ 10071 .balign 64 10072.L_OP_UNUSED_C3FF: /* 0x1c3 */ 10073/* File: armv5te/OP_UNUSED_C3FF.S */ 10074/* File: armv5te/unused.S */ 10075 bl common_abort 10076 10077 10078/* ------------------------------ */ 10079 .balign 64 10080.L_OP_UNUSED_C4FF: /* 0x1c4 */ 10081/* File: armv5te/OP_UNUSED_C4FF.S */ 10082/* File: armv5te/unused.S */ 10083 bl common_abort 10084 10085 10086/* ------------------------------ */ 10087 .balign 64 10088.L_OP_UNUSED_C5FF: /* 0x1c5 */ 10089/* File: armv5te/OP_UNUSED_C5FF.S */ 10090/* File: armv5te/unused.S */ 10091 bl common_abort 10092 10093 10094/* ------------------------------ */ 10095 .balign 64 10096.L_OP_UNUSED_C6FF: /* 0x1c6 */ 10097/* File: armv5te/OP_UNUSED_C6FF.S */ 10098/* File: armv5te/unused.S */ 10099 bl common_abort 10100 10101 10102/* ------------------------------ */ 10103 .balign 64 10104.L_OP_UNUSED_C7FF: /* 0x1c7 */ 10105/* File: armv5te/OP_UNUSED_C7FF.S */ 10106/* File: armv5te/unused.S */ 10107 bl common_abort 10108 10109 10110/* ------------------------------ */ 10111 .balign 64 10112.L_OP_UNUSED_C8FF: /* 0x1c8 */ 10113/* File: armv5te/OP_UNUSED_C8FF.S */ 10114/* File: armv5te/unused.S */ 10115 bl common_abort 10116 10117 10118/* ------------------------------ */ 10119 .balign 64 10120.L_OP_UNUSED_C9FF: /* 0x1c9 */ 10121/* File: armv5te/OP_UNUSED_C9FF.S */ 10122/* File: armv5te/unused.S */ 10123 bl common_abort 10124 10125 10126/* ------------------------------ */ 10127 .balign 64 10128.L_OP_UNUSED_CAFF: /* 0x1ca */ 10129/* File: armv5te/OP_UNUSED_CAFF.S */ 10130/* File: armv5te/unused.S */ 10131 bl common_abort 10132 10133 10134/* ------------------------------ */ 10135 .balign 64 10136.L_OP_UNUSED_CBFF: /* 0x1cb */ 10137/* File: armv5te/OP_UNUSED_CBFF.S */ 10138/* File: armv5te/unused.S */ 10139 bl common_abort 10140 10141 10142/* ------------------------------ */ 10143 .balign 64 10144.L_OP_UNUSED_CCFF: /* 0x1cc */ 10145/* File: armv5te/OP_UNUSED_CCFF.S */ 10146/* File: armv5te/unused.S */ 10147 bl common_abort 10148 10149 10150/* ------------------------------ */ 10151 .balign 64 10152.L_OP_UNUSED_CDFF: /* 0x1cd */ 10153/* File: armv5te/OP_UNUSED_CDFF.S */ 10154/* File: armv5te/unused.S */ 10155 bl common_abort 10156 10157 10158/* ------------------------------ */ 10159 .balign 64 10160.L_OP_UNUSED_CEFF: /* 0x1ce */ 10161/* File: armv5te/OP_UNUSED_CEFF.S */ 10162/* File: armv5te/unused.S */ 10163 bl common_abort 10164 10165 10166/* ------------------------------ */ 10167 .balign 64 10168.L_OP_UNUSED_CFFF: /* 0x1cf */ 10169/* File: armv5te/OP_UNUSED_CFFF.S */ 10170/* File: armv5te/unused.S */ 10171 bl common_abort 10172 10173 10174/* ------------------------------ */ 10175 .balign 64 10176.L_OP_UNUSED_D0FF: /* 0x1d0 */ 10177/* File: armv5te/OP_UNUSED_D0FF.S */ 10178/* File: armv5te/unused.S */ 10179 bl common_abort 10180 10181 10182/* ------------------------------ */ 10183 .balign 64 10184.L_OP_UNUSED_D1FF: /* 0x1d1 */ 10185/* File: armv5te/OP_UNUSED_D1FF.S */ 10186/* File: armv5te/unused.S */ 10187 bl common_abort 10188 10189 10190/* ------------------------------ */ 10191 .balign 64 10192.L_OP_UNUSED_D2FF: /* 0x1d2 */ 10193/* File: armv5te/OP_UNUSED_D2FF.S */ 10194/* File: armv5te/unused.S */ 10195 bl common_abort 10196 10197 10198/* ------------------------------ */ 10199 .balign 64 10200.L_OP_UNUSED_D3FF: /* 0x1d3 */ 10201/* File: armv5te/OP_UNUSED_D3FF.S */ 10202/* File: armv5te/unused.S */ 10203 bl common_abort 10204 10205 10206/* ------------------------------ */ 10207 .balign 64 10208.L_OP_UNUSED_D4FF: /* 0x1d4 */ 10209/* File: armv5te/OP_UNUSED_D4FF.S */ 10210/* File: armv5te/unused.S */ 10211 bl common_abort 10212 10213 10214/* ------------------------------ */ 10215 .balign 64 10216.L_OP_UNUSED_D5FF: /* 0x1d5 */ 10217/* File: armv5te/OP_UNUSED_D5FF.S */ 10218/* File: armv5te/unused.S */ 10219 bl common_abort 10220 10221 10222/* ------------------------------ */ 10223 .balign 64 10224.L_OP_UNUSED_D6FF: /* 0x1d6 */ 10225/* File: armv5te/OP_UNUSED_D6FF.S */ 10226/* File: armv5te/unused.S */ 10227 bl common_abort 10228 10229 10230/* ------------------------------ */ 10231 .balign 64 10232.L_OP_UNUSED_D7FF: /* 0x1d7 */ 10233/* File: armv5te/OP_UNUSED_D7FF.S */ 10234/* File: armv5te/unused.S */ 10235 bl common_abort 10236 10237 10238/* ------------------------------ */ 10239 .balign 64 10240.L_OP_UNUSED_D8FF: /* 0x1d8 */ 10241/* File: armv5te/OP_UNUSED_D8FF.S */ 10242/* File: armv5te/unused.S */ 10243 bl common_abort 10244 10245 10246/* ------------------------------ */ 10247 .balign 64 10248.L_OP_UNUSED_D9FF: /* 0x1d9 */ 10249/* File: armv5te/OP_UNUSED_D9FF.S */ 10250/* File: armv5te/unused.S */ 10251 bl common_abort 10252 10253 10254/* ------------------------------ */ 10255 .balign 64 10256.L_OP_UNUSED_DAFF: /* 0x1da */ 10257/* File: armv5te/OP_UNUSED_DAFF.S */ 10258/* File: armv5te/unused.S */ 10259 bl common_abort 10260 10261 10262/* ------------------------------ */ 10263 .balign 64 10264.L_OP_UNUSED_DBFF: /* 0x1db */ 10265/* File: armv5te/OP_UNUSED_DBFF.S */ 10266/* File: armv5te/unused.S */ 10267 bl common_abort 10268 10269 10270/* ------------------------------ */ 10271 .balign 64 10272.L_OP_UNUSED_DCFF: /* 0x1dc */ 10273/* File: armv5te/OP_UNUSED_DCFF.S */ 10274/* File: armv5te/unused.S */ 10275 bl common_abort 10276 10277 10278/* ------------------------------ */ 10279 .balign 64 10280.L_OP_UNUSED_DDFF: /* 0x1dd */ 10281/* File: armv5te/OP_UNUSED_DDFF.S */ 10282/* File: armv5te/unused.S */ 10283 bl common_abort 10284 10285 10286/* ------------------------------ */ 10287 .balign 64 10288.L_OP_UNUSED_DEFF: /* 0x1de */ 10289/* File: armv5te/OP_UNUSED_DEFF.S */ 10290/* File: armv5te/unused.S */ 10291 bl common_abort 10292 10293 10294/* ------------------------------ */ 10295 .balign 64 10296.L_OP_UNUSED_DFFF: /* 0x1df */ 10297/* File: armv5te/OP_UNUSED_DFFF.S */ 10298/* File: armv5te/unused.S */ 10299 bl common_abort 10300 10301 10302/* ------------------------------ */ 10303 .balign 64 10304.L_OP_UNUSED_E0FF: /* 0x1e0 */ 10305/* File: armv5te/OP_UNUSED_E0FF.S */ 10306/* File: armv5te/unused.S */ 10307 bl common_abort 10308 10309 10310/* ------------------------------ */ 10311 .balign 64 10312.L_OP_UNUSED_E1FF: /* 0x1e1 */ 10313/* File: armv5te/OP_UNUSED_E1FF.S */ 10314/* File: armv5te/unused.S */ 10315 bl common_abort 10316 10317 10318/* ------------------------------ */ 10319 .balign 64 10320.L_OP_UNUSED_E2FF: /* 0x1e2 */ 10321/* File: armv5te/OP_UNUSED_E2FF.S */ 10322/* File: armv5te/unused.S */ 10323 bl common_abort 10324 10325 10326/* ------------------------------ */ 10327 .balign 64 10328.L_OP_UNUSED_E3FF: /* 0x1e3 */ 10329/* File: armv5te/OP_UNUSED_E3FF.S */ 10330/* File: armv5te/unused.S */ 10331 bl common_abort 10332 10333 10334/* ------------------------------ */ 10335 .balign 64 10336.L_OP_UNUSED_E4FF: /* 0x1e4 */ 10337/* File: armv5te/OP_UNUSED_E4FF.S */ 10338/* File: armv5te/unused.S */ 10339 bl common_abort 10340 10341 10342/* ------------------------------ */ 10343 .balign 64 10344.L_OP_UNUSED_E5FF: /* 0x1e5 */ 10345/* File: armv5te/OP_UNUSED_E5FF.S */ 10346/* File: armv5te/unused.S */ 10347 bl common_abort 10348 10349 10350/* ------------------------------ */ 10351 .balign 64 10352.L_OP_UNUSED_E6FF: /* 0x1e6 */ 10353/* File: armv5te/OP_UNUSED_E6FF.S */ 10354/* File: armv5te/unused.S */ 10355 bl common_abort 10356 10357 10358/* ------------------------------ */ 10359 .balign 64 10360.L_OP_UNUSED_E7FF: /* 0x1e7 */ 10361/* File: armv5te/OP_UNUSED_E7FF.S */ 10362/* File: armv5te/unused.S */ 10363 bl common_abort 10364 10365 10366/* ------------------------------ */ 10367 .balign 64 10368.L_OP_UNUSED_E8FF: /* 0x1e8 */ 10369/* File: armv5te/OP_UNUSED_E8FF.S */ 10370/* File: armv5te/unused.S */ 10371 bl common_abort 10372 10373 10374/* ------------------------------ */ 10375 .balign 64 10376.L_OP_UNUSED_E9FF: /* 0x1e9 */ 10377/* File: armv5te/OP_UNUSED_E9FF.S */ 10378/* File: armv5te/unused.S */ 10379 bl common_abort 10380 10381 10382/* ------------------------------ */ 10383 .balign 64 10384.L_OP_UNUSED_EAFF: /* 0x1ea */ 10385/* File: armv5te/OP_UNUSED_EAFF.S */ 10386/* File: armv5te/unused.S */ 10387 bl common_abort 10388 10389 10390/* ------------------------------ */ 10391 .balign 64 10392.L_OP_UNUSED_EBFF: /* 0x1eb */ 10393/* File: armv5te/OP_UNUSED_EBFF.S */ 10394/* File: armv5te/unused.S */ 10395 bl common_abort 10396 10397 10398/* ------------------------------ */ 10399 .balign 64 10400.L_OP_UNUSED_ECFF: /* 0x1ec */ 10401/* File: armv5te/OP_UNUSED_ECFF.S */ 10402/* File: armv5te/unused.S */ 10403 bl common_abort 10404 10405 10406/* ------------------------------ */ 10407 .balign 64 10408.L_OP_UNUSED_EDFF: /* 0x1ed */ 10409/* File: armv5te/OP_UNUSED_EDFF.S */ 10410/* File: armv5te/unused.S */ 10411 bl common_abort 10412 10413 10414/* ------------------------------ */ 10415 .balign 64 10416.L_OP_UNUSED_EEFF: /* 0x1ee */ 10417/* File: armv5te/OP_UNUSED_EEFF.S */ 10418/* File: armv5te/unused.S */ 10419 bl common_abort 10420 10421 10422/* ------------------------------ */ 10423 .balign 64 10424.L_OP_UNUSED_EFFF: /* 0x1ef */ 10425/* File: armv5te/OP_UNUSED_EFFF.S */ 10426/* File: armv5te/unused.S */ 10427 bl common_abort 10428 10429 10430/* ------------------------------ */ 10431 .balign 64 10432.L_OP_UNUSED_F0FF: /* 0x1f0 */ 10433/* File: armv5te/OP_UNUSED_F0FF.S */ 10434/* File: armv5te/unused.S */ 10435 bl common_abort 10436 10437 10438/* ------------------------------ */ 10439 .balign 64 10440.L_OP_UNUSED_F1FF: /* 0x1f1 */ 10441/* File: armv5te/OP_UNUSED_F1FF.S */ 10442/* File: armv5te/unused.S */ 10443 bl common_abort 10444 10445 10446/* ------------------------------ */ 10447 .balign 64 10448.L_OP_UNUSED_F2FF: /* 0x1f2 */ 10449/* File: armv5te/OP_UNUSED_F2FF.S */ 10450/* File: armv5te/unused.S */ 10451 bl common_abort 10452 10453 10454/* ------------------------------ */ 10455 .balign 64 10456.L_OP_UNUSED_F3FF: /* 0x1f3 */ 10457/* File: armv5te/OP_UNUSED_F3FF.S */ 10458/* File: armv5te/unused.S */ 10459 bl common_abort 10460 10461 10462/* ------------------------------ */ 10463 .balign 64 10464.L_OP_UNUSED_F4FF: /* 0x1f4 */ 10465/* File: armv5te/OP_UNUSED_F4FF.S */ 10466/* File: armv5te/unused.S */ 10467 bl common_abort 10468 10469 10470/* ------------------------------ */ 10471 .balign 64 10472.L_OP_UNUSED_F5FF: /* 0x1f5 */ 10473/* File: armv5te/OP_UNUSED_F5FF.S */ 10474/* File: armv5te/unused.S */ 10475 bl common_abort 10476 10477 10478/* ------------------------------ */ 10479 .balign 64 10480.L_OP_UNUSED_F6FF: /* 0x1f6 */ 10481/* File: armv5te/OP_UNUSED_F6FF.S */ 10482/* File: armv5te/unused.S */ 10483 bl common_abort 10484 10485 10486/* ------------------------------ */ 10487 .balign 64 10488.L_OP_UNUSED_F7FF: /* 0x1f7 */ 10489/* File: armv5te/OP_UNUSED_F7FF.S */ 10490/* File: armv5te/unused.S */ 10491 bl common_abort 10492 10493 10494/* ------------------------------ */ 10495 .balign 64 10496.L_OP_UNUSED_F8FF: /* 0x1f8 */ 10497/* File: armv5te/OP_UNUSED_F8FF.S */ 10498/* File: armv5te/unused.S */ 10499 bl common_abort 10500 10501 10502/* ------------------------------ */ 10503 .balign 64 10504.L_OP_UNUSED_F9FF: /* 0x1f9 */ 10505/* File: armv5te/OP_UNUSED_F9FF.S */ 10506/* File: armv5te/unused.S */ 10507 bl common_abort 10508 10509 10510/* ------------------------------ */ 10511 .balign 64 10512.L_OP_UNUSED_FAFF: /* 0x1fa */ 10513/* File: armv5te/OP_UNUSED_FAFF.S */ 10514/* File: armv5te/unused.S */ 10515 bl common_abort 10516 10517 10518/* ------------------------------ */ 10519 .balign 64 10520.L_OP_UNUSED_FBFF: /* 0x1fb */ 10521/* File: armv5te/OP_UNUSED_FBFF.S */ 10522/* File: armv5te/unused.S */ 10523 bl common_abort 10524 10525 10526/* ------------------------------ */ 10527 .balign 64 10528.L_OP_UNUSED_FCFF: /* 0x1fc */ 10529/* File: armv5te/OP_UNUSED_FCFF.S */ 10530/* File: armv5te/unused.S */ 10531 bl common_abort 10532 10533 10534/* ------------------------------ */ 10535 .balign 64 10536.L_OP_UNUSED_FDFF: /* 0x1fd */ 10537/* File: armv5te/OP_UNUSED_FDFF.S */ 10538/* File: armv5te/unused.S */ 10539 bl common_abort 10540 10541 10542/* ------------------------------ */ 10543 .balign 64 10544.L_OP_UNUSED_FEFF: /* 0x1fe */ 10545/* File: armv5te/OP_UNUSED_FEFF.S */ 10546/* File: armv5te/unused.S */ 10547 bl common_abort 10548 10549 10550/* ------------------------------ */ 10551 .balign 64 10552.L_OP_THROW_VERIFICATION_ERROR_JUMBO: /* 0x1ff */ 10553/* File: armv5te/OP_THROW_VERIFICATION_ERROR_JUMBO.S */ 10554 /* 10555 * Handle a jumbo throw-verification-error instruction. This throws an 10556 * exception for an error discovered during verification. The 10557 * exception is indicated by BBBB, with some detail provided by AAAAAAAA. 10558 */ 10559 /* exop BBBB, Class@AAAAAAAA */ 10560 FETCH(r1, 1) @ r1<- aaaa (lo) 10561 FETCH(r2, 2) @ r2<- AAAA (hi) 10562 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 10563 orr r2, r1, r2, lsl #16 @ r2<- AAAAaaaa 10564 EXPORT_PC() @ export the PC 10565 FETCH(r1, 3) @ r1<- BBBB 10566 bl dvmThrowVerificationError @ always throws 10567 b common_exceptionThrown @ handle exception 10568 10569 10570 .balign 64 10571 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 10572 .global dvmAsmInstructionEnd 10573dvmAsmInstructionEnd: 10574 10575/* 10576 * =========================================================================== 10577 * Sister implementations 10578 * =========================================================================== 10579 */ 10580 .global dvmAsmSisterStart 10581 .type dvmAsmSisterStart, %function 10582 .text 10583 .balign 4 10584dvmAsmSisterStart: 10585 10586/* continuation for OP_CONST_STRING */ 10587 10588 /* 10589 * Continuation if the String has not yet been resolved. 10590 * r1: BBBB (String ref) 10591 * r9: target register 10592 */ 10593.LOP_CONST_STRING_resolve: 10594 EXPORT_PC() 10595 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 10596 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 10597 bl dvmResolveString @ r0<- String reference 10598 cmp r0, #0 @ failed? 10599 beq common_exceptionThrown @ yup, handle the exception 10600 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 10601 GET_INST_OPCODE(ip) @ extract opcode from rINST 10602 SET_VREG(r0, r9) @ vAA<- r0 10603 GOTO_OPCODE(ip) @ jump to next instruction 10604 10605/* continuation for OP_CONST_STRING_JUMBO */ 10606 10607 /* 10608 * Continuation if the String has not yet been resolved. 10609 * r1: BBBBBBBB (String ref) 10610 * r9: target register 10611 */ 10612.LOP_CONST_STRING_JUMBO_resolve: 10613 EXPORT_PC() 10614 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 10615 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 10616 bl dvmResolveString @ r0<- String reference 10617 cmp r0, #0 @ failed? 10618 beq common_exceptionThrown @ yup, handle the exception 10619 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 10620 GET_INST_OPCODE(ip) @ extract opcode from rINST 10621 SET_VREG(r0, r9) @ vAA<- r0 10622 GOTO_OPCODE(ip) @ jump to next instruction 10623 10624/* continuation for OP_CONST_CLASS */ 10625 10626 /* 10627 * Continuation if the Class has not yet been resolved. 10628 * r1: BBBB (Class ref) 10629 * r9: target register 10630 */ 10631.LOP_CONST_CLASS_resolve: 10632 EXPORT_PC() 10633 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 10634 mov r2, #1 @ r2<- true 10635 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 10636 bl dvmResolveClass @ r0<- Class reference 10637 cmp r0, #0 @ failed? 10638 beq common_exceptionThrown @ yup, handle the exception 10639 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 10640 GET_INST_OPCODE(ip) @ extract opcode from rINST 10641 SET_VREG(r0, r9) @ vAA<- r0 10642 GOTO_OPCODE(ip) @ jump to next instruction 10643 10644/* continuation for OP_CHECK_CAST */ 10645 10646 /* 10647 * Trivial test failed, need to perform full check. This is common. 10648 * r0 holds obj->clazz 10649 * r1 holds desired class resolved from BBBB 10650 * r9 holds object 10651 */ 10652.LOP_CHECK_CAST_fullcheck: 10653 mov r10, r1 @ avoid ClassObject getting clobbered 10654 bl dvmInstanceofNonTrivial @ r0<- boolean result 10655 cmp r0, #0 @ failed? 10656 bne .LOP_CHECK_CAST_okay @ no, success 10657 10658 @ A cast has failed. We need to throw a ClassCastException. 10659 EXPORT_PC() @ about to throw 10660 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz (actual class) 10661 mov r1, r10 @ r1<- desired class 10662 bl dvmThrowClassCastException 10663 b common_exceptionThrown 10664 10665 /* 10666 * Resolution required. This is the least-likely path. 10667 * 10668 * r2 holds BBBB 10669 * r9 holds object 10670 */ 10671.LOP_CHECK_CAST_resolve: 10672 EXPORT_PC() @ resolve() could throw 10673 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 10674 mov r1, r2 @ r1<- BBBB 10675 mov r2, #0 @ r2<- false 10676 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 10677 bl dvmResolveClass @ r0<- resolved ClassObject ptr 10678 cmp r0, #0 @ got null? 10679 beq common_exceptionThrown @ yes, handle exception 10680 mov r1, r0 @ r1<- class resolved from BBB 10681 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 10682 b .LOP_CHECK_CAST_resolved @ pick up where we left off 10683 10684/* continuation for OP_INSTANCE_OF */ 10685 10686 /* 10687 * Trivial test failed, need to perform full check. This is common. 10688 * r0 holds obj->clazz 10689 * r1 holds class resolved from BBBB 10690 * r9 holds A 10691 */ 10692.LOP_INSTANCE_OF_fullcheck: 10693 bl dvmInstanceofNonTrivial @ r0<- boolean result 10694 @ fall through to OP_INSTANCE_OF_store 10695 10696 /* 10697 * r0 holds boolean result 10698 * r9 holds A 10699 */ 10700.LOP_INSTANCE_OF_store: 10701 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 10702 SET_VREG(r0, r9) @ vA<- r0 10703 GET_INST_OPCODE(ip) @ extract opcode from rINST 10704 GOTO_OPCODE(ip) @ jump to next instruction 10705 10706 /* 10707 * Trivial test succeeded, save and bail. 10708 * r9 holds A 10709 */ 10710.LOP_INSTANCE_OF_trivial: 10711 mov r0, #1 @ indicate success 10712 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 10713 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 10714 SET_VREG(r0, r9) @ vA<- r0 10715 GET_INST_OPCODE(ip) @ extract opcode from rINST 10716 GOTO_OPCODE(ip) @ jump to next instruction 10717 10718 /* 10719 * Resolution required. This is the least-likely path. 10720 * 10721 * r3 holds BBBB 10722 * r9 holds A 10723 */ 10724.LOP_INSTANCE_OF_resolve: 10725 EXPORT_PC() @ resolve() could throw 10726 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 10727 mov r1, r3 @ r1<- BBBB 10728 mov r2, #1 @ r2<- true 10729 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 10730 bl dvmResolveClass @ r0<- resolved ClassObject ptr 10731 cmp r0, #0 @ got null? 10732 beq common_exceptionThrown @ yes, handle exception 10733 mov r1, r0 @ r1<- class resolved from BBB 10734 mov r3, rINST, lsr #12 @ r3<- B 10735 GET_VREG(r0, r3) @ r0<- vB (object) 10736 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 10737 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 10738 10739/* continuation for OP_NEW_INSTANCE */ 10740 10741 .balign 32 @ minimize cache lines 10742.LOP_NEW_INSTANCE_finish: @ r0=new object 10743 mov r3, rINST, lsr #8 @ r3<- AA 10744 cmp r0, #0 @ failed? 10745 beq common_exceptionThrown @ yes, handle the exception 10746 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 10747 GET_INST_OPCODE(ip) @ extract opcode from rINST 10748 SET_VREG(r0, r3) @ vAA<- r0 10749 GOTO_OPCODE(ip) @ jump to next instruction 10750 10751 /* 10752 * Class initialization required. 10753 * 10754 * r0 holds class object 10755 */ 10756.LOP_NEW_INSTANCE_needinit: 10757 mov r9, r0 @ save r0 10758 bl dvmInitClass @ initialize class 10759 cmp r0, #0 @ check boolean result 10760 mov r0, r9 @ restore r0 10761 bne .LOP_NEW_INSTANCE_initialized @ success, continue 10762 b common_exceptionThrown @ failed, deal with init exception 10763 10764 /* 10765 * Resolution required. This is the least-likely path. 10766 * 10767 * r1 holds BBBB 10768 */ 10769.LOP_NEW_INSTANCE_resolve: 10770 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 10771 mov r2, #0 @ r2<- false 10772 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 10773 bl dvmResolveClass @ r0<- resolved ClassObject ptr 10774 cmp r0, #0 @ got null? 10775 bne .LOP_NEW_INSTANCE_resolved @ no, continue 10776 b common_exceptionThrown @ yes, handle exception 10777 10778.LstrInstantiationErrorPtr: 10779 .word .LstrInstantiationError 10780 10781/* continuation for OP_NEW_ARRAY */ 10782 10783 10784 /* 10785 * Resolve class. (This is an uncommon case.) 10786 * 10787 * r1 holds array length 10788 * r2 holds class ref CCCC 10789 */ 10790.LOP_NEW_ARRAY_resolve: 10791 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 10792 mov r9, r1 @ r9<- length (save) 10793 mov r1, r2 @ r1<- CCCC 10794 mov r2, #0 @ r2<- false 10795 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 10796 bl dvmResolveClass @ r0<- call(clazz, ref) 10797 cmp r0, #0 @ got null? 10798 mov r1, r9 @ r1<- length (restore) 10799 beq common_exceptionThrown @ yes, handle exception 10800 @ fall through to OP_NEW_ARRAY_finish 10801 10802 /* 10803 * Finish allocation. 10804 * 10805 * r0 holds class 10806 * r1 holds array length 10807 */ 10808.LOP_NEW_ARRAY_finish: 10809 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 10810 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 10811 cmp r0, #0 @ failed? 10812 mov r2, rINST, lsr #8 @ r2<- A+ 10813 beq common_exceptionThrown @ yes, handle the exception 10814 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 10815 and r2, r2, #15 @ r2<- A 10816 GET_INST_OPCODE(ip) @ extract opcode from rINST 10817 SET_VREG(r0, r2) @ vA<- r0 10818 GOTO_OPCODE(ip) @ jump to next instruction 10819 10820/* continuation for OP_FILLED_NEW_ARRAY */ 10821 10822 /* 10823 * On entry: 10824 * r0 holds array class 10825 * r10 holds AA or BA 10826 */ 10827.LOP_FILLED_NEW_ARRAY_continue: 10828 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 10829 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 10830 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 10831 .if 0 10832 mov r1, r10 @ r1<- AA (length) 10833 .else 10834 mov r1, r10, lsr #4 @ r1<- B (length) 10835 .endif 10836 cmp rINST, #'I' @ array of ints? 10837 cmpne rINST, #'L' @ array of objects? 10838 cmpne rINST, #'[' @ array of arrays? 10839 mov r9, r1 @ save length in r9 10840 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 10841 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 10842 cmp r0, #0 @ null return? 10843 beq common_exceptionThrown @ alloc failed, handle exception 10844 10845 FETCH(r1, 2) @ r1<- FEDC or CCCC 10846 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 10847 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 10848 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 10849 subs r9, r9, #1 @ length--, check for neg 10850 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 10851 bmi 2f @ was zero, bail 10852 10853 @ copy values from registers into the array 10854 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 10855 .if 0 10856 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 108571: ldr r3, [r2], #4 @ r3<- *r2++ 10858 subs r9, r9, #1 @ count-- 10859 str r3, [r0], #4 @ *contents++ = vX 10860 bpl 1b 10861 @ continue at 2 10862 .else 10863 cmp r9, #4 @ length was initially 5? 10864 and r2, r10, #15 @ r2<- A 10865 bne 1f @ <= 4 args, branch 10866 GET_VREG(r3, r2) @ r3<- vA 10867 sub r9, r9, #1 @ count-- 10868 str r3, [r0, #16] @ contents[4] = vA 108691: and r2, r1, #15 @ r2<- F/E/D/C 10870 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 10871 mov r1, r1, lsr #4 @ r1<- next reg in low 4 10872 subs r9, r9, #1 @ count-- 10873 str r3, [r0], #4 @ *contents++ = vX 10874 bpl 1b 10875 @ continue at 2 10876 .endif 10877 108782: 10879 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 10880 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 10881 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 10882 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 10883 cmp r1, #'I' @ Is int array? 10884 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 10885 GOTO_OPCODE(ip) @ execute it 10886 10887 /* 10888 * Throw an exception indicating that we have not implemented this 10889 * mode of filled-new-array. 10890 */ 10891.LOP_FILLED_NEW_ARRAY_notimpl: 10892 ldr r0, .L_strInternalError 10893 ldr r1, .L_strFilledNewArrayNotImpl 10894 bl dvmThrowException 10895 b common_exceptionThrown 10896 10897 .if (!0) @ define in one or the other, not both 10898.L_strFilledNewArrayNotImpl: 10899 .word .LstrFilledNewArrayNotImpl 10900.L_strInternalError: 10901 .word .LstrInternalError 10902 .endif 10903 10904/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 10905 10906 /* 10907 * On entry: 10908 * r0 holds array class 10909 * r10 holds AA or BA 10910 */ 10911.LOP_FILLED_NEW_ARRAY_RANGE_continue: 10912 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 10913 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 10914 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 10915 .if 1 10916 mov r1, r10 @ r1<- AA (length) 10917 .else 10918 mov r1, r10, lsr #4 @ r1<- B (length) 10919 .endif 10920 cmp rINST, #'I' @ array of ints? 10921 cmpne rINST, #'L' @ array of objects? 10922 cmpne rINST, #'[' @ array of arrays? 10923 mov r9, r1 @ save length in r9 10924 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 10925 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 10926 cmp r0, #0 @ null return? 10927 beq common_exceptionThrown @ alloc failed, handle exception 10928 10929 FETCH(r1, 2) @ r1<- FEDC or CCCC 10930 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 10931 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 10932 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 10933 subs r9, r9, #1 @ length--, check for neg 10934 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 10935 bmi 2f @ was zero, bail 10936 10937 @ copy values from registers into the array 10938 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 10939 .if 1 10940 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 109411: ldr r3, [r2], #4 @ r3<- *r2++ 10942 subs r9, r9, #1 @ count-- 10943 str r3, [r0], #4 @ *contents++ = vX 10944 bpl 1b 10945 @ continue at 2 10946 .else 10947 cmp r9, #4 @ length was initially 5? 10948 and r2, r10, #15 @ r2<- A 10949 bne 1f @ <= 4 args, branch 10950 GET_VREG(r3, r2) @ r3<- vA 10951 sub r9, r9, #1 @ count-- 10952 str r3, [r0, #16] @ contents[4] = vA 109531: and r2, r1, #15 @ r2<- F/E/D/C 10954 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 10955 mov r1, r1, lsr #4 @ r1<- next reg in low 4 10956 subs r9, r9, #1 @ count-- 10957 str r3, [r0], #4 @ *contents++ = vX 10958 bpl 1b 10959 @ continue at 2 10960 .endif 10961 109622: 10963 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 10964 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 10965 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 10966 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 10967 cmp r1, #'I' @ Is int array? 10968 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 10969 GOTO_OPCODE(ip) @ execute it 10970 10971 /* 10972 * Throw an exception indicating that we have not implemented this 10973 * mode of filled-new-array. 10974 */ 10975.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 10976 ldr r0, .L_strInternalError 10977 ldr r1, .L_strFilledNewArrayNotImpl 10978 bl dvmThrowException 10979 b common_exceptionThrown 10980 10981 .if (!1) @ define in one or the other, not both 10982.L_strFilledNewArrayNotImpl: 10983 .word .LstrFilledNewArrayNotImpl 10984.L_strInternalError: 10985 .word .LstrInternalError 10986 .endif 10987 10988/* continuation for OP_CMPL_FLOAT */ 10989.LOP_CMPL_FLOAT_finish: 10990 SET_VREG(r0, r9) @ vAA<- r0 10991 GOTO_OPCODE(ip) @ jump to next instruction 10992 10993/* continuation for OP_CMPG_FLOAT */ 10994.LOP_CMPG_FLOAT_finish: 10995 SET_VREG(r0, r9) @ vAA<- r0 10996 GOTO_OPCODE(ip) @ jump to next instruction 10997 10998/* continuation for OP_CMPL_DOUBLE */ 10999.LOP_CMPL_DOUBLE_finish: 11000 SET_VREG(r0, r9) @ vAA<- r0 11001 GOTO_OPCODE(ip) @ jump to next instruction 11002 11003/* continuation for OP_CMPG_DOUBLE */ 11004.LOP_CMPG_DOUBLE_finish: 11005 SET_VREG(r0, r9) @ vAA<- r0 11006 GOTO_OPCODE(ip) @ jump to next instruction 11007 11008/* continuation for OP_CMP_LONG */ 11009 11010.LOP_CMP_LONG_less: 11011 mvn r1, #0 @ r1<- -1 11012 @ Want to cond code the next mov so we can avoid branch, but don't see it; 11013 @ instead, we just replicate the tail end. 11014 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11015 SET_VREG(r1, r9) @ vAA<- r1 11016 GET_INST_OPCODE(ip) @ extract opcode from rINST 11017 GOTO_OPCODE(ip) @ jump to next instruction 11018 11019.LOP_CMP_LONG_greater: 11020 mov r1, #1 @ r1<- 1 11021 @ fall through to _finish 11022 11023.LOP_CMP_LONG_finish: 11024 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11025 SET_VREG(r1, r9) @ vAA<- r1 11026 GET_INST_OPCODE(ip) @ extract opcode from rINST 11027 GOTO_OPCODE(ip) @ jump to next instruction 11028 11029/* continuation for OP_AGET_WIDE */ 11030 11031.LOP_AGET_WIDE_finish: 11032 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11033 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 11034 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 11035 GET_INST_OPCODE(ip) @ extract opcode from rINST 11036 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 11037 GOTO_OPCODE(ip) @ jump to next instruction 11038 11039/* continuation for OP_APUT_WIDE */ 11040 11041.LOP_APUT_WIDE_finish: 11042 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11043 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 11044 GET_INST_OPCODE(ip) @ extract opcode from rINST 11045 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 11046 GOTO_OPCODE(ip) @ jump to next instruction 11047 11048/* continuation for OP_APUT_OBJECT */ 11049 /* 11050 * On entry: 11051 * rINST = vBB (arrayObj) 11052 * r9 = vAA (obj) 11053 * r10 = offset into array (vBB + vCC * width) 11054 */ 11055.LOP_APUT_OBJECT_finish: 11056 cmp r9, #0 @ storing null reference? 11057 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 11058 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 11059 ldr r1, [rINST, #offObject_clazz] @ r1<- arrayObj->clazz 11060 bl dvmCanPutArrayElement @ test object type vs. array type 11061 cmp r0, #0 @ okay? 11062 beq .LOP_APUT_OBJECT_throw @ no 11063 mov r1, rINST @ r1<- arrayObj 11064 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11065 ldr r2, [rGLUE, #offGlue_cardTable] @ get biased CT base 11066 add r10, #offArrayObject_contents @ r0<- pointer to slot 11067 GET_INST_OPCODE(ip) @ extract opcode from rINST 11068 str r9, [r10] @ vBB[vCC]<- vAA 11069 strb r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head 11070 GOTO_OPCODE(ip) @ jump to next instruction 11071.LOP_APUT_OBJECT_skip_check: 11072 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11073 GET_INST_OPCODE(ip) @ extract opcode from rINST 11074 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 11075 GOTO_OPCODE(ip) @ jump to next instruction 11076.LOP_APUT_OBJECT_throw: 11077 @ The types don't match. We need to throw an ArrayStoreException. 11078 ldr r0, [r9, #offObject_clazz] 11079 ldr r1, [rINST, #offObject_clazz] 11080 EXPORT_PC() 11081 bl dvmThrowArrayStoreException 11082 b common_exceptionThrown 11083 11084/* continuation for OP_IGET */ 11085 11086 /* 11087 * Currently: 11088 * r0 holds resolved field 11089 * r9 holds object 11090 */ 11091.LOP_IGET_finish: 11092 @bl common_squeak0 11093 cmp r9, #0 @ check object for null 11094 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11095 beq common_errNullObject @ object was null 11096 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11097 @ no-op @ acquiring load 11098 mov r2, rINST, lsr #8 @ r2<- A+ 11099 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11100 and r2, r2, #15 @ r2<- A 11101 GET_INST_OPCODE(ip) @ extract opcode from rINST 11102 SET_VREG(r0, r2) @ fp[A]<- r0 11103 GOTO_OPCODE(ip) @ jump to next instruction 11104 11105/* continuation for OP_IGET_WIDE */ 11106 11107 /* 11108 * Currently: 11109 * r0 holds resolved field 11110 * r9 holds object 11111 */ 11112.LOP_IGET_WIDE_finish: 11113 cmp r9, #0 @ check object for null 11114 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11115 beq common_errNullObject @ object was null 11116 .if 0 11117 add r0, r9, r3 @ r0<- address of field 11118 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 11119 .else 11120 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 11121 .endif 11122 mov r2, rINST, lsr #8 @ r2<- A+ 11123 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11124 and r2, r2, #15 @ r2<- A 11125 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 11126 GET_INST_OPCODE(ip) @ extract opcode from rINST 11127 stmia r3, {r0-r1} @ fp[A]<- r0/r1 11128 GOTO_OPCODE(ip) @ jump to next instruction 11129 11130/* continuation for OP_IGET_OBJECT */ 11131 11132 /* 11133 * Currently: 11134 * r0 holds resolved field 11135 * r9 holds object 11136 */ 11137.LOP_IGET_OBJECT_finish: 11138 @bl common_squeak0 11139 cmp r9, #0 @ check object for null 11140 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11141 beq common_errNullObject @ object was null 11142 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11143 @ no-op @ acquiring load 11144 mov r2, rINST, lsr #8 @ r2<- A+ 11145 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11146 and r2, r2, #15 @ r2<- A 11147 GET_INST_OPCODE(ip) @ extract opcode from rINST 11148 SET_VREG(r0, r2) @ fp[A]<- r0 11149 GOTO_OPCODE(ip) @ jump to next instruction 11150 11151/* continuation for OP_IGET_BOOLEAN */ 11152 11153 /* 11154 * Currently: 11155 * r0 holds resolved field 11156 * r9 holds object 11157 */ 11158.LOP_IGET_BOOLEAN_finish: 11159 @bl common_squeak1 11160 cmp r9, #0 @ check object for null 11161 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11162 beq common_errNullObject @ object was null 11163 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11164 @ no-op @ acquiring load 11165 mov r2, rINST, lsr #8 @ r2<- A+ 11166 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11167 and r2, r2, #15 @ r2<- A 11168 GET_INST_OPCODE(ip) @ extract opcode from rINST 11169 SET_VREG(r0, r2) @ fp[A]<- r0 11170 GOTO_OPCODE(ip) @ jump to next instruction 11171 11172/* continuation for OP_IGET_BYTE */ 11173 11174 /* 11175 * Currently: 11176 * r0 holds resolved field 11177 * r9 holds object 11178 */ 11179.LOP_IGET_BYTE_finish: 11180 @bl common_squeak2 11181 cmp r9, #0 @ check object for null 11182 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11183 beq common_errNullObject @ object was null 11184 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11185 @ no-op @ acquiring load 11186 mov r2, rINST, lsr #8 @ r2<- A+ 11187 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11188 and r2, r2, #15 @ r2<- A 11189 GET_INST_OPCODE(ip) @ extract opcode from rINST 11190 SET_VREG(r0, r2) @ fp[A]<- r0 11191 GOTO_OPCODE(ip) @ jump to next instruction 11192 11193/* continuation for OP_IGET_CHAR */ 11194 11195 /* 11196 * Currently: 11197 * r0 holds resolved field 11198 * r9 holds object 11199 */ 11200.LOP_IGET_CHAR_finish: 11201 @bl common_squeak3 11202 cmp r9, #0 @ check object for null 11203 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11204 beq common_errNullObject @ object was null 11205 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11206 @ no-op @ acquiring load 11207 mov r2, rINST, lsr #8 @ r2<- A+ 11208 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11209 and r2, r2, #15 @ r2<- A 11210 GET_INST_OPCODE(ip) @ extract opcode from rINST 11211 SET_VREG(r0, r2) @ fp[A]<- r0 11212 GOTO_OPCODE(ip) @ jump to next instruction 11213 11214/* continuation for OP_IGET_SHORT */ 11215 11216 /* 11217 * Currently: 11218 * r0 holds resolved field 11219 * r9 holds object 11220 */ 11221.LOP_IGET_SHORT_finish: 11222 @bl common_squeak4 11223 cmp r9, #0 @ check object for null 11224 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11225 beq common_errNullObject @ object was null 11226 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11227 @ no-op @ acquiring load 11228 mov r2, rINST, lsr #8 @ r2<- A+ 11229 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11230 and r2, r2, #15 @ r2<- A 11231 GET_INST_OPCODE(ip) @ extract opcode from rINST 11232 SET_VREG(r0, r2) @ fp[A]<- r0 11233 GOTO_OPCODE(ip) @ jump to next instruction 11234 11235/* continuation for OP_IPUT */ 11236 11237 /* 11238 * Currently: 11239 * r0 holds resolved field 11240 * r9 holds object 11241 */ 11242.LOP_IPUT_finish: 11243 @bl common_squeak0 11244 mov r1, rINST, lsr #8 @ r1<- A+ 11245 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11246 and r1, r1, #15 @ r1<- A 11247 cmp r9, #0 @ check object for null 11248 GET_VREG(r0, r1) @ r0<- fp[A] 11249 beq common_errNullObject @ object was null 11250 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11251 GET_INST_OPCODE(ip) @ extract opcode from rINST 11252 @ no-op @ releasing store 11253 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 11254 GOTO_OPCODE(ip) @ jump to next instruction 11255 11256/* continuation for OP_IPUT_WIDE */ 11257 11258 /* 11259 * Currently: 11260 * r0 holds resolved field 11261 * r9 holds object 11262 */ 11263.LOP_IPUT_WIDE_finish: 11264 mov r2, rINST, lsr #8 @ r2<- A+ 11265 cmp r9, #0 @ check object for null 11266 and r2, r2, #15 @ r2<- A 11267 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11268 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 11269 beq common_errNullObject @ object was null 11270 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11271 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 11272 GET_INST_OPCODE(r10) @ extract opcode from rINST 11273 .if 0 11274 add r2, r9, r3 @ r2<- target address 11275 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 11276 .else 11277 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 11278 .endif 11279 GOTO_OPCODE(r10) @ jump to next instruction 11280 11281/* continuation for OP_IPUT_OBJECT */ 11282 11283 /* 11284 * Currently: 11285 * r0 holds resolved field 11286 * r9 holds object 11287 */ 11288.LOP_IPUT_OBJECT_finish: 11289 @bl common_squeak0 11290 mov r1, rINST, lsr #8 @ r1<- A+ 11291 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11292 and r1, r1, #15 @ r1<- A 11293 cmp r9, #0 @ check object for null 11294 GET_VREG(r0, r1) @ r0<- fp[A] 11295 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 11296 beq common_errNullObject @ object was null 11297 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11298 GET_INST_OPCODE(ip) @ extract opcode from rINST 11299 @ no-op @ releasing store 11300 str r0, [r9, r3] @ obj.field (32 bits)<- r0 11301 cmp r0, #0 @ stored a null reference? 11302 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 11303 GOTO_OPCODE(ip) @ jump to next instruction 11304 11305/* continuation for OP_IPUT_BOOLEAN */ 11306 11307 /* 11308 * Currently: 11309 * r0 holds resolved field 11310 * r9 holds object 11311 */ 11312.LOP_IPUT_BOOLEAN_finish: 11313 @bl common_squeak1 11314 mov r1, rINST, lsr #8 @ r1<- A+ 11315 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11316 and r1, r1, #15 @ r1<- A 11317 cmp r9, #0 @ check object for null 11318 GET_VREG(r0, r1) @ r0<- fp[A] 11319 beq common_errNullObject @ object was null 11320 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11321 GET_INST_OPCODE(ip) @ extract opcode from rINST 11322 @ no-op @ releasing store 11323 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 11324 GOTO_OPCODE(ip) @ jump to next instruction 11325 11326/* continuation for OP_IPUT_BYTE */ 11327 11328 /* 11329 * Currently: 11330 * r0 holds resolved field 11331 * r9 holds object 11332 */ 11333.LOP_IPUT_BYTE_finish: 11334 @bl common_squeak2 11335 mov r1, rINST, lsr #8 @ r1<- A+ 11336 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11337 and r1, r1, #15 @ r1<- A 11338 cmp r9, #0 @ check object for null 11339 GET_VREG(r0, r1) @ r0<- fp[A] 11340 beq common_errNullObject @ object was null 11341 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11342 GET_INST_OPCODE(ip) @ extract opcode from rINST 11343 @ no-op @ releasing store 11344 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 11345 GOTO_OPCODE(ip) @ jump to next instruction 11346 11347/* continuation for OP_IPUT_CHAR */ 11348 11349 /* 11350 * Currently: 11351 * r0 holds resolved field 11352 * r9 holds object 11353 */ 11354.LOP_IPUT_CHAR_finish: 11355 @bl common_squeak3 11356 mov r1, rINST, lsr #8 @ r1<- A+ 11357 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11358 and r1, r1, #15 @ r1<- A 11359 cmp r9, #0 @ check object for null 11360 GET_VREG(r0, r1) @ r0<- fp[A] 11361 beq common_errNullObject @ object was null 11362 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11363 GET_INST_OPCODE(ip) @ extract opcode from rINST 11364 @ no-op @ releasing store 11365 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 11366 GOTO_OPCODE(ip) @ jump to next instruction 11367 11368/* continuation for OP_IPUT_SHORT */ 11369 11370 /* 11371 * Currently: 11372 * r0 holds resolved field 11373 * r9 holds object 11374 */ 11375.LOP_IPUT_SHORT_finish: 11376 @bl common_squeak4 11377 mov r1, rINST, lsr #8 @ r1<- A+ 11378 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11379 and r1, r1, #15 @ r1<- A 11380 cmp r9, #0 @ check object for null 11381 GET_VREG(r0, r1) @ r0<- fp[A] 11382 beq common_errNullObject @ object was null 11383 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11384 GET_INST_OPCODE(ip) @ extract opcode from rINST 11385 @ no-op @ releasing store 11386 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 11387 GOTO_OPCODE(ip) @ jump to next instruction 11388 11389/* continuation for OP_SGET */ 11390 11391 /* 11392 * Continuation if the field has not yet been resolved. 11393 * r1: BBBB field ref 11394 */ 11395.LOP_SGET_resolve: 11396 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11397 EXPORT_PC() @ resolve() could throw, so export now 11398 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11399 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11400 cmp r0, #0 @ success? 11401 bne .LOP_SGET_finish @ yes, finish 11402 b common_exceptionThrown @ no, handle exception 11403 11404/* continuation for OP_SGET_WIDE */ 11405 11406 /* 11407 * Continuation if the field has not yet been resolved. 11408 * r1: BBBB field ref 11409 * 11410 * Returns StaticField pointer in r0. 11411 */ 11412.LOP_SGET_WIDE_resolve: 11413 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11414 EXPORT_PC() @ resolve() could throw, so export now 11415 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11416 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11417 cmp r0, #0 @ success? 11418 bne .LOP_SGET_WIDE_finish @ yes, finish 11419 b common_exceptionThrown @ no, handle exception 11420 11421/* continuation for OP_SGET_OBJECT */ 11422 11423 /* 11424 * Continuation if the field has not yet been resolved. 11425 * r1: BBBB field ref 11426 */ 11427.LOP_SGET_OBJECT_resolve: 11428 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11429 EXPORT_PC() @ resolve() could throw, so export now 11430 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11431 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11432 cmp r0, #0 @ success? 11433 bne .LOP_SGET_OBJECT_finish @ yes, finish 11434 b common_exceptionThrown @ no, handle exception 11435 11436/* continuation for OP_SGET_BOOLEAN */ 11437 11438 /* 11439 * Continuation if the field has not yet been resolved. 11440 * r1: BBBB field ref 11441 */ 11442.LOP_SGET_BOOLEAN_resolve: 11443 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11444 EXPORT_PC() @ resolve() could throw, so export now 11445 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11446 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11447 cmp r0, #0 @ success? 11448 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 11449 b common_exceptionThrown @ no, handle exception 11450 11451/* continuation for OP_SGET_BYTE */ 11452 11453 /* 11454 * Continuation if the field has not yet been resolved. 11455 * r1: BBBB field ref 11456 */ 11457.LOP_SGET_BYTE_resolve: 11458 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11459 EXPORT_PC() @ resolve() could throw, so export now 11460 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11461 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11462 cmp r0, #0 @ success? 11463 bne .LOP_SGET_BYTE_finish @ yes, finish 11464 b common_exceptionThrown @ no, handle exception 11465 11466/* continuation for OP_SGET_CHAR */ 11467 11468 /* 11469 * Continuation if the field has not yet been resolved. 11470 * r1: BBBB field ref 11471 */ 11472.LOP_SGET_CHAR_resolve: 11473 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11474 EXPORT_PC() @ resolve() could throw, so export now 11475 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11476 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11477 cmp r0, #0 @ success? 11478 bne .LOP_SGET_CHAR_finish @ yes, finish 11479 b common_exceptionThrown @ no, handle exception 11480 11481/* continuation for OP_SGET_SHORT */ 11482 11483 /* 11484 * Continuation if the field has not yet been resolved. 11485 * r1: BBBB field ref 11486 */ 11487.LOP_SGET_SHORT_resolve: 11488 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11489 EXPORT_PC() @ resolve() could throw, so export now 11490 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11491 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11492 cmp r0, #0 @ success? 11493 bne .LOP_SGET_SHORT_finish @ yes, finish 11494 b common_exceptionThrown @ no, handle exception 11495 11496/* continuation for OP_SPUT */ 11497 11498 /* 11499 * Continuation if the field has not yet been resolved. 11500 * r1: BBBB field ref 11501 */ 11502.LOP_SPUT_resolve: 11503 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11504 EXPORT_PC() @ resolve() could throw, so export now 11505 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11506 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11507 cmp r0, #0 @ success? 11508 bne .LOP_SPUT_finish @ yes, finish 11509 b common_exceptionThrown @ no, handle exception 11510 11511/* continuation for OP_SPUT_WIDE */ 11512 11513 /* 11514 * Continuation if the field has not yet been resolved. 11515 * r1: BBBB field ref 11516 * r9: &fp[AA] 11517 * 11518 * Returns StaticField pointer in r2. 11519 */ 11520.LOP_SPUT_WIDE_resolve: 11521 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11522 EXPORT_PC() @ resolve() could throw, so export now 11523 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11524 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11525 cmp r0, #0 @ success? 11526 mov r2, r0 @ copy to r2 11527 bne .LOP_SPUT_WIDE_finish @ yes, finish 11528 b common_exceptionThrown @ no, handle exception 11529 11530/* continuation for OP_SPUT_OBJECT */ 11531.LOP_SPUT_OBJECT_finish: @ field ptr in r0 11532 mov r2, rINST, lsr #8 @ r2<- AA 11533 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11534 GET_VREG(r1, r2) @ r1<- fp[AA] 11535 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 11536 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz 11537 GET_INST_OPCODE(ip) @ extract opcode from rINST 11538 @ no-op @ releasing store 11539 str r1, [r0, #offStaticField_value] @ field<- vAA 11540 cmp r1, #0 @ stored a null object? 11541 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 11542 GOTO_OPCODE(ip) @ jump to next instruction 11543 11544/* continuation for OP_SPUT_BOOLEAN */ 11545 11546 /* 11547 * Continuation if the field has not yet been resolved. 11548 * r1: BBBB field ref 11549 */ 11550.LOP_SPUT_BOOLEAN_resolve: 11551 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11552 EXPORT_PC() @ resolve() could throw, so export now 11553 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11554 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11555 cmp r0, #0 @ success? 11556 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 11557 b common_exceptionThrown @ no, handle exception 11558 11559/* continuation for OP_SPUT_BYTE */ 11560 11561 /* 11562 * Continuation if the field has not yet been resolved. 11563 * r1: BBBB field ref 11564 */ 11565.LOP_SPUT_BYTE_resolve: 11566 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11567 EXPORT_PC() @ resolve() could throw, so export now 11568 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11569 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11570 cmp r0, #0 @ success? 11571 bne .LOP_SPUT_BYTE_finish @ yes, finish 11572 b common_exceptionThrown @ no, handle exception 11573 11574/* continuation for OP_SPUT_CHAR */ 11575 11576 /* 11577 * Continuation if the field has not yet been resolved. 11578 * r1: BBBB field ref 11579 */ 11580.LOP_SPUT_CHAR_resolve: 11581 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11582 EXPORT_PC() @ resolve() could throw, so export now 11583 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11584 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11585 cmp r0, #0 @ success? 11586 bne .LOP_SPUT_CHAR_finish @ yes, finish 11587 b common_exceptionThrown @ no, handle exception 11588 11589/* continuation for OP_SPUT_SHORT */ 11590 11591 /* 11592 * Continuation if the field has not yet been resolved. 11593 * r1: BBBB field ref 11594 */ 11595.LOP_SPUT_SHORT_resolve: 11596 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11597 EXPORT_PC() @ resolve() could throw, so export now 11598 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11599 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11600 cmp r0, #0 @ success? 11601 bne .LOP_SPUT_SHORT_finish @ yes, finish 11602 b common_exceptionThrown @ no, handle exception 11603 11604/* continuation for OP_INVOKE_VIRTUAL */ 11605 11606 /* 11607 * At this point: 11608 * r0 = resolved base method 11609 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 11610 */ 11611.LOP_INVOKE_VIRTUAL_continue: 11612 GET_VREG(r1, r10) @ r1<- "this" ptr 11613 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 11614 cmp r1, #0 @ is "this" null? 11615 beq common_errNullObject @ null "this", throw exception 11616 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 11617 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 11618 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 11619 bl common_invokeMethodNoRange @ continue on 11620 11621/* continuation for OP_INVOKE_SUPER */ 11622 11623 /* 11624 * At this point: 11625 * r0 = resolved base method 11626 * r9 = method->clazz 11627 */ 11628.LOP_INVOKE_SUPER_continue: 11629 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 11630 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 11631 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 11632 EXPORT_PC() @ must export for invoke 11633 cmp r2, r3 @ compare (methodIndex, vtableCount) 11634 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 11635 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 11636 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 11637 bl common_invokeMethodNoRange @ continue on 11638 11639.LOP_INVOKE_SUPER_resolve: 11640 mov r0, r9 @ r0<- method->clazz 11641 mov r2, #METHOD_VIRTUAL @ resolver method type 11642 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 11643 cmp r0, #0 @ got null? 11644 bne .LOP_INVOKE_SUPER_continue @ no, continue 11645 b common_exceptionThrown @ yes, handle exception 11646 11647 /* 11648 * Throw a NoSuchMethodError with the method name as the message. 11649 * r0 = resolved base method 11650 */ 11651.LOP_INVOKE_SUPER_nsm: 11652 ldr r1, [r0, #offMethod_name] @ r1<- method name 11653 b common_errNoSuchMethod 11654 11655/* continuation for OP_INVOKE_DIRECT */ 11656 11657 /* 11658 * On entry: 11659 * r1 = reference (BBBB or CCCC) 11660 * r10 = "this" register 11661 */ 11662.LOP_INVOKE_DIRECT_resolve: 11663 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 11664 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 11665 mov r2, #METHOD_DIRECT @ resolver method type 11666 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 11667 cmp r0, #0 @ got null? 11668 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 11669 bne .LOP_INVOKE_DIRECT_finish @ no, continue 11670 b common_exceptionThrown @ yes, handle exception 11671 11672/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 11673 11674 /* 11675 * At this point: 11676 * r0 = resolved base method 11677 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 11678 */ 11679.LOP_INVOKE_VIRTUAL_RANGE_continue: 11680 GET_VREG(r1, r10) @ r1<- "this" ptr 11681 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 11682 cmp r1, #0 @ is "this" null? 11683 beq common_errNullObject @ null "this", throw exception 11684 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 11685 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 11686 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 11687 bl common_invokeMethodRange @ continue on 11688 11689/* continuation for OP_INVOKE_SUPER_RANGE */ 11690 11691 /* 11692 * At this point: 11693 * r0 = resolved base method 11694 * r9 = method->clazz 11695 */ 11696.LOP_INVOKE_SUPER_RANGE_continue: 11697 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 11698 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 11699 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 11700 EXPORT_PC() @ must export for invoke 11701 cmp r2, r3 @ compare (methodIndex, vtableCount) 11702 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 11703 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 11704 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 11705 bl common_invokeMethodRange @ continue on 11706 11707.LOP_INVOKE_SUPER_RANGE_resolve: 11708 mov r0, r9 @ r0<- method->clazz 11709 mov r2, #METHOD_VIRTUAL @ resolver method type 11710 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 11711 cmp r0, #0 @ got null? 11712 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 11713 b common_exceptionThrown @ yes, handle exception 11714 11715 /* 11716 * Throw a NoSuchMethodError with the method name as the message. 11717 * r0 = resolved base method 11718 */ 11719.LOP_INVOKE_SUPER_RANGE_nsm: 11720 ldr r1, [r0, #offMethod_name] @ r1<- method name 11721 b common_errNoSuchMethod 11722 11723/* continuation for OP_INVOKE_DIRECT_RANGE */ 11724 11725 /* 11726 * On entry: 11727 * r1 = reference (BBBB or CCCC) 11728 * r10 = "this" register 11729 */ 11730.LOP_INVOKE_DIRECT_RANGE_resolve: 11731 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 11732 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 11733 mov r2, #METHOD_DIRECT @ resolver method type 11734 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 11735 cmp r0, #0 @ got null? 11736 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 11737 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 11738 b common_exceptionThrown @ yes, handle exception 11739 11740/* continuation for OP_FLOAT_TO_LONG */ 11741/* 11742 * Convert the float in r0 to a long in r0/r1. 11743 * 11744 * We have to clip values to long min/max per the specification. The 11745 * expected common case is a "reasonable" value that converts directly 11746 * to modest integer. The EABI convert function isn't doing this for us. 11747 */ 11748f2l_doconv: 11749 stmfd sp!, {r4, lr} 11750 mov r1, #0x5f000000 @ (float)maxlong 11751 mov r4, r0 11752 bl __aeabi_fcmpge @ is arg >= maxlong? 11753 cmp r0, #0 @ nonzero == yes 11754 mvnne r0, #0 @ return maxlong (7fffffff) 11755 mvnne r1, #0x80000000 11756 ldmnefd sp!, {r4, pc} 11757 11758 mov r0, r4 @ recover arg 11759 mov r1, #0xdf000000 @ (float)minlong 11760 bl __aeabi_fcmple @ is arg <= minlong? 11761 cmp r0, #0 @ nonzero == yes 11762 movne r0, #0 @ return minlong (80000000) 11763 movne r1, #0x80000000 11764 ldmnefd sp!, {r4, pc} 11765 11766 mov r0, r4 @ recover arg 11767 mov r1, r4 11768 bl __aeabi_fcmpeq @ is arg == self? 11769 cmp r0, #0 @ zero == no 11770 moveq r1, #0 @ return zero for NaN 11771 ldmeqfd sp!, {r4, pc} 11772 11773 mov r0, r4 @ recover arg 11774 bl __aeabi_f2lz @ convert float to long 11775 ldmfd sp!, {r4, pc} 11776 11777/* continuation for OP_DOUBLE_TO_LONG */ 11778/* 11779 * Convert the double in r0/r1 to a long in r0/r1. 11780 * 11781 * We have to clip values to long min/max per the specification. The 11782 * expected common case is a "reasonable" value that converts directly 11783 * to modest integer. The EABI convert function isn't doing this for us. 11784 */ 11785d2l_doconv: 11786 stmfd sp!, {r4, r5, lr} @ save regs 11787 mov r3, #0x43000000 @ maxlong, as a double (high word) 11788 add r3, #0x00e00000 @ 0x43e00000 11789 mov r2, #0 @ maxlong, as a double (low word) 11790 sub sp, sp, #4 @ align for EABI 11791 mov r4, r0 @ save a copy of r0 11792 mov r5, r1 @ and r1 11793 bl __aeabi_dcmpge @ is arg >= maxlong? 11794 cmp r0, #0 @ nonzero == yes 11795 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 11796 mvnne r1, #0x80000000 11797 bne 1f 11798 11799 mov r0, r4 @ recover arg 11800 mov r1, r5 11801 mov r3, #0xc3000000 @ minlong, as a double (high word) 11802 add r3, #0x00e00000 @ 0xc3e00000 11803 mov r2, #0 @ minlong, as a double (low word) 11804 bl __aeabi_dcmple @ is arg <= minlong? 11805 cmp r0, #0 @ nonzero == yes 11806 movne r0, #0 @ return minlong (8000000000000000) 11807 movne r1, #0x80000000 11808 bne 1f 11809 11810 mov r0, r4 @ recover arg 11811 mov r1, r5 11812 mov r2, r4 @ compare against self 11813 mov r3, r5 11814 bl __aeabi_dcmpeq @ is arg == self? 11815 cmp r0, #0 @ zero == no 11816 moveq r1, #0 @ return zero for NaN 11817 beq 1f 11818 11819 mov r0, r4 @ recover arg 11820 mov r1, r5 11821 bl __aeabi_d2lz @ convert double to long 11822 118231: 11824 add sp, sp, #4 11825 ldmfd sp!, {r4, r5, pc} 11826 11827/* continuation for OP_MUL_LONG */ 11828 11829.LOP_MUL_LONG_finish: 11830 GET_INST_OPCODE(ip) @ extract opcode from rINST 11831 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 11832 GOTO_OPCODE(ip) @ jump to next instruction 11833 11834/* continuation for OP_SHL_LONG */ 11835 11836.LOP_SHL_LONG_finish: 11837 mov r0, r0, asl r2 @ r0<- r0 << r2 11838 GET_INST_OPCODE(ip) @ extract opcode from rINST 11839 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 11840 GOTO_OPCODE(ip) @ jump to next instruction 11841 11842/* continuation for OP_SHR_LONG */ 11843 11844.LOP_SHR_LONG_finish: 11845 mov r1, r1, asr r2 @ r1<- r1 >> r2 11846 GET_INST_OPCODE(ip) @ extract opcode from rINST 11847 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 11848 GOTO_OPCODE(ip) @ jump to next instruction 11849 11850/* continuation for OP_USHR_LONG */ 11851 11852.LOP_USHR_LONG_finish: 11853 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 11854 GET_INST_OPCODE(ip) @ extract opcode from rINST 11855 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 11856 GOTO_OPCODE(ip) @ jump to next instruction 11857 11858/* continuation for OP_SHL_LONG_2ADDR */ 11859 11860.LOP_SHL_LONG_2ADDR_finish: 11861 GET_INST_OPCODE(ip) @ extract opcode from rINST 11862 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 11863 GOTO_OPCODE(ip) @ jump to next instruction 11864 11865/* continuation for OP_SHR_LONG_2ADDR */ 11866 11867.LOP_SHR_LONG_2ADDR_finish: 11868 GET_INST_OPCODE(ip) @ extract opcode from rINST 11869 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 11870 GOTO_OPCODE(ip) @ jump to next instruction 11871 11872/* continuation for OP_USHR_LONG_2ADDR */ 11873 11874.LOP_USHR_LONG_2ADDR_finish: 11875 GET_INST_OPCODE(ip) @ extract opcode from rINST 11876 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 11877 GOTO_OPCODE(ip) @ jump to next instruction 11878 11879/* continuation for OP_IGET_VOLATILE */ 11880 11881 /* 11882 * Currently: 11883 * r0 holds resolved field 11884 * r9 holds object 11885 */ 11886.LOP_IGET_VOLATILE_finish: 11887 @bl common_squeak0 11888 cmp r9, #0 @ check object for null 11889 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11890 beq common_errNullObject @ object was null 11891 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11892 SMP_DMB @ acquiring load 11893 mov r2, rINST, lsr #8 @ r2<- A+ 11894 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11895 and r2, r2, #15 @ r2<- A 11896 GET_INST_OPCODE(ip) @ extract opcode from rINST 11897 SET_VREG(r0, r2) @ fp[A]<- r0 11898 GOTO_OPCODE(ip) @ jump to next instruction 11899 11900/* continuation for OP_IPUT_VOLATILE */ 11901 11902 /* 11903 * Currently: 11904 * r0 holds resolved field 11905 * r9 holds object 11906 */ 11907.LOP_IPUT_VOLATILE_finish: 11908 @bl common_squeak0 11909 mov r1, rINST, lsr #8 @ r1<- A+ 11910 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11911 and r1, r1, #15 @ r1<- A 11912 cmp r9, #0 @ check object for null 11913 GET_VREG(r0, r1) @ r0<- fp[A] 11914 beq common_errNullObject @ object was null 11915 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11916 GET_INST_OPCODE(ip) @ extract opcode from rINST 11917 SMP_DMB @ releasing store 11918 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 11919 GOTO_OPCODE(ip) @ jump to next instruction 11920 11921/* continuation for OP_SGET_VOLATILE */ 11922 11923 /* 11924 * Continuation if the field has not yet been resolved. 11925 * r1: BBBB field ref 11926 */ 11927.LOP_SGET_VOLATILE_resolve: 11928 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11929 EXPORT_PC() @ resolve() could throw, so export now 11930 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11931 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11932 cmp r0, #0 @ success? 11933 bne .LOP_SGET_VOLATILE_finish @ yes, finish 11934 b common_exceptionThrown @ no, handle exception 11935 11936/* continuation for OP_SPUT_VOLATILE */ 11937 11938 /* 11939 * Continuation if the field has not yet been resolved. 11940 * r1: BBBB field ref 11941 */ 11942.LOP_SPUT_VOLATILE_resolve: 11943 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 11944 EXPORT_PC() @ resolve() could throw, so export now 11945 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 11946 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 11947 cmp r0, #0 @ success? 11948 bne .LOP_SPUT_VOLATILE_finish @ yes, finish 11949 b common_exceptionThrown @ no, handle exception 11950 11951/* continuation for OP_IGET_OBJECT_VOLATILE */ 11952 11953 /* 11954 * Currently: 11955 * r0 holds resolved field 11956 * r9 holds object 11957 */ 11958.LOP_IGET_OBJECT_VOLATILE_finish: 11959 @bl common_squeak0 11960 cmp r9, #0 @ check object for null 11961 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11962 beq common_errNullObject @ object was null 11963 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 11964 SMP_DMB @ acquiring load 11965 mov r2, rINST, lsr #8 @ r2<- A+ 11966 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11967 and r2, r2, #15 @ r2<- A 11968 GET_INST_OPCODE(ip) @ extract opcode from rINST 11969 SET_VREG(r0, r2) @ fp[A]<- r0 11970 GOTO_OPCODE(ip) @ jump to next instruction 11971 11972/* continuation for OP_IGET_WIDE_VOLATILE */ 11973 11974 /* 11975 * Currently: 11976 * r0 holds resolved field 11977 * r9 holds object 11978 */ 11979.LOP_IGET_WIDE_VOLATILE_finish: 11980 cmp r9, #0 @ check object for null 11981 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 11982 beq common_errNullObject @ object was null 11983 .if 1 11984 add r0, r9, r3 @ r0<- address of field 11985 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 11986 .else 11987 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 11988 .endif 11989 mov r2, rINST, lsr #8 @ r2<- A+ 11990 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 11991 and r2, r2, #15 @ r2<- A 11992 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 11993 GET_INST_OPCODE(ip) @ extract opcode from rINST 11994 stmia r3, {r0-r1} @ fp[A]<- r0/r1 11995 GOTO_OPCODE(ip) @ jump to next instruction 11996 11997/* continuation for OP_IPUT_WIDE_VOLATILE */ 11998 11999 /* 12000 * Currently: 12001 * r0 holds resolved field 12002 * r9 holds object 12003 */ 12004.LOP_IPUT_WIDE_VOLATILE_finish: 12005 mov r2, rINST, lsr #8 @ r2<- A+ 12006 cmp r9, #0 @ check object for null 12007 and r2, r2, #15 @ r2<- A 12008 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12009 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 12010 beq common_errNullObject @ object was null 12011 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 12012 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 12013 GET_INST_OPCODE(r10) @ extract opcode from rINST 12014 .if 1 12015 add r2, r9, r3 @ r2<- target address 12016 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 12017 .else 12018 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 12019 .endif 12020 GOTO_OPCODE(r10) @ jump to next instruction 12021 12022/* continuation for OP_SGET_WIDE_VOLATILE */ 12023 12024 /* 12025 * Continuation if the field has not yet been resolved. 12026 * r1: BBBB field ref 12027 * 12028 * Returns StaticField pointer in r0. 12029 */ 12030.LOP_SGET_WIDE_VOLATILE_resolve: 12031 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12032 EXPORT_PC() @ resolve() could throw, so export now 12033 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12034 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12035 cmp r0, #0 @ success? 12036 bne .LOP_SGET_WIDE_VOLATILE_finish @ yes, finish 12037 b common_exceptionThrown @ no, handle exception 12038 12039/* continuation for OP_SPUT_WIDE_VOLATILE */ 12040 12041 /* 12042 * Continuation if the field has not yet been resolved. 12043 * r1: BBBB field ref 12044 * r9: &fp[AA] 12045 * 12046 * Returns StaticField pointer in r2. 12047 */ 12048.LOP_SPUT_WIDE_VOLATILE_resolve: 12049 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12050 EXPORT_PC() @ resolve() could throw, so export now 12051 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12052 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12053 cmp r0, #0 @ success? 12054 mov r2, r0 @ copy to r2 12055 bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish 12056 b common_exceptionThrown @ no, handle exception 12057 12058/* continuation for OP_EXECUTE_INLINE */ 12059 12060 /* 12061 * Extract args, call function. 12062 * r0 = #of args (0-4) 12063 * r10 = call index 12064 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 12065 * 12066 * Other ideas: 12067 * - Use a jump table from the main piece to jump directly into the 12068 * AND/LDR pairs. Costs a data load, saves a branch. 12069 * - Have five separate pieces that do the loading, so we can work the 12070 * interleave a little better. Increases code size. 12071 */ 12072.LOP_EXECUTE_INLINE_continue: 12073 rsb r0, r0, #4 @ r0<- 4-r0 12074 FETCH(r9, 2) @ r9<- FEDC 12075 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 12076 bl common_abort @ (skipped due to ARM prefetch) 120774: and ip, r9, #0xf000 @ isolate F 12078 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 120793: and ip, r9, #0x0f00 @ isolate E 12080 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 120812: and ip, r9, #0x00f0 @ isolate D 12082 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 120831: and ip, r9, #0x000f @ isolate C 12084 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 120850: 12086 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 12087 ldr pc, [r9, r10, lsl #4] @ sizeof=16, "func" is first entry 12088 @ (not reached) 12089 12090.LOP_EXECUTE_INLINE_table: 12091 .word gDvmInlineOpsTable 12092 12093/* continuation for OP_EXECUTE_INLINE_RANGE */ 12094 12095 /* 12096 * Extract args, call function. 12097 * r0 = #of args (0-4) 12098 * r10 = call index 12099 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 12100 */ 12101.LOP_EXECUTE_INLINE_RANGE_continue: 12102 rsb r0, r0, #4 @ r0<- 4-r0 12103 FETCH(r9, 2) @ r9<- CCCC 12104 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 12105 bl common_abort @ (skipped due to ARM prefetch) 121064: add ip, r9, #3 @ base+3 12107 GET_VREG(r3, ip) @ r3<- vBase[3] 121083: add ip, r9, #2 @ base+2 12109 GET_VREG(r2, ip) @ r2<- vBase[2] 121102: add ip, r9, #1 @ base+1 12111 GET_VREG(r1, ip) @ r1<- vBase[1] 121121: add ip, r9, #0 @ (nop) 12113 GET_VREG(r0, ip) @ r0<- vBase[0] 121140: 12115 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation 12116 ldr pc, [r9, r10, lsl #4] @ sizeof=16, "func" is first entry 12117 @ (not reached) 12118 12119.LOP_EXECUTE_INLINE_RANGE_table: 12120 .word gDvmInlineOpsTable 12121 12122/* continuation for OP_IPUT_OBJECT_VOLATILE */ 12123 12124 /* 12125 * Currently: 12126 * r0 holds resolved field 12127 * r9 holds object 12128 */ 12129.LOP_IPUT_OBJECT_VOLATILE_finish: 12130 @bl common_squeak0 12131 mov r1, rINST, lsr #8 @ r1<- A+ 12132 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12133 and r1, r1, #15 @ r1<- A 12134 cmp r9, #0 @ check object for null 12135 GET_VREG(r0, r1) @ r0<- fp[A] 12136 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 12137 beq common_errNullObject @ object was null 12138 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 12139 GET_INST_OPCODE(ip) @ extract opcode from rINST 12140 SMP_DMB @ releasing store 12141 str r0, [r9, r3] @ obj.field (32 bits)<- r0 12142 cmp r0, #0 @ stored a null reference? 12143 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 12144 GOTO_OPCODE(ip) @ jump to next instruction 12145 12146/* continuation for OP_SGET_OBJECT_VOLATILE */ 12147 12148 /* 12149 * Continuation if the field has not yet been resolved. 12150 * r1: BBBB field ref 12151 */ 12152.LOP_SGET_OBJECT_VOLATILE_resolve: 12153 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12154 EXPORT_PC() @ resolve() could throw, so export now 12155 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12156 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12157 cmp r0, #0 @ success? 12158 bne .LOP_SGET_OBJECT_VOLATILE_finish @ yes, finish 12159 b common_exceptionThrown @ no, handle exception 12160 12161/* continuation for OP_SPUT_OBJECT_VOLATILE */ 12162.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0 12163 mov r2, rINST, lsr #8 @ r2<- AA 12164 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 12165 GET_VREG(r1, r2) @ r1<- fp[AA] 12166 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 12167 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz 12168 GET_INST_OPCODE(ip) @ extract opcode from rINST 12169 SMP_DMB @ releasing store 12170 str r1, [r0, #offStaticField_value] @ field<- vAA 12171 cmp r1, #0 @ stored a null object? 12172 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 12173 GOTO_OPCODE(ip) @ jump to next instruction 12174 12175/* continuation for OP_CONST_CLASS_JUMBO */ 12176 12177 /* 12178 * Continuation if the Class has not yet been resolved. 12179 * r1: AAAAAAAA (Class ref) 12180 * r9: target register 12181 */ 12182.LOP_CONST_CLASS_JUMBO_resolve: 12183 EXPORT_PC() 12184 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 12185 mov r2, #1 @ r2<- true 12186 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 12187 bl dvmResolveClass @ r0<- Class reference 12188 cmp r0, #0 @ failed? 12189 beq common_exceptionThrown @ yup, handle the exception 12190 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 12191 GET_INST_OPCODE(ip) @ extract opcode from rINST 12192 SET_VREG(r0, r9) @ vBBBB<- r0 12193 GOTO_OPCODE(ip) @ jump to next instruction 12194 12195/* continuation for OP_CHECK_CAST_JUMBO */ 12196 12197 /* 12198 * Trivial test failed, need to perform full check. This is common. 12199 * r0 holds obj->clazz 12200 * r1 holds desired class resolved from AAAAAAAA 12201 * r9 holds object 12202 */ 12203.LOP_CHECK_CAST_JUMBO_fullcheck: 12204 mov r10, r1 @ avoid ClassObject getting clobbered 12205 bl dvmInstanceofNonTrivial @ r0<- boolean result 12206 cmp r0, #0 @ failed? 12207 bne .LOP_CHECK_CAST_JUMBO_okay @ no, success 12208 12209 @ A cast has failed. We need to throw a ClassCastException. 12210 EXPORT_PC() @ about to throw 12211 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz (actual class) 12212 mov r1, r10 @ r1<- desired class 12213 bl dvmThrowClassCastException 12214 b common_exceptionThrown 12215 12216 /* 12217 * Advance PC and get the next opcode. 12218 */ 12219.LOP_CHECK_CAST_JUMBO_okay: 12220 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 12221 GET_INST_OPCODE(ip) @ extract opcode from rINST 12222 GOTO_OPCODE(ip) @ jump to next instruction 12223 12224 /* 12225 * Resolution required. This is the least-likely path. 12226 * 12227 * r2 holds AAAAAAAA 12228 * r9 holds object 12229 */ 12230.LOP_CHECK_CAST_JUMBO_resolve: 12231 EXPORT_PC() @ resolve() could throw 12232 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 12233 mov r1, r2 @ r1<- AAAAAAAA 12234 mov r2, #0 @ r2<- false 12235 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 12236 bl dvmResolveClass @ r0<- resolved ClassObject ptr 12237 cmp r0, #0 @ got null? 12238 beq common_exceptionThrown @ yes, handle exception 12239 mov r1, r0 @ r1<- class resolved from AAAAAAAA 12240 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 12241 b .LOP_CHECK_CAST_JUMBO_resolved @ pick up where we left off 12242 12243/* continuation for OP_INSTANCE_OF_JUMBO */ 12244 12245 /* 12246 * Class resolved, determine type of check necessary. This is common. 12247 * r0 holds obj->clazz 12248 * r1 holds class resolved from AAAAAAAA 12249 * r9 holds BBBB 12250 */ 12251.LOP_INSTANCE_OF_JUMBO_resolved: 12252 cmp r0, r1 @ same class (trivial success)? 12253 beq .LOP_INSTANCE_OF_JUMBO_trivial @ yes, trivial finish 12254 @ fall through to OP_INSTANCE_OF_JUMBO_fullcheck 12255 12256 /* 12257 * Trivial test failed, need to perform full check. This is common. 12258 * r0 holds obj->clazz 12259 * r1 holds class resolved from AAAAAAAA 12260 * r9 holds BBBB 12261 */ 12262.LOP_INSTANCE_OF_JUMBO_fullcheck: 12263 bl dvmInstanceofNonTrivial @ r0<- boolean result 12264 @ fall through to OP_INSTANCE_OF_JUMBO_store 12265 12266 /* 12267 * r0 holds boolean result 12268 * r9 holds BBBB 12269 */ 12270.LOP_INSTANCE_OF_JUMBO_store: 12271 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12272 SET_VREG(r0, r9) @ vBBBB<- r0 12273 GET_INST_OPCODE(ip) @ extract opcode from rINST 12274 GOTO_OPCODE(ip) @ jump to next instruction 12275 12276 /* 12277 * Trivial test succeeded, save and bail. 12278 * r9 holds BBBB 12279 */ 12280.LOP_INSTANCE_OF_JUMBO_trivial: 12281 mov r0, #1 @ indicate success 12282 @ could b OP_INSTANCE_OF_JUMBO_store, but copying is faster and cheaper 12283 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12284 SET_VREG(r0, r9) @ vBBBB<- r0 12285 GET_INST_OPCODE(ip) @ extract opcode from rINST 12286 GOTO_OPCODE(ip) @ jump to next instruction 12287 12288 /* 12289 * Resolution required. This is the least-likely path. 12290 * 12291 * r3 holds AAAAAAAA 12292 * r9 holds BBBB 12293 */ 12294 12295.LOP_INSTANCE_OF_JUMBO_resolve: 12296 EXPORT_PC() @ resolve() could throw 12297 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 12298 mov r1, r3 @ r1<- AAAAAAAA 12299 mov r2, #1 @ r2<- true 12300 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 12301 bl dvmResolveClass @ r0<- resolved ClassObject ptr 12302 cmp r0, #0 @ got null? 12303 beq common_exceptionThrown @ yes, handle exception 12304 FETCH(r3, 4) @ r3<- vCCCC 12305 mov r1, r0 @ r1<- class resolved from AAAAAAAA 12306 GET_VREG(r0, r3) @ r0<- vCCCC (object) 12307 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 12308 b .LOP_INSTANCE_OF_JUMBO_resolved @ pick up where we left off 12309 12310/* continuation for OP_NEW_INSTANCE_JUMBO */ 12311 12312 .balign 32 @ minimize cache lines 12313.LOP_NEW_INSTANCE_JUMBO_finish: @ r0=new object 12314 FETCH(r3, 3) @ r3<- BBBB 12315 cmp r0, #0 @ failed? 12316 beq common_exceptionThrown @ yes, handle the exception 12317 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 12318 GET_INST_OPCODE(ip) @ extract opcode from rINST 12319 SET_VREG(r0, r3) @ vBBBB<- r0 12320 GOTO_OPCODE(ip) @ jump to next instruction 12321 12322 /* 12323 * Class initialization required. 12324 * 12325 * r0 holds class object 12326 */ 12327.LOP_NEW_INSTANCE_JUMBO_needinit: 12328 mov r9, r0 @ save r0 12329 bl dvmInitClass @ initialize class 12330 cmp r0, #0 @ check boolean result 12331 mov r0, r9 @ restore r0 12332 bne .LOP_NEW_INSTANCE_JUMBO_initialized @ success, continue 12333 b common_exceptionThrown @ failed, deal with init exception 12334 12335 /* 12336 * Resolution required. This is the least-likely path. 12337 * 12338 * r1 holds AAAAAAAA 12339 */ 12340.LOP_NEW_INSTANCE_JUMBO_resolve: 12341 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 12342 mov r2, #0 @ r2<- false 12343 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 12344 bl dvmResolveClass @ r0<- resolved ClassObject ptr 12345 cmp r0, #0 @ got null? 12346 bne .LOP_NEW_INSTANCE_JUMBO_resolved @ no, continue 12347 b common_exceptionThrown @ yes, handle exception 12348 12349/* continuation for OP_NEW_ARRAY_JUMBO */ 12350 12351 12352 /* 12353 * Resolve class. (This is an uncommon case.) 12354 * 12355 * r1 holds array length 12356 * r2 holds class ref AAAAAAAA 12357 */ 12358.LOP_NEW_ARRAY_JUMBO_resolve: 12359 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 12360 mov r9, r1 @ r9<- length (save) 12361 mov r1, r2 @ r1<- AAAAAAAA 12362 mov r2, #0 @ r2<- false 12363 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 12364 bl dvmResolveClass @ r0<- call(clazz, ref) 12365 cmp r0, #0 @ got null? 12366 mov r1, r9 @ r1<- length (restore) 12367 beq common_exceptionThrown @ yes, handle exception 12368 @ fall through to OP_NEW_ARRAY_JUMBO_finish 12369 12370 /* 12371 * Finish allocation. 12372 * 12373 * r0 holds class 12374 * r1 holds array length 12375 */ 12376.LOP_NEW_ARRAY_JUMBO_finish: 12377 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 12378 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 12379 cmp r0, #0 @ failed? 12380 FETCH(r2, 3) @ r2<- vBBBB 12381 beq common_exceptionThrown @ yes, handle the exception 12382 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12383 GET_INST_OPCODE(ip) @ extract opcode from rINST 12384 SET_VREG(r0, r2) @ vBBBB<- r0 12385 GOTO_OPCODE(ip) @ jump to next instruction 12386 12387/* continuation for OP_FILLED_NEW_ARRAY_JUMBO */ 12388 12389 /* 12390 * On entry: 12391 * r0 holds array class 12392 */ 12393.LOP_FILLED_NEW_ARRAY_JUMBO_continue: 12394 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 12395 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 12396 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 12397 FETCH(r1, 3) @ r1<- BBBB (length) 12398 cmp rINST, #'I' @ array of ints? 12399 cmpne rINST, #'L' @ array of objects? 12400 cmpne rINST, #'[' @ array of arrays? 12401 mov r9, r1 @ save length in r9 12402 bne .LOP_FILLED_NEW_ARRAY_JUMBO_notimpl @ no, not handled yet 12403 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 12404 cmp r0, #0 @ null return? 12405 beq common_exceptionThrown @ alloc failed, handle exception 12406 12407 FETCH(r1, 4) @ r1<- CCCC 12408 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 12409 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 12410 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 12411 subs r9, r9, #1 @ length--, check for neg 12412 FETCH_ADVANCE_INST(5) @ advance to next instr, load rINST 12413 bmi 2f @ was zero, bail 12414 12415 @ copy values from registers into the array 12416 @ r0=array, r1=CCCC, r9=BBBB (length) 12417 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 124181: ldr r3, [r2], #4 @ r3<- *r2++ 12419 subs r9, r9, #1 @ count-- 12420 str r3, [r0], #4 @ *contents++ = vX 12421 bpl 1b 12422 124232: ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 12424 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 12425 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 12426 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 12427 cmp r1, #'I' @ Is int array? 12428 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 12429 GOTO_OPCODE(ip) @ execute it 12430 12431 /* 12432 * Throw an exception indicating that we have not implemented this 12433 * mode of filled-new-array. 12434 */ 12435.LOP_FILLED_NEW_ARRAY_JUMBO_notimpl: 12436 ldr r0, .L_strInternalError 12437 ldr r1, .L_strFilledNewArrayNotImpl 12438 bl dvmThrowException 12439 b common_exceptionThrown 12440 12441/* continuation for OP_IGET_JUMBO */ 12442 12443 /* 12444 * Currently: 12445 * r0 holds resolved field 12446 * r9 holds object 12447 */ 12448.LOP_IGET_JUMBO_resolved: 12449 cmp r0, #0 @ resolution unsuccessful? 12450 beq common_exceptionThrown @ yes, throw exception 12451 @ fall through to OP_IGET_JUMBO_finish 12452 12453 /* 12454 * Currently: 12455 * r0 holds resolved field 12456 * r9 holds object 12457 */ 12458.LOP_IGET_JUMBO_finish: 12459 @bl common_squeak0 12460 cmp r9, #0 @ check object for null 12461 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12462 beq common_errNullObject @ object was null 12463 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 12464 @ no-op @ acquiring load 12465 FETCH(r2, 3) @ r2<- BBBB 12466 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12467 SET_VREG(r0, r2) @ fp[BBBB]<- r0 12468 GET_INST_OPCODE(ip) @ extract opcode from rINST 12469 GOTO_OPCODE(ip) @ jump to next instruction 12470 12471/* continuation for OP_IGET_WIDE_JUMBO */ 12472 12473 /* 12474 * Currently: 12475 * r0 holds resolved field 12476 * r9 holds object 12477 */ 12478.LOP_IGET_WIDE_JUMBO_resolved: 12479 cmp r0, #0 @ resolution unsuccessful? 12480 beq common_exceptionThrown @ yes, throw exception 12481 @ fall through to OP_IGET_WIDE_JUMBO_finish 12482 12483 /* 12484 * Currently: 12485 * r0 holds resolved field 12486 * r9 holds object 12487 */ 12488.LOP_IGET_WIDE_JUMBO_finish: 12489 cmp r9, #0 @ check object for null 12490 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12491 beq common_errNullObject @ object was null 12492 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 12493 FETCH(r2, 3) @ r2<- BBBB 12494 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12495 add r3, rFP, r2, lsl #2 @ r3<- &fp[BBBB] 12496 GET_INST_OPCODE(ip) @ extract opcode from rINST 12497 stmia r3, {r0-r1} @ fp[BBBB]<- r0/r1 12498 GOTO_OPCODE(ip) @ jump to next instruction 12499 12500/* continuation for OP_IGET_OBJECT_JUMBO */ 12501 12502 /* 12503 * Currently: 12504 * r0 holds resolved field 12505 * r9 holds object 12506 */ 12507.LOP_IGET_OBJECT_JUMBO_resolved: 12508 cmp r0, #0 @ resolution unsuccessful? 12509 beq common_exceptionThrown @ yes, throw exception 12510 @ fall through to OP_IGET_OBJECT_JUMBO_finish 12511 12512 /* 12513 * Currently: 12514 * r0 holds resolved field 12515 * r9 holds object 12516 */ 12517.LOP_IGET_OBJECT_JUMBO_finish: 12518 @bl common_squeak0 12519 cmp r9, #0 @ check object for null 12520 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12521 beq common_errNullObject @ object was null 12522 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 12523 @ no-op @ acquiring load 12524 FETCH(r2, 3) @ r2<- BBBB 12525 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12526 SET_VREG(r0, r2) @ fp[BBBB]<- r0 12527 GET_INST_OPCODE(ip) @ extract opcode from rINST 12528 GOTO_OPCODE(ip) @ jump to next instruction 12529 12530/* continuation for OP_IGET_BOOLEAN_JUMBO */ 12531 12532 /* 12533 * Currently: 12534 * r0 holds resolved field 12535 * r9 holds object 12536 */ 12537.LOP_IGET_BOOLEAN_JUMBO_resolved: 12538 cmp r0, #0 @ resolution unsuccessful? 12539 beq common_exceptionThrown @ yes, throw exception 12540 @ fall through to OP_IGET_BOOLEAN_JUMBO_finish 12541 12542 /* 12543 * Currently: 12544 * r0 holds resolved field 12545 * r9 holds object 12546 */ 12547.LOP_IGET_BOOLEAN_JUMBO_finish: 12548 @bl common_squeak1 12549 cmp r9, #0 @ check object for null 12550 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12551 beq common_errNullObject @ object was null 12552 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 12553 @ no-op @ acquiring load 12554 FETCH(r2, 3) @ r2<- BBBB 12555 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12556 SET_VREG(r0, r2) @ fp[BBBB]<- r0 12557 GET_INST_OPCODE(ip) @ extract opcode from rINST 12558 GOTO_OPCODE(ip) @ jump to next instruction 12559 12560/* continuation for OP_IGET_BYTE_JUMBO */ 12561 12562 /* 12563 * Currently: 12564 * r0 holds resolved field 12565 * r9 holds object 12566 */ 12567.LOP_IGET_BYTE_JUMBO_resolved: 12568 cmp r0, #0 @ resolution unsuccessful? 12569 beq common_exceptionThrown @ yes, throw exception 12570 @ fall through to OP_IGET_BYTE_JUMBO_finish 12571 12572 /* 12573 * Currently: 12574 * r0 holds resolved field 12575 * r9 holds object 12576 */ 12577.LOP_IGET_BYTE_JUMBO_finish: 12578 @bl common_squeak2 12579 cmp r9, #0 @ check object for null 12580 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12581 beq common_errNullObject @ object was null 12582 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 12583 @ no-op @ acquiring load 12584 FETCH(r2, 3) @ r2<- BBBB 12585 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12586 SET_VREG(r0, r2) @ fp[BBBB]<- r0 12587 GET_INST_OPCODE(ip) @ extract opcode from rINST 12588 GOTO_OPCODE(ip) @ jump to next instruction 12589 12590/* continuation for OP_IGET_CHAR_JUMBO */ 12591 12592 /* 12593 * Currently: 12594 * r0 holds resolved field 12595 * r9 holds object 12596 */ 12597.LOP_IGET_CHAR_JUMBO_resolved: 12598 cmp r0, #0 @ resolution unsuccessful? 12599 beq common_exceptionThrown @ yes, throw exception 12600 @ fall through to OP_IGET_CHAR_JUMBO_finish 12601 12602 /* 12603 * Currently: 12604 * r0 holds resolved field 12605 * r9 holds object 12606 */ 12607.LOP_IGET_CHAR_JUMBO_finish: 12608 @bl common_squeak3 12609 cmp r9, #0 @ check object for null 12610 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12611 beq common_errNullObject @ object was null 12612 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 12613 @ no-op @ acquiring load 12614 FETCH(r2, 3) @ r2<- BBBB 12615 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12616 SET_VREG(r0, r2) @ fp[BBBB]<- r0 12617 GET_INST_OPCODE(ip) @ extract opcode from rINST 12618 GOTO_OPCODE(ip) @ jump to next instruction 12619 12620/* continuation for OP_IGET_SHORT_JUMBO */ 12621 12622 /* 12623 * Currently: 12624 * r0 holds resolved field 12625 * r9 holds object 12626 */ 12627.LOP_IGET_SHORT_JUMBO_resolved: 12628 cmp r0, #0 @ resolution unsuccessful? 12629 beq common_exceptionThrown @ yes, throw exception 12630 @ fall through to OP_IGET_SHORT_JUMBO_finish 12631 12632 /* 12633 * Currently: 12634 * r0 holds resolved field 12635 * r9 holds object 12636 */ 12637.LOP_IGET_SHORT_JUMBO_finish: 12638 @bl common_squeak4 12639 cmp r9, #0 @ check object for null 12640 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12641 beq common_errNullObject @ object was null 12642 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 12643 @ no-op @ acquiring load 12644 FETCH(r2, 3) @ r2<- BBBB 12645 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12646 SET_VREG(r0, r2) @ fp[BBBB]<- r0 12647 GET_INST_OPCODE(ip) @ extract opcode from rINST 12648 GOTO_OPCODE(ip) @ jump to next instruction 12649 12650/* continuation for OP_IPUT_JUMBO */ 12651 12652 /* 12653 * Currently: 12654 * r0 holds resolved field 12655 * r9 holds object 12656 */ 12657.LOP_IPUT_JUMBO_resolved: 12658 cmp r0, #0 @ resolution unsuccessful? 12659 beq common_exceptionThrown @ yes, throw exception 12660 @ fall through to OP_IPUT_JUMBO_finish 12661 12662 /* 12663 * Currently: 12664 * r0 holds resolved field 12665 * r9 holds object 12666 */ 12667.LOP_IPUT_JUMBO_finish: 12668 @bl common_squeak0 12669 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12670 FETCH(r1, 3) @ r1<- BBBB 12671 cmp r9, #0 @ check object for null 12672 GET_VREG(r0, r1) @ r0<- fp[BBBB] 12673 beq common_errNullObject @ object was null 12674 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12675 GET_INST_OPCODE(ip) @ extract opcode from rINST 12676 @ no-op @ releasing store 12677 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 12678 GOTO_OPCODE(ip) @ jump to next instruction 12679 12680/* continuation for OP_IPUT_WIDE_JUMBO */ 12681 12682 /* 12683 * Currently: 12684 * r0 holds resolved field 12685 * r9 holds object 12686 */ 12687.LOP_IPUT_WIDE_JUMBO_resolved: 12688 cmp r0, #0 @ resolution unsuccessful? 12689 beq common_exceptionThrown @ yes, throw exception 12690 @ fall through to OP_IPUT_WIDE_JUMBO_finish 12691 12692 /* 12693 * Currently: 12694 * r0 holds resolved field 12695 * r9 holds object 12696 */ 12697.LOP_IPUT_WIDE_JUMBO_finish: 12698 cmp r9, #0 @ check object for null 12699 FETCH(r2, 3) @ r1<- BBBB 12700 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12701 add r2, rFP, r2, lsl #2 @ r3<- &fp[BBBB] 12702 beq common_errNullObject @ object was null 12703 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12704 ldmia r2, {r0-r1} @ r0/r1<- fp[BBBB] 12705 GET_INST_OPCODE(r10) @ extract opcode from rINST 12706 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 12707 GOTO_OPCODE(r10) @ jump to next instruction 12708 12709/* continuation for OP_IPUT_OBJECT_JUMBO */ 12710 12711 /* 12712 * Currently: 12713 * r0 holds resolved field 12714 * r9 holds object 12715 */ 12716.LOP_IPUT_OBJECT_JUMBO_resolved: 12717 cmp r0, #0 @ resolution unsuccessful? 12718 beq common_exceptionThrown @ yes, throw exception 12719 @ fall through to OP_IPUT_OBJECT_JUMBO_finish 12720 12721 /* 12722 * Currently: 12723 * r0 holds resolved field 12724 * r9 holds object 12725 */ 12726.LOP_IPUT_OBJECT_JUMBO_finish: 12727 @bl common_squeak0 12728 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12729 FETCH(r1, 3) @ r1<- BBBB 12730 cmp r9, #0 @ check object for null 12731 GET_VREG(r0, r1) @ r0<- fp[BBBB] 12732 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 12733 beq common_errNullObject @ object was null 12734 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12735 GET_INST_OPCODE(ip) @ extract opcode from rINST 12736 @ no-op @ releasing store 12737 str r0, [r9, r3] @ obj.field (32 bits)<- r0 12738 cmp r0, #0 @ stored a null reference? 12739 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 12740 GOTO_OPCODE(ip) @ jump to next instruction 12741 12742/* continuation for OP_IPUT_BOOLEAN_JUMBO */ 12743 12744 /* 12745 * Currently: 12746 * r0 holds resolved field 12747 * r9 holds object 12748 */ 12749.LOP_IPUT_BOOLEAN_JUMBO_resolved: 12750 cmp r0, #0 @ resolution unsuccessful? 12751 beq common_exceptionThrown @ yes, throw exception 12752 @ fall through to OP_IPUT_BOOLEAN_JUMBO_finish 12753 12754 /* 12755 * Currently: 12756 * r0 holds resolved field 12757 * r9 holds object 12758 */ 12759.LOP_IPUT_BOOLEAN_JUMBO_finish: 12760 @bl common_squeak1 12761 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12762 FETCH(r1, 3) @ r1<- BBBB 12763 cmp r9, #0 @ check object for null 12764 GET_VREG(r0, r1) @ r0<- fp[BBBB] 12765 beq common_errNullObject @ object was null 12766 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12767 GET_INST_OPCODE(ip) @ extract opcode from rINST 12768 @ no-op @ releasing store 12769 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 12770 GOTO_OPCODE(ip) @ jump to next instruction 12771 12772/* continuation for OP_IPUT_BYTE_JUMBO */ 12773 12774 /* 12775 * Currently: 12776 * r0 holds resolved field 12777 * r9 holds object 12778 */ 12779.LOP_IPUT_BYTE_JUMBO_resolved: 12780 cmp r0, #0 @ resolution unsuccessful? 12781 beq common_exceptionThrown @ yes, throw exception 12782 @ fall through to OP_IPUT_BYTE_JUMBO_finish 12783 12784 /* 12785 * Currently: 12786 * r0 holds resolved field 12787 * r9 holds object 12788 */ 12789.LOP_IPUT_BYTE_JUMBO_finish: 12790 @bl common_squeak2 12791 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12792 FETCH(r1, 3) @ r1<- BBBB 12793 cmp r9, #0 @ check object for null 12794 GET_VREG(r0, r1) @ r0<- fp[BBBB] 12795 beq common_errNullObject @ object was null 12796 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12797 GET_INST_OPCODE(ip) @ extract opcode from rINST 12798 @ no-op @ releasing store 12799 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 12800 GOTO_OPCODE(ip) @ jump to next instruction 12801 12802/* continuation for OP_IPUT_CHAR_JUMBO */ 12803 12804 /* 12805 * Currently: 12806 * r0 holds resolved field 12807 * r9 holds object 12808 */ 12809.LOP_IPUT_CHAR_JUMBO_resolved: 12810 cmp r0, #0 @ resolution unsuccessful? 12811 beq common_exceptionThrown @ yes, throw exception 12812 @ fall through to OP_IPUT_CHAR_JUMBO_finish 12813 12814 /* 12815 * Currently: 12816 * r0 holds resolved field 12817 * r9 holds object 12818 */ 12819.LOP_IPUT_CHAR_JUMBO_finish: 12820 @bl common_squeak3 12821 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12822 FETCH(r1, 3) @ r1<- BBBB 12823 cmp r9, #0 @ check object for null 12824 GET_VREG(r0, r1) @ r0<- fp[BBBB] 12825 beq common_errNullObject @ object was null 12826 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12827 GET_INST_OPCODE(ip) @ extract opcode from rINST 12828 @ no-op @ releasing store 12829 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 12830 GOTO_OPCODE(ip) @ jump to next instruction 12831 12832/* continuation for OP_IPUT_SHORT_JUMBO */ 12833 12834 /* 12835 * Currently: 12836 * r0 holds resolved field 12837 * r9 holds object 12838 */ 12839.LOP_IPUT_SHORT_JUMBO_resolved: 12840 cmp r0, #0 @ resolution unsuccessful? 12841 beq common_exceptionThrown @ yes, throw exception 12842 @ fall through to OP_IPUT_SHORT_JUMBO_finish 12843 12844 /* 12845 * Currently: 12846 * r0 holds resolved field 12847 * r9 holds object 12848 */ 12849.LOP_IPUT_SHORT_JUMBO_finish: 12850 @bl common_squeak4 12851 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 12852 FETCH(r1, 3) @ r1<- BBBB 12853 cmp r9, #0 @ check object for null 12854 GET_VREG(r0, r1) @ r0<- fp[BBBB] 12855 beq common_errNullObject @ object was null 12856 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 12857 GET_INST_OPCODE(ip) @ extract opcode from rINST 12858 @ no-op @ releasing store 12859 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 12860 GOTO_OPCODE(ip) @ jump to next instruction 12861 12862/* continuation for OP_SGET_JUMBO */ 12863 12864 /* 12865 * Continuation if the field has not yet been resolved. 12866 * r1: AAAAAAAA field ref 12867 */ 12868.LOP_SGET_JUMBO_resolve: 12869 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12870 EXPORT_PC() @ resolve() could throw, so export now 12871 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12872 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12873 cmp r0, #0 @ success? 12874 bne .LOP_SGET_JUMBO_finish @ yes, finish 12875 b common_exceptionThrown @ no, handle exception 12876 12877/* continuation for OP_SGET_WIDE_JUMBO */ 12878 12879 /* 12880 * Continuation if the field has not yet been resolved. 12881 * r1: BBBB field ref 12882 * 12883 * Returns StaticField pointer in r0. 12884 */ 12885.LOP_SGET_WIDE_JUMBO_resolve: 12886 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12887 EXPORT_PC() @ resolve() could throw, so export now 12888 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12889 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12890 cmp r0, #0 @ success? 12891 bne .LOP_SGET_WIDE_JUMBO_finish @ yes, finish 12892 b common_exceptionThrown @ no, handle exception 12893 12894/* continuation for OP_SGET_OBJECT_JUMBO */ 12895 12896 /* 12897 * Continuation if the field has not yet been resolved. 12898 * r1: AAAAAAAA field ref 12899 */ 12900.LOP_SGET_OBJECT_JUMBO_resolve: 12901 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12902 EXPORT_PC() @ resolve() could throw, so export now 12903 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12904 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12905 cmp r0, #0 @ success? 12906 bne .LOP_SGET_OBJECT_JUMBO_finish @ yes, finish 12907 b common_exceptionThrown @ no, handle exception 12908 12909/* continuation for OP_SGET_BOOLEAN_JUMBO */ 12910 12911 /* 12912 * Continuation if the field has not yet been resolved. 12913 * r1: AAAAAAAA field ref 12914 */ 12915.LOP_SGET_BOOLEAN_JUMBO_resolve: 12916 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12917 EXPORT_PC() @ resolve() could throw, so export now 12918 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12919 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12920 cmp r0, #0 @ success? 12921 bne .LOP_SGET_BOOLEAN_JUMBO_finish @ yes, finish 12922 b common_exceptionThrown @ no, handle exception 12923 12924/* continuation for OP_SGET_BYTE_JUMBO */ 12925 12926 /* 12927 * Continuation if the field has not yet been resolved. 12928 * r1: AAAAAAAA field ref 12929 */ 12930.LOP_SGET_BYTE_JUMBO_resolve: 12931 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12932 EXPORT_PC() @ resolve() could throw, so export now 12933 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12934 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12935 cmp r0, #0 @ success? 12936 bne .LOP_SGET_BYTE_JUMBO_finish @ yes, finish 12937 b common_exceptionThrown @ no, handle exception 12938 12939/* continuation for OP_SGET_CHAR_JUMBO */ 12940 12941 /* 12942 * Continuation if the field has not yet been resolved. 12943 * r1: AAAAAAAA field ref 12944 */ 12945.LOP_SGET_CHAR_JUMBO_resolve: 12946 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12947 EXPORT_PC() @ resolve() could throw, so export now 12948 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12949 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12950 cmp r0, #0 @ success? 12951 bne .LOP_SGET_CHAR_JUMBO_finish @ yes, finish 12952 b common_exceptionThrown @ no, handle exception 12953 12954/* continuation for OP_SGET_SHORT_JUMBO */ 12955 12956 /* 12957 * Continuation if the field has not yet been resolved. 12958 * r1: AAAAAAAA field ref 12959 */ 12960.LOP_SGET_SHORT_JUMBO_resolve: 12961 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12962 EXPORT_PC() @ resolve() could throw, so export now 12963 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12964 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12965 cmp r0, #0 @ success? 12966 bne .LOP_SGET_SHORT_JUMBO_finish @ yes, finish 12967 b common_exceptionThrown @ no, handle exception 12968 12969/* continuation for OP_SPUT_JUMBO */ 12970 12971 /* 12972 * Continuation if the field has not yet been resolved. 12973 * r1: AAAAAAAA field ref 12974 */ 12975.LOP_SPUT_JUMBO_resolve: 12976 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12977 EXPORT_PC() @ resolve() could throw, so export now 12978 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12979 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12980 cmp r0, #0 @ success? 12981 bne .LOP_SPUT_JUMBO_finish @ yes, finish 12982 b common_exceptionThrown @ no, handle exception 12983 12984/* continuation for OP_SPUT_WIDE_JUMBO */ 12985 12986 /* 12987 * Continuation if the field has not yet been resolved. 12988 * r1: BBBB field ref 12989 * r9: &fp[AA] 12990 * 12991 * Returns StaticField pointer in r2. 12992 */ 12993.LOP_SPUT_WIDE_JUMBO_resolve: 12994 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 12995 EXPORT_PC() @ resolve() could throw, so export now 12996 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 12997 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 12998 cmp r0, #0 @ success? 12999 mov r2, r0 @ copy to r2 13000 bne .LOP_SPUT_WIDE_JUMBO_finish @ yes, finish 13001 b common_exceptionThrown @ no, handle exception 13002 13003/* continuation for OP_SPUT_OBJECT_JUMBO */ 13004 13005.LOP_SPUT_OBJECT_JUMBO_finish: @ field ptr in r0 13006 FETCH(r2, 3) @ r2<- BBBB 13007 FETCH_ADVANCE_INST(4) @ advance rPC, load rINST 13008 GET_VREG(r1, r2) @ r1<- fp[BBBB] 13009 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 13010 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz 13011 GET_INST_OPCODE(ip) @ extract opcode from rINST 13012 @ no-op @ releasing store 13013 str r1, [r0, #offStaticField_value] @ field<- vBBBB 13014 cmp r1, #0 @ stored a null object? 13015 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 13016 GOTO_OPCODE(ip) @ jump to next instruction 13017 13018/* continuation for OP_SPUT_BOOLEAN_JUMBO */ 13019 13020 /* 13021 * Continuation if the field has not yet been resolved. 13022 * r1: AAAAAAAA field ref 13023 */ 13024.LOP_SPUT_BOOLEAN_JUMBO_resolve: 13025 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 13026 EXPORT_PC() @ resolve() could throw, so export now 13027 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 13028 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 13029 cmp r0, #0 @ success? 13030 bne .LOP_SPUT_BOOLEAN_JUMBO_finish @ yes, finish 13031 b common_exceptionThrown @ no, handle exception 13032 13033/* continuation for OP_SPUT_BYTE_JUMBO */ 13034 13035 /* 13036 * Continuation if the field has not yet been resolved. 13037 * r1: AAAAAAAA field ref 13038 */ 13039.LOP_SPUT_BYTE_JUMBO_resolve: 13040 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 13041 EXPORT_PC() @ resolve() could throw, so export now 13042 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 13043 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 13044 cmp r0, #0 @ success? 13045 bne .LOP_SPUT_BYTE_JUMBO_finish @ yes, finish 13046 b common_exceptionThrown @ no, handle exception 13047 13048/* continuation for OP_SPUT_CHAR_JUMBO */ 13049 13050 /* 13051 * Continuation if the field has not yet been resolved. 13052 * r1: AAAAAAAA field ref 13053 */ 13054.LOP_SPUT_CHAR_JUMBO_resolve: 13055 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 13056 EXPORT_PC() @ resolve() could throw, so export now 13057 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 13058 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 13059 cmp r0, #0 @ success? 13060 bne .LOP_SPUT_CHAR_JUMBO_finish @ yes, finish 13061 b common_exceptionThrown @ no, handle exception 13062 13063/* continuation for OP_SPUT_SHORT_JUMBO */ 13064 13065 /* 13066 * Continuation if the field has not yet been resolved. 13067 * r1: AAAAAAAA field ref 13068 */ 13069.LOP_SPUT_SHORT_JUMBO_resolve: 13070 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 13071 EXPORT_PC() @ resolve() could throw, so export now 13072 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 13073 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 13074 cmp r0, #0 @ success? 13075 bne .LOP_SPUT_SHORT_JUMBO_finish @ yes, finish 13076 b common_exceptionThrown @ no, handle exception 13077 13078/* continuation for OP_INVOKE_VIRTUAL_JUMBO */ 13079 13080 /* 13081 * At this point: 13082 * r0 = resolved base method 13083 */ 13084.LOP_INVOKE_VIRTUAL_JUMBO_continue: 13085 FETCH(r10, 4) @ r10<- CCCC 13086 GET_VREG(r1, r10) @ r1<- "this" ptr 13087 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 13088 cmp r1, #0 @ is "this" null? 13089 beq common_errNullObject @ null "this", throw exception 13090 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 13091 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 13092 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 13093 bl common_invokeMethodJumbo @ continue on 13094 13095/* continuation for OP_INVOKE_SUPER_JUMBO */ 13096 13097 /* 13098 * At this point: 13099 * r0 = resolved base method 13100 * r9 = method->clazz 13101 */ 13102.LOP_INVOKE_SUPER_JUMBO_continue: 13103 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 13104 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 13105 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 13106 EXPORT_PC() @ must export for invoke 13107 cmp r2, r3 @ compare (methodIndex, vtableCount) 13108 bcs .LOP_INVOKE_SUPER_JUMBO_nsm @ method not present in superclass 13109 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 13110 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 13111 bl common_invokeMethodJumbo @ continue on 13112 13113.LOP_INVOKE_SUPER_JUMBO_resolve: 13114 mov r0, r9 @ r0<- method->clazz 13115 mov r2, #METHOD_VIRTUAL @ resolver method type 13116 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 13117 cmp r0, #0 @ got null? 13118 bne .LOP_INVOKE_SUPER_JUMBO_continue @ no, continue 13119 b common_exceptionThrown @ yes, handle exception 13120 13121 /* 13122 * Throw a NoSuchMethodError with the method name as the message. 13123 * r0 = resolved base method 13124 */ 13125.LOP_INVOKE_SUPER_JUMBO_nsm: 13126 ldr r1, [r0, #offMethod_name] @ r1<- method name 13127 b common_errNoSuchMethod 13128 13129/* continuation for OP_INVOKE_DIRECT_JUMBO */ 13130 13131 /* 13132 * On entry: 13133 * r1 = reference (CCCC) 13134 * r10 = "this" register 13135 */ 13136.LOP_INVOKE_DIRECT_JUMBO_resolve: 13137 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 13138 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 13139 mov r2, #METHOD_DIRECT @ resolver method type 13140 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 13141 cmp r0, #0 @ got null? 13142 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 13143 bne .LOP_INVOKE_DIRECT_JUMBO_finish @ no, continue 13144 b common_exceptionThrown @ yes, handle exception 13145 13146 .size dvmAsmSisterStart, .-dvmAsmSisterStart 13147 .global dvmAsmSisterEnd 13148dvmAsmSisterEnd: 13149 13150/* File: armv5te/footer.S */ 13151 13152/* 13153 * =========================================================================== 13154 * Common subroutines and data 13155 * =========================================================================== 13156 */ 13157 13158 13159 13160 .text 13161 .align 2 13162 13163#if defined(WITH_JIT) 13164#if defined(WITH_SELF_VERIFICATION) 13165 .global dvmJitToInterpPunt 13166dvmJitToInterpPunt: 13167 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13168 mov r2,#kSVSPunt @ r2<- interpreter entry point 13169 mov r3, #0 13170 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 13171 b jitSVShadowRunEnd @ doesn't return 13172 13173 .global dvmJitToInterpSingleStep 13174dvmJitToInterpSingleStep: 13175 str lr,[rGLUE,#offGlue_jitResumeNPC] 13176 str r1,[rGLUE,#offGlue_jitResumeDPC] 13177 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 13178 b jitSVShadowRunEnd @ doesn't return 13179 13180 .global dvmJitToInterpNoChainNoProfile 13181dvmJitToInterpNoChainNoProfile: 13182 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13183 mov r0,rPC @ pass our target PC 13184 mov r2,#kSVSNoProfile @ r2<- interpreter entry point 13185 mov r3, #0 @ 0 means !inJitCodeCache 13186 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land 13187 b jitSVShadowRunEnd @ doesn't return 13188 13189 .global dvmJitToInterpTraceSelectNoChain 13190dvmJitToInterpTraceSelectNoChain: 13191 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13192 mov r0,rPC @ pass our target PC 13193 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 13194 mov r3, #0 @ 0 means !inJitCodeCache 13195 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 13196 b jitSVShadowRunEnd @ doesn't return 13197 13198 .global dvmJitToInterpTraceSelect 13199dvmJitToInterpTraceSelect: 13200 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13201 ldr r0,[lr, #-1] @ pass our target PC 13202 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 13203 mov r3, #0 @ 0 means !inJitCodeCache 13204 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 13205 b jitSVShadowRunEnd @ doesn't return 13206 13207 .global dvmJitToInterpBackwardBranch 13208dvmJitToInterpBackwardBranch: 13209 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13210 ldr r0,[lr, #-1] @ pass our target PC 13211 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 13212 mov r3, #0 @ 0 means !inJitCodeCache 13213 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 13214 b jitSVShadowRunEnd @ doesn't return 13215 13216 .global dvmJitToInterpNormal 13217dvmJitToInterpNormal: 13218 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13219 ldr r0,[lr, #-1] @ pass our target PC 13220 mov r2,#kSVSNormal @ r2<- interpreter entry point 13221 mov r3, #0 @ 0 means !inJitCodeCache 13222 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 13223 b jitSVShadowRunEnd @ doesn't return 13224 13225 .global dvmJitToInterpNoChain 13226dvmJitToInterpNoChain: 13227 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13228 mov r0,rPC @ pass our target PC 13229 mov r2,#kSVSNoChain @ r2<- interpreter entry point 13230 mov r3, #0 @ 0 means !inJitCodeCache 13231 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 13232 b jitSVShadowRunEnd @ doesn't return 13233#else 13234/* 13235 * Return from the translation cache to the interpreter when the compiler is 13236 * having issues translating/executing a Dalvik instruction. We have to skip 13237 * the code cache lookup otherwise it is possible to indefinitely bouce 13238 * between the interpreter and the code cache if the instruction that fails 13239 * to be compiled happens to be at a trace start. 13240 */ 13241 .global dvmJitToInterpPunt 13242dvmJitToInterpPunt: 13243 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13244 mov rPC, r0 13245#if defined(WITH_JIT_TUNING) 13246 mov r0,lr 13247 bl dvmBumpPunt; 13248#endif 13249 EXPORT_PC() 13250 mov r0, #0 13251 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land 13252 adrl rIBASE, dvmAsmInstructionStart 13253 FETCH_INST() 13254 GET_INST_OPCODE(ip) 13255 GOTO_OPCODE(ip) 13256 13257/* 13258 * Return to the interpreter to handle a single instruction. 13259 * On entry: 13260 * r0 <= PC 13261 * r1 <= PC of resume instruction 13262 * lr <= resume point in translation 13263 */ 13264 .global dvmJitToInterpSingleStep 13265dvmJitToInterpSingleStep: 13266 str lr,[rGLUE,#offGlue_jitResumeNPC] 13267 str r1,[rGLUE,#offGlue_jitResumeDPC] 13268 mov r1,#kInterpEntryInstr 13269 @ enum is 4 byte in aapcs-EABI 13270 str r1, [rGLUE, #offGlue_entryPoint] 13271 mov rPC,r0 13272 EXPORT_PC() 13273 13274 adrl rIBASE, dvmAsmInstructionStart 13275 mov r2,#kJitSingleStep @ Ask for single step and then revert 13276 str r2,[rGLUE,#offGlue_jitState] 13277 mov r1,#1 @ set changeInterp to bail to debug interp 13278 b common_gotoBail 13279 13280/* 13281 * Return from the translation cache and immediately request 13282 * a translation for the exit target. Commonly used for callees. 13283 */ 13284 .global dvmJitToInterpTraceSelectNoChain 13285dvmJitToInterpTraceSelectNoChain: 13286#if defined(WITH_JIT_TUNING) 13287 bl dvmBumpNoChain 13288#endif 13289 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13290 mov r0,rPC 13291 bl dvmJitGetTraceAddr @ Is there a translation? 13292 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 13293 mov r1, rPC @ arg1 of translation may need this 13294 mov lr, #0 @ in case target is HANDLER_INTERPRET 13295 cmp r0,#0 @ !0 means translation exists 13296 bxne r0 @ continue native execution if so 13297 b 2f @ branch over to use the interpreter 13298 13299/* 13300 * Return from the translation cache and immediately request 13301 * a translation for the exit target. Commonly used following 13302 * invokes. 13303 */ 13304 .global dvmJitToInterpTraceSelect 13305dvmJitToInterpTraceSelect: 13306 ldr rPC,[lr, #-1] @ get our target PC 13307 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13308 add rINST,lr,#-5 @ save start of chain branch 13309 add rINST, #-4 @ .. which is 9 bytes back 13310 mov r0,rPC 13311 bl dvmJitGetTraceAddr @ Is there a translation? 13312 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 13313 cmp r0,#0 13314 beq 2f 13315 mov r1,rINST 13316 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 13317 mov r1, rPC @ arg1 of translation may need this 13318 mov lr, #0 @ in case target is HANDLER_INTERPRET 13319 cmp r0,#0 @ successful chain? 13320 bxne r0 @ continue native execution 13321 b toInterpreter @ didn't chain - resume with interpreter 13322 13323/* No translation, so request one if profiling isn't disabled*/ 133242: 13325 adrl rIBASE, dvmAsmInstructionStart 13326 GET_JIT_PROF_TABLE(r0) 13327 FETCH_INST() 13328 cmp r0, #0 13329 movne r2,#kJitTSelectRequestHot @ ask for trace selection 13330 bne common_selectTrace 13331 GET_INST_OPCODE(ip) 13332 GOTO_OPCODE(ip) 13333 13334/* 13335 * Return from the translation cache to the interpreter. 13336 * The return was done with a BLX from thumb mode, and 13337 * the following 32-bit word contains the target rPC value. 13338 * Note that lr (r14) will have its low-order bit set to denote 13339 * its thumb-mode origin. 13340 * 13341 * We'll need to stash our lr origin away, recover the new 13342 * target and then check to see if there is a translation available 13343 * for our new target. If so, we do a translation chain and 13344 * go back to native execution. Otherwise, it's back to the 13345 * interpreter (after treating this entry as a potential 13346 * trace start). 13347 */ 13348 .global dvmJitToInterpNormal 13349dvmJitToInterpNormal: 13350 ldr rPC,[lr, #-1] @ get our target PC 13351 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13352 add rINST,lr,#-5 @ save start of chain branch 13353 add rINST,#-4 @ .. which is 9 bytes back 13354#if defined(WITH_JIT_TUNING) 13355 bl dvmBumpNormal 13356#endif 13357 mov r0,rPC 13358 bl dvmJitGetTraceAddr @ Is there a translation? 13359 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 13360 cmp r0,#0 13361 beq toInterpreter @ go if not, otherwise do chain 13362 mov r1,rINST 13363 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 13364 mov r1, rPC @ arg1 of translation may need this 13365 mov lr, #0 @ in case target is HANDLER_INTERPRET 13366 cmp r0,#0 @ successful chain? 13367 bxne r0 @ continue native execution 13368 b toInterpreter @ didn't chain - resume with interpreter 13369 13370/* 13371 * Return from the translation cache to the interpreter to do method invocation. 13372 * Check if translation exists for the callee, but don't chain to it. 13373 */ 13374 .global dvmJitToInterpNoChainNoProfile 13375dvmJitToInterpNoChainNoProfile: 13376#if defined(WITH_JIT_TUNING) 13377 bl dvmBumpNoChain 13378#endif 13379 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13380 mov r0,rPC 13381 bl dvmJitGetTraceAddr @ Is there a translation? 13382 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 13383 mov r1, rPC @ arg1 of translation may need this 13384 mov lr, #0 @ in case target is HANDLER_INTERPRET 13385 cmp r0,#0 13386 bxne r0 @ continue native execution if so 13387 EXPORT_PC() 13388 adrl rIBASE, dvmAsmInstructionStart 13389 FETCH_INST() 13390 GET_INST_OPCODE(ip) @ extract opcode from rINST 13391 GOTO_OPCODE(ip) @ jump to next instruction 13392 13393/* 13394 * Return from the translation cache to the interpreter to do method invocation. 13395 * Check if translation exists for the callee, but don't chain to it. 13396 */ 13397 .global dvmJitToInterpNoChain 13398dvmJitToInterpNoChain: 13399#if defined(WITH_JIT_TUNING) 13400 bl dvmBumpNoChain 13401#endif 13402 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13403 mov r0,rPC 13404 bl dvmJitGetTraceAddr @ Is there a translation? 13405 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 13406 mov r1, rPC @ arg1 of translation may need this 13407 mov lr, #0 @ in case target is HANDLER_INTERPRET 13408 cmp r0,#0 13409 bxne r0 @ continue native execution if so 13410#endif 13411 13412/* 13413 * No translation, restore interpreter regs and start interpreting. 13414 * rGLUE & rFP were preserved in the translated code, and rPC has 13415 * already been restored by the time we get here. We'll need to set 13416 * up rIBASE & rINST, and load the address of the JitTable into r0. 13417 */ 13418toInterpreter: 13419 EXPORT_PC() 13420 adrl rIBASE, dvmAsmInstructionStart 13421 FETCH_INST() 13422 GET_JIT_PROF_TABLE(r0) 13423 @ NOTE: intended fallthrough 13424 13425/* 13426 * Common code to update potential trace start counter, and initiate 13427 * a trace-build if appropriate. On entry, rPC should point to the 13428 * next instruction to execute, and rINST should be already loaded with 13429 * the next opcode word, and r0 holds a pointer to the jit profile 13430 * table (pJitProfTable). 13431 */ 13432common_testUpdateProfile: 13433 cmp r0,#0 13434 GET_INST_OPCODE(ip) 13435 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 13436 13437common_updateProfile: 13438 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 13439 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits 13440 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter 13441 GET_INST_OPCODE(ip) 13442 subs r1,r1,#1 @ decrement counter 13443 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it 13444 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 13445 13446/* 13447 * Here, we switch to the debug interpreter to request 13448 * trace selection. First, though, check to see if there 13449 * is already a native translation in place (and, if so, 13450 * jump to it now). 13451 */ 13452 GET_JIT_THRESHOLD(r1) 13453 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 13454 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter 13455 EXPORT_PC() 13456 mov r0,rPC 13457 bl dvmJitGetTraceAddr @ r0<- dvmJitGetTraceAddr(rPC) 13458 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 13459 mov r1, rPC @ arg1 of translation may need this 13460 mov lr, #0 @ in case target is HANDLER_INTERPRET 13461 cmp r0,#0 13462#if !defined(WITH_SELF_VERIFICATION) 13463 bxne r0 @ jump to the translation 13464 mov r2,#kJitTSelectRequest @ ask for trace selection 13465 @ fall-through to common_selectTrace 13466#else 13467 moveq r2,#kJitTSelectRequest @ ask for trace selection 13468 beq common_selectTrace 13469 /* 13470 * At this point, we have a target translation. However, if 13471 * that translation is actually the interpret-only pseudo-translation 13472 * we want to treat it the same as no translation. 13473 */ 13474 mov r10, r0 @ save target 13475 bl dvmCompilerGetInterpretTemplate 13476 cmp r0, r10 @ special case? 13477 bne jitSVShadowRunStart @ set up self verification shadow space 13478 @ Need to clear the inJitCodeCache flag 13479 ldr r10, [rGLUE, #offGlue_self] @ r10 <- glue->self 13480 mov r3, #0 @ 0 means not in the JIT code cache 13481 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land 13482 GET_INST_OPCODE(ip) 13483 GOTO_OPCODE(ip) 13484 /* no return */ 13485#endif 13486 13487/* 13488 * On entry: 13489 * r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot 13490 */ 13491common_selectTrace: 13492 str r2,[rGLUE,#offGlue_jitState] 13493 mov r2,#kInterpEntryInstr @ normal entry reason 13494 str r2,[rGLUE,#offGlue_entryPoint] 13495 mov r1,#1 @ set changeInterp 13496 b common_gotoBail 13497 13498#if defined(WITH_SELF_VERIFICATION) 13499/* 13500 * Save PC and registers to shadow memory for self verification mode 13501 * before jumping to native translation. 13502 * On entry: 13503 * rPC, rFP, rGLUE: the values that they should contain 13504 * r10: the address of the target translation. 13505 */ 13506jitSVShadowRunStart: 13507 mov r0,rPC @ r0<- program counter 13508 mov r1,rFP @ r1<- frame pointer 13509 mov r2,rGLUE @ r2<- InterpState pointer 13510 mov r3,r10 @ r3<- target translation 13511 bl dvmSelfVerificationSaveState @ save registers to shadow space 13512 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 13513 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 13514 bx r10 @ jump to the translation 13515 13516/* 13517 * Restore PC, registers, and interpState to original values 13518 * before jumping back to the interpreter. 13519 */ 13520jitSVShadowRunEnd: 13521 mov r1,rFP @ pass ending fp 13522 bl dvmSelfVerificationRestoreState @ restore pc and fp values 13523 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 13524 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 13525 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 13526 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 13527 cmp r1,#0 @ check for punt condition 13528 beq 1f 13529 mov r2,#kJitSelfVerification @ ask for self verification 13530 str r2,[rGLUE,#offGlue_jitState] 13531 mov r2,#kInterpEntryInstr @ normal entry reason 13532 str r2,[rGLUE,#offGlue_entryPoint] 13533 mov r1,#1 @ set changeInterp 13534 b common_gotoBail 13535 135361: @ exit to interpreter without check 13537 EXPORT_PC() 13538 adrl rIBASE, dvmAsmInstructionStart 13539 FETCH_INST() 13540 GET_INST_OPCODE(ip) 13541 GOTO_OPCODE(ip) 13542#endif 13543 13544#endif 13545 13546/* 13547 * Common code when a backward branch is taken. 13548 * 13549 * TODO: we could avoid a branch by just setting r0 and falling through 13550 * into the common_periodicChecks code, and having a test on r0 at the 13551 * end determine if we should return to the caller or update & branch to 13552 * the next instr. 13553 * 13554 * On entry: 13555 * r9 is PC adjustment *in bytes* 13556 */ 13557common_backwardBranch: 13558 mov r0, #kInterpEntryInstr 13559 bl common_periodicChecks 13560#if defined(WITH_JIT) 13561 GET_JIT_PROF_TABLE(r0) 13562 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 13563 cmp r0,#0 13564 bne common_updateProfile 13565 GET_INST_OPCODE(ip) 13566 GOTO_OPCODE(ip) 13567#else 13568 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 13569 GET_INST_OPCODE(ip) @ extract opcode from rINST 13570 GOTO_OPCODE(ip) @ jump to next instruction 13571#endif 13572 13573 13574/* 13575 * Need to see if the thread needs to be suspended or debugger/profiler 13576 * activity has begun. If so, we suspend the thread or side-exit to 13577 * the debug interpreter as appropriate. 13578 * 13579 * The common case is no activity on any of these, so we want to figure 13580 * that out quickly. If something is up, we can then sort out what. 13581 * 13582 * We want to be fast if the VM was built without debugger or profiler 13583 * support, but we also need to recognize that the system is usually 13584 * shipped with both of these enabled. 13585 * 13586 * TODO: reduce this so we're just checking a single location. 13587 * 13588 * On entry: 13589 * r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling) 13590 * r9 is trampoline PC adjustment *in bytes* 13591 */ 13592common_periodicChecks: 13593 ldr r1, [rGLUE, #offGlue_pInterpBreak] @ r3<- &interpBreak 13594 /* speculatively load address of thread-specific suspend count */ 13595 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 13596 ldr r1, [r1] @ r1<- interpBreak 13597 /* speculatively load thread-specific suspend count */ 13598 ldr ip, [r3] @ ip<- suspendCount (int) 13599 cmp r1, #0 @ anything unusual? 13600 bxeq lr @ return if not 13601 /* 13602 * One or more interesting events have happened. Figure out what. 13603 * 13604 * r0 still holds the reentry type. 13605 */ 13606 cmp ip, #0 @ want suspend? 13607 beq 3f @ no, must be something else 13608 13609 stmfd sp!, {r0, lr} @ preserve r0 and lr 13610#if defined(WITH_JIT) 13611 /* 13612 * Refresh the Jit's cached copy of profile table pointer. This pointer 13613 * doubles as the Jit's on/off switch. 13614 */ 13615 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable 13616 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 13617 ldr r3, [r3] @ r3 <- pJitProfTable 13618 EXPORT_PC() @ need for precise GC 13619 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch 13620#else 13621 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 13622 EXPORT_PC() @ need for precise GC 13623#endif 13624 bl dvmCheckSuspendPending @ do full check, suspend if necessary 13625 ldmfd sp!, {r0, lr} @ restore r0 and lr 13626 13627 /* 13628 * Reload the interpBreak flags - they may have changed while we 13629 * were suspended. 13630 */ 13631 ldr r1, [rGLUE, #offGlue_pInterpBreak] @ r1<- &interpBreak 13632 ldr r1, [r1] @ r1<- interpBreak 136333: 13634 /* 13635 * TODO: this code is too fragile. Need a general mechanism 13636 * to identify what actions to take by submode. Some profiling modes 13637 * (instruction count) need to single-step, while method tracing 13638 * may not. Debugging with breakpoints can run unfettered, but 13639 * source-level single-stepping requires Dalvik singlestepping. 13640 * GC may require a one-shot action and then full-speed resumption. 13641 */ 13642 ands r1, #(kSubModeDebuggerActive | kSubModeEmulatorTrace | kSubModeInstCounting) 13643 bxeq lr @ nothing to do, return 13644 13645 @ debugger/profiler enabled, bail out; glue->entryPoint was set above 13646 str r0, [rGLUE, #offGlue_entryPoint] @ store r0, need for debug/prof 13647 add rPC, rPC, r9 @ update rPC 13648 mov r1, #1 @ "want switch" = true 13649 b common_gotoBail @ side exit 13650 13651 13652/* 13653 * The equivalent of "goto bail", this calls through the "bail handler". 13654 * 13655 * State registers will be saved to the "glue" area before bailing. 13656 * 13657 * On entry: 13658 * r1 is "bool changeInterp", indicating if we want to switch to the 13659 * other interpreter or just bail all the way out 13660 */ 13661common_gotoBail: 13662 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 13663 mov r0, rGLUE @ r0<- glue ptr 13664 b dvmMterpStdBail @ call(glue, changeInterp) 13665 13666 @add r1, r1, #1 @ using (boolean+1) 13667 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 13668 @bl _longjmp @ does not return 13669 @bl common_abort 13670 13671 13672/* 13673 * Common code for jumbo method invocation. 13674 * NOTE: this adjusts rPC to account for the difference in instruction width. 13675 * As a result, the savedPc in the stack frame will not be wholly accurate. So 13676 * long as that is only used for source file line number calculations, we're 13677 * okay. 13678 * 13679 * On entry: 13680 * r0 is "Method* methodToCall", the method we're trying to call 13681 */ 13682common_invokeMethodJumbo: 13683.LinvokeNewJumbo: 13684 @ prepare to copy args to "outs" area of current frame 13685 add rPC, rPC, #4 @ adjust pc to make return consistent 13686 FETCH(r2, 1) @ r2<- BBBB (arg count) 13687 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 13688 cmp r2, #0 @ no args? 13689 beq .LinvokeArgsDone @ if no args, skip the rest 13690 FETCH(r1, 2) @ r1<- CCCC 13691 b .LinvokeRangeArgs @ handle args like invoke range 13692 13693/* 13694 * Common code for method invocation with range. 13695 * 13696 * On entry: 13697 * r0 is "Method* methodToCall", the method we're trying to call 13698 */ 13699common_invokeMethodRange: 13700.LinvokeNewRange: 13701 @ prepare to copy args to "outs" area of current frame 13702 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 13703 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 13704 beq .LinvokeArgsDone @ if no args, skip the rest 13705 FETCH(r1, 2) @ r1<- CCCC 13706 13707.LinvokeRangeArgs: 13708 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 13709 @ (very few methods have > 10 args; could unroll for common cases) 13710 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 13711 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 137121: ldr r1, [r3], #4 @ val = *fp++ 13713 subs r2, r2, #1 @ count-- 13714 str r1, [r10], #4 @ *outs++ = val 13715 bne 1b @ ...while count != 0 13716 b .LinvokeArgsDone 13717 13718/* 13719 * Common code for method invocation without range. 13720 * 13721 * On entry: 13722 * r0 is "Method* methodToCall", the method we're trying to call 13723 */ 13724common_invokeMethodNoRange: 13725.LinvokeNewNoRange: 13726 @ prepare to copy args to "outs" area of current frame 13727 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 13728 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 13729 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 13730 beq .LinvokeArgsDone 13731 13732 @ r0=methodToCall, r1=GFED, r2=count, r10=outs 13733.LinvokeNonRange: 13734 rsb r2, r2, #5 @ r2<- 5-r2 13735 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 13736 bl common_abort @ (skipped due to ARM prefetch) 137375: and ip, rINST, #0x0f00 @ isolate A 13738 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 13739 mov r0, r0 @ nop 13740 str r2, [r10, #-4]! @ *--outs = vA 137414: and ip, r1, #0xf000 @ isolate G 13742 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 13743 mov r0, r0 @ nop 13744 str r2, [r10, #-4]! @ *--outs = vG 137453: and ip, r1, #0x0f00 @ isolate F 13746 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 13747 mov r0, r0 @ nop 13748 str r2, [r10, #-4]! @ *--outs = vF 137492: and ip, r1, #0x00f0 @ isolate E 13750 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 13751 mov r0, r0 @ nop 13752 str r2, [r10, #-4]! @ *--outs = vE 137531: and ip, r1, #0x000f @ isolate D 13754 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 13755 mov r0, r0 @ nop 13756 str r2, [r10, #-4]! @ *--outs = vD 137570: @ fall through to .LinvokeArgsDone 13758 13759.LinvokeArgsDone: @ r0=methodToCall 13760 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 13761 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 13762 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 13763 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 13764 @ find space for the new stack frame, check for overflow 13765 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 13766 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 13767 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 13768@ bl common_dumpRegs 13769 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 13770 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 13771 cmp r3, r9 @ bottom < interpStackEnd? 13772 ldr lr, [rGLUE, #offGlue_pInterpBreak] 13773 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 13774 blo .LstackOverflow @ yes, this frame will overflow stack 13775 13776 @ set up newSaveArea 13777 ldr lr, [lr] @ lr<- active submodes 13778#ifdef EASY_GDB 13779 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 13780 str ip, [r10, #offStackSaveArea_prevSave] 13781#endif 13782 str rFP, [r10, #offStackSaveArea_prevFrame] 13783 str rPC, [r10, #offStackSaveArea_savedPc] 13784#if defined(WITH_JIT) 13785 mov r9, #0 13786 str r9, [r10, #offStackSaveArea_returnAddr] 13787#endif 13788 ands lr, #kSubModeMethodTrace @ method tracing? 13789 beq 1f @ skip if not 13790 stmfd sp!, {r0-r3} @ preserve r0-r3 13791 mov r1, r6 13792 @ r0=methodToCall, r1=rGlue 13793 bl dvmFastMethodTraceEnter 13794 ldmfd sp!, {r0-r3} @ restore r0-r3 137951: 13796 str r0, [r10, #offStackSaveArea_method] 13797 tst r3, #ACC_NATIVE 13798 bne .LinvokeNative 13799 13800 /* 13801 stmfd sp!, {r0-r3} 13802 bl common_printNewline 13803 mov r0, rFP 13804 mov r1, #0 13805 bl dvmDumpFp 13806 ldmfd sp!, {r0-r3} 13807 stmfd sp!, {r0-r3} 13808 mov r0, r1 13809 mov r1, r10 13810 bl dvmDumpFp 13811 bl common_printNewline 13812 ldmfd sp!, {r0-r3} 13813 */ 13814 13815 ldrh r9, [r2] @ r9 <- load INST from new PC 13816 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 13817 mov rPC, r2 @ publish new rPC 13818 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 13819 13820 @ Update "glue" values for the new method 13821 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 13822 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 13823 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 13824#if defined(WITH_JIT) 13825 GET_JIT_PROF_TABLE(r0) 13826 mov rFP, r1 @ fp = newFp 13827 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 13828 mov rINST, r9 @ publish new rINST 13829 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 13830 cmp r0,#0 13831 bne common_updateProfile 13832 GOTO_OPCODE(ip) @ jump to next instruction 13833#else 13834 mov rFP, r1 @ fp = newFp 13835 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 13836 mov rINST, r9 @ publish new rINST 13837 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 13838 GOTO_OPCODE(ip) @ jump to next instruction 13839#endif 13840 13841.LinvokeNative: 13842 @ Prep for the native call 13843 @ r0=methodToCall, r1=newFp, r10=newSaveArea 13844 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 13845 ldr lr, [rGLUE, #offGlue_pInterpBreak] 13846 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 13847 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 13848 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 13849 ldr lr, [lr] @ lr<- active submodes 13850 mov r9, r3 @ r9<- glue->self (preserve) 13851 13852 mov r2, r0 @ r2<- methodToCall 13853 mov r0, r1 @ r0<- newFp (points to args) 13854 add r1, rGLUE, #offGlue_retval @ r1<- &retval 13855 13856#ifdef ASSIST_DEBUGGER 13857 /* insert fake function header to help gdb find the stack frame */ 13858 b .Lskip 13859 .type dalvik_mterp, %function 13860dalvik_mterp: 13861 .fnstart 13862 MTERP_ENTRY1 13863 MTERP_ENTRY2 13864.Lskip: 13865#endif 13866 13867 ands lr, #kSubModeMethodTrace @ method tracing? 13868 beq 110f @ hop if not 13869 @ r2=JNIMethod, r6=rGLUE 13870 stmfd sp!, {r2,r6} 13871 13872 mov lr, pc @ set return addr 13873 ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 13874 13875 @ r0=JNIMethod, r1=rGLUE 13876 ldmfd sp!, {r0-r1} 13877 bl dvmFastNativeMethodTraceExit 13878 b 220f 13879110: 13880 mov lr, pc @ set return addr 13881 ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 13882220: 13883#if defined(WITH_JIT) 13884 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status 13885#endif 13886 13887 @ native return; r9=self, r10=newSaveArea 13888 @ equivalent to dvmPopJniLocals 13889 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 13890 ldr r1, [r9, #offThread_exception] @ check for exception 13891#if defined(WITH_JIT) 13892 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable 13893#endif 13894 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 13895 cmp r1, #0 @ null? 13896 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 13897#if defined(WITH_JIT) 13898 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch 13899#endif 13900 bne common_exceptionThrown @ no, handle exception 13901 13902 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 13903 GET_INST_OPCODE(ip) @ extract opcode from rINST 13904 GOTO_OPCODE(ip) @ jump to next instruction 13905 13906.LstackOverflow: @ r0=methodToCall 13907 mov r1, r0 @ r1<- methodToCall 13908 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 13909 bl dvmHandleStackOverflow 13910 b common_exceptionThrown 13911#ifdef ASSIST_DEBUGGER 13912 .fnend 13913#endif 13914 13915 13916 /* 13917 * Common code for method invocation, calling through "glue code". 13918 * 13919 * TODO: now that we have range and non-range invoke handlers, this 13920 * needs to be split into two. Maybe just create entry points 13921 * that set r9 and jump here? 13922 * 13923 * On entry: 13924 * r0 is "Method* methodToCall", the method we're trying to call 13925 * r9 is "bool methodCallRange", indicating if this is a /range variant 13926 */ 13927 .if 0 13928.LinvokeOld: 13929 sub sp, sp, #8 @ space for args + pad 13930 FETCH(ip, 2) @ ip<- FEDC or CCCC 13931 mov r2, r0 @ A2<- methodToCall 13932 mov r0, rGLUE @ A0<- glue 13933 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 13934 mov r1, r9 @ A1<- methodCallRange 13935 mov r3, rINST, lsr #8 @ A3<- AA 13936 str ip, [sp, #0] @ A4<- ip 13937 bl dvmMterp_invokeMethod @ call the C invokeMethod 13938 add sp, sp, #8 @ remove arg area 13939 b common_resumeAfterGlueCall @ continue to next instruction 13940 .endif 13941 13942 13943 13944/* 13945 * Common code for handling a return instruction. 13946 * 13947 * This does not return. 13948 */ 13949common_returnFromMethod: 13950.LreturnNew: 13951 mov r0, #kInterpEntryReturn 13952 mov r9, #0 13953 bl common_periodicChecks 13954 13955 ldr lr, [rGLUE, #offGlue_pInterpBreak] 13956 SAVEAREA_FROM_FP(r0, rFP) 13957 ldr lr, [lr] @ lr<- active submodes 13958 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 13959 ands lr, #kSubModeMethodTrace @ method tracing? 13960 beq 333f 13961 stmfd sp!, {r0-r3} @ preserve r0-r3 13962 mov r0, r6 13963 @ r0=rGlue 13964 bl dvmFastJavaMethodTraceExit 13965 ldmfd sp!, {r0-r3} @ restore r0-r3 13966333: 13967 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 13968 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 13969 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 13970 @ r2<- method we're returning to 13971 cmp r2, #0 @ is this a break frame? 13972#if defined(WORKAROUND_CORTEX_A9_745320) 13973 /* Don't use conditional loads if the HW defect exists */ 13974 beq 101f 13975 ldr r10, [r2, #offMethod_clazz] @ r10<- method->clazz 13976101: 13977#else 13978 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 13979#endif 13980 mov r1, #0 @ "want switch" = false 13981 beq common_gotoBail @ break frame, bail out completely 13982 13983 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 13984 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 13985 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 13986 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 13987#if defined(WITH_JIT) 13988 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr 13989 mov rPC, r9 @ publish new rPC 13990 str r1, [rGLUE, #offGlue_methodClassDex] 13991 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land 13992 cmp r10, #0 @ caller is compiled code 13993 blxne r10 13994 GET_INST_OPCODE(ip) @ extract opcode from rINST 13995 GOTO_OPCODE(ip) @ jump to next instruction 13996#else 13997 GET_INST_OPCODE(ip) @ extract opcode from rINST 13998 mov rPC, r9 @ publish new rPC 13999 str r1, [rGLUE, #offGlue_methodClassDex] 14000 GOTO_OPCODE(ip) @ jump to next instruction 14001#endif 14002 14003 /* 14004 * Return handling, calls through "glue code". 14005 */ 14006 .if 0 14007.LreturnOld: 14008 SAVE_PC_FP_TO_GLUE() @ export state 14009 mov r0, rGLUE @ arg to function 14010 bl dvmMterp_returnFromMethod 14011 b common_resumeAfterGlueCall 14012 .endif 14013 14014 14015/* 14016 * Somebody has thrown an exception. Handle it. 14017 * 14018 * If the exception processing code returns to us (instead of falling 14019 * out of the interpreter), continue with whatever the next instruction 14020 * now happens to be. 14021 * 14022 * This does not return. 14023 */ 14024 .global dvmMterpCommonExceptionThrown 14025dvmMterpCommonExceptionThrown: 14026common_exceptionThrown: 14027.LexceptionNew: 14028 mov r0, #kInterpEntryThrow 14029 mov r9, #0 14030 bl common_periodicChecks 14031 14032 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 14033 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 14034 mov r1, r10 @ r1<- self 14035 mov r0, r9 @ r0<- exception 14036 bl dvmAddTrackedAlloc @ don't let the exception be GCed 14037 mov r3, #0 @ r3<- NULL 14038 str r3, [r10, #offThread_exception] @ self->exception = NULL 14039 14040 /* set up args and a local for "&fp" */ 14041 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 14042 str rFP, [sp, #-4]! @ *--sp = fp 14043 mov ip, sp @ ip<- &fp 14044 mov r3, #0 @ r3<- false 14045 str ip, [sp, #-4]! @ *--sp = &fp 14046 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 14047 mov r0, r10 @ r0<- self 14048 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 14049 mov r2, r9 @ r2<- exception 14050 sub r1, rPC, r1 @ r1<- pc - method->insns 14051 mov r1, r1, asr #1 @ r1<- offset in code units 14052 14053 /* call, r0 gets catchRelPc (a code-unit offset) */ 14054 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 14055 14056 /* fix earlier stack overflow if necessary; may trash rFP */ 14057 ldrb r1, [r10, #offThread_stackOverflowed] 14058 cmp r1, #0 @ did we overflow earlier? 14059 beq 1f @ no, skip ahead 14060 mov rFP, r0 @ save relPc result in rFP 14061 mov r0, r10 @ r0<- self 14062 mov r1, r9 @ r1<- exception 14063 bl dvmCleanupStackOverflow @ call(self) 14064 mov r0, rFP @ restore result 140651: 14066 14067 /* update frame pointer and check result from dvmFindCatchBlock */ 14068 ldr rFP, [sp, #4] @ retrieve the updated rFP 14069 cmp r0, #0 @ is catchRelPc < 0? 14070 add sp, sp, #8 @ restore stack 14071 bmi .LnotCaughtLocally 14072 14073 /* adjust locals to match self->curFrame and updated PC */ 14074 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 14075 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 14076 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 14077 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 14078 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 14079 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 14080 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 14081 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 14082 14083 /* release the tracked alloc on the exception */ 14084 mov r0, r9 @ r0<- exception 14085 mov r1, r10 @ r1<- self 14086 bl dvmReleaseTrackedAlloc @ release the exception 14087 14088 /* restore the exception if the handler wants it */ 14089 FETCH_INST() @ load rINST from rPC 14090 GET_INST_OPCODE(ip) @ extract opcode from rINST 14091 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 14092 streq r9, [r10, #offThread_exception] @ yes, restore the exception 14093 GOTO_OPCODE(ip) @ jump to next instruction 14094 14095.LnotCaughtLocally: @ r9=exception, r10=self 14096 /* fix stack overflow if necessary */ 14097 ldrb r1, [r10, #offThread_stackOverflowed] 14098 cmp r1, #0 @ did we overflow earlier? 14099 movne r0, r10 @ if yes: r0<- self 14100 movne r1, r9 @ if yes: r1<- exception 14101 blne dvmCleanupStackOverflow @ if yes: call(self) 14102 14103 @ may want to show "not caught locally" debug messages here 14104#if DVM_SHOW_EXCEPTION >= 2 14105 /* call __android_log_print(prio, tag, format, ...) */ 14106 /* "Exception %s from %s:%d not caught locally" */ 14107 @ dvmLineNumFromPC(method, pc - method->insns) 14108 ldr r0, [rGLUE, #offGlue_method] 14109 ldr r1, [r0, #offMethod_insns] 14110 sub r1, rPC, r1 14111 asr r1, r1, #1 14112 bl dvmLineNumFromPC 14113 str r0, [sp, #-4]! 14114 @ dvmGetMethodSourceFile(method) 14115 ldr r0, [rGLUE, #offGlue_method] 14116 bl dvmGetMethodSourceFile 14117 str r0, [sp, #-4]! 14118 @ exception->clazz->descriptor 14119 ldr r3, [r9, #offObject_clazz] 14120 ldr r3, [r3, #offClassObject_descriptor] 14121 @ 14122 ldr r2, strExceptionNotCaughtLocally 14123 ldr r1, strLogTag 14124 mov r0, #3 @ LOG_DEBUG 14125 bl __android_log_print 14126#endif 14127 str r9, [r10, #offThread_exception] @ restore exception 14128 mov r0, r9 @ r0<- exception 14129 mov r1, r10 @ r1<- self 14130 bl dvmReleaseTrackedAlloc @ release the exception 14131 mov r1, #0 @ "want switch" = false 14132 b common_gotoBail @ bail out 14133 14134 14135 /* 14136 * Exception handling, calls through "glue code". 14137 */ 14138 .if 0 14139.LexceptionOld: 14140 SAVE_PC_FP_TO_GLUE() @ export state 14141 mov r0, rGLUE @ arg to function 14142 bl dvmMterp_exceptionThrown 14143 b common_resumeAfterGlueCall 14144 .endif 14145 14146 14147/* 14148 * After returning from a "glued" function, pull out the updated 14149 * values and start executing at the next instruction. 14150 */ 14151common_resumeAfterGlueCall: 14152 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 14153 FETCH_INST() @ load rINST from rPC 14154 GET_INST_OPCODE(ip) @ extract opcode from rINST 14155 GOTO_OPCODE(ip) @ jump to next instruction 14156 14157/* 14158 * Invalid array index. Note that our calling convention is strange; we use r1 14159 * and r3 because those just happen to be the registers all our callers are 14160 * using. We shuffle them here before calling the C function. 14161 * r1: index 14162 * r3: size 14163 */ 14164common_errArrayIndex: 14165 EXPORT_PC() 14166 mov r0, r1 14167 mov r1, r3 14168 bl dvmThrowAIOOBE 14169 b common_exceptionThrown 14170 14171/* 14172 * Integer divide or mod by zero. 14173 */ 14174common_errDivideByZero: 14175 EXPORT_PC() 14176 ldr r0, strArithmeticException 14177 ldr r1, strDivideByZero 14178 bl dvmThrowException 14179 b common_exceptionThrown 14180 14181/* 14182 * Attempt to allocate an array with a negative size. 14183 */ 14184common_errNegativeArraySize: 14185 EXPORT_PC() 14186 ldr r0, strNegativeArraySizeException 14187 mov r1, #0 14188 bl dvmThrowException 14189 b common_exceptionThrown 14190 14191/* 14192 * Invocation of a non-existent method. 14193 */ 14194common_errNoSuchMethod: 14195 EXPORT_PC() 14196 ldr r0, strNoSuchMethodError 14197 mov r1, #0 14198 bl dvmThrowException 14199 b common_exceptionThrown 14200 14201/* 14202 * We encountered a null object when we weren't expecting one. We 14203 * export the PC, throw a NullPointerException, and goto the exception 14204 * processing code. 14205 */ 14206common_errNullObject: 14207 EXPORT_PC() 14208 ldr r0, strNullPointerException 14209 mov r1, #0 14210 bl dvmThrowException 14211 b common_exceptionThrown 14212 14213/* 14214 * For debugging, cause an immediate fault. The source address will 14215 * be in lr (use a bl instruction to jump here). 14216 */ 14217common_abort: 14218 ldr pc, .LdeadFood 14219.LdeadFood: 14220 .word 0xdeadf00d 14221 14222/* 14223 * Spit out a "we were here", preserving all registers. (The attempt 14224 * to save ip won't work, but we need to save an even number of 14225 * registers for EABI 64-bit stack alignment.) 14226 */ 14227 .macro SQUEAK num 14228common_squeak\num: 14229 stmfd sp!, {r0, r1, r2, r3, ip, lr} 14230 ldr r0, strSqueak 14231 mov r1, #\num 14232 bl printf 14233 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 14234 bx lr 14235 .endm 14236 14237 SQUEAK 0 14238 SQUEAK 1 14239 SQUEAK 2 14240 SQUEAK 3 14241 SQUEAK 4 14242 SQUEAK 5 14243 14244/* 14245 * Spit out the number in r0, preserving registers. 14246 */ 14247common_printNum: 14248 stmfd sp!, {r0, r1, r2, r3, ip, lr} 14249 mov r1, r0 14250 ldr r0, strSqueak 14251 bl printf 14252 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 14253 bx lr 14254 14255/* 14256 * Print a newline, preserving registers. 14257 */ 14258common_printNewline: 14259 stmfd sp!, {r0, r1, r2, r3, ip, lr} 14260 ldr r0, strNewline 14261 bl printf 14262 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 14263 bx lr 14264 14265 /* 14266 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 14267 */ 14268common_printHex: 14269 stmfd sp!, {r0, r1, r2, r3, ip, lr} 14270 mov r1, r0 14271 ldr r0, strPrintHex 14272 bl printf 14273 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 14274 bx lr 14275 14276/* 14277 * Print the 64-bit quantity in r0-r1, preserving registers. 14278 */ 14279common_printLong: 14280 stmfd sp!, {r0, r1, r2, r3, ip, lr} 14281 mov r3, r1 14282 mov r2, r0 14283 ldr r0, strPrintLong 14284 bl printf 14285 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 14286 bx lr 14287 14288/* 14289 * Print full method info. Pass the Method* in r0. Preserves regs. 14290 */ 14291common_printMethod: 14292 stmfd sp!, {r0, r1, r2, r3, ip, lr} 14293 bl dvmMterpPrintMethod 14294 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 14295 bx lr 14296 14297/* 14298 * Call a C helper function that dumps regs and possibly some 14299 * additional info. Requires the C function to be compiled in. 14300 */ 14301 .if 0 14302common_dumpRegs: 14303 stmfd sp!, {r0, r1, r2, r3, ip, lr} 14304 bl dvmMterpDumpArmRegs 14305 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 14306 bx lr 14307 .endif 14308 14309#if 0 14310/* 14311 * Experiment on VFP mode. 14312 * 14313 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 14314 * 14315 * Updates the bits specified by "mask", setting them to the values in "val". 14316 */ 14317setFPSCR: 14318 and r0, r0, r1 @ make sure no stray bits are set 14319 fmrx r2, fpscr @ get VFP reg 14320 mvn r1, r1 @ bit-invert mask 14321 and r2, r2, r1 @ clear masked bits 14322 orr r2, r2, r0 @ set specified bits 14323 fmxr fpscr, r2 @ set VFP reg 14324 mov r0, r2 @ return new value 14325 bx lr 14326 14327 .align 2 14328 .global dvmConfigureFP 14329 .type dvmConfigureFP, %function 14330dvmConfigureFP: 14331 stmfd sp!, {ip, lr} 14332 /* 0x03000000 sets DN/FZ */ 14333 /* 0x00009f00 clears the six exception enable flags */ 14334 bl common_squeak0 14335 mov r0, #0x03000000 @ r0<- 0x03000000 14336 add r1, r0, #0x9f00 @ r1<- 0x03009f00 14337 bl setFPSCR 14338 ldmfd sp!, {ip, pc} 14339#endif 14340 14341 14342/* 14343 * String references, must be close to the code that uses them. 14344 */ 14345 .align 2 14346strArithmeticException: 14347 .word .LstrArithmeticException 14348strDivideByZero: 14349 .word .LstrDivideByZero 14350strNegativeArraySizeException: 14351 .word .LstrNegativeArraySizeException 14352strNoSuchMethodError: 14353 .word .LstrNoSuchMethodError 14354strNullPointerException: 14355 .word .LstrNullPointerException 14356 14357strLogTag: 14358 .word .LstrLogTag 14359strExceptionNotCaughtLocally: 14360 .word .LstrExceptionNotCaughtLocally 14361 14362strNewline: 14363 .word .LstrNewline 14364strSqueak: 14365 .word .LstrSqueak 14366strPrintHex: 14367 .word .LstrPrintHex 14368strPrintLong: 14369 .word .LstrPrintLong 14370 14371/* 14372 * Zero-terminated ASCII string data. 14373 * 14374 * On ARM we have two choices: do like gcc does, and LDR from a .word 14375 * with the address, or use an ADR pseudo-op to get the address 14376 * directly. ADR saves 4 bytes and an indirection, but it's using a 14377 * PC-relative addressing mode and hence has a limited range, which 14378 * makes it not work well with mergeable string sections. 14379 */ 14380 .section .rodata.str1.4,"aMS",%progbits,1 14381 14382.LstrBadEntryPoint: 14383 .asciz "Bad entry point %d\n" 14384.LstrArithmeticException: 14385 .asciz "Ljava/lang/ArithmeticException;" 14386.LstrDivideByZero: 14387 .asciz "divide by zero" 14388.LstrFilledNewArrayNotImpl: 14389 .asciz "filled-new-array only implemented for objects and 'int'" 14390.LstrInternalError: 14391 .asciz "Ljava/lang/InternalError;" 14392.LstrInstantiationError: 14393 .asciz "Ljava/lang/InstantiationError;" 14394.LstrNegativeArraySizeException: 14395 .asciz "Ljava/lang/NegativeArraySizeException;" 14396.LstrNoSuchMethodError: 14397 .asciz "Ljava/lang/NoSuchMethodError;" 14398.LstrNullPointerException: 14399 .asciz "Ljava/lang/NullPointerException;" 14400 14401.LstrLogTag: 14402 .asciz "mterp" 14403.LstrExceptionNotCaughtLocally: 14404 .asciz "Exception %s from %s:%d not caught locally\n" 14405 14406.LstrNewline: 14407 .asciz "\n" 14408.LstrSqueak: 14409 .asciz "<%d>" 14410.LstrPrintHex: 14411 .asciz "<0x%x>" 14412.LstrPrintLong: 14413 .asciz "<%lld>" 14414 14415