InterpAsm-armv5te-vfp.S revision 90f15431b24a4004fab2db70f273155fcd1c42a4
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, MONITOR_TRACKING 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#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ 857 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 858 ldr r1, [r0, #offThread_exception] @ check for exception 859 cmp r1, #0 860 bne common_exceptionThrown @ exception raised, bail out 861#endif 862 GET_INST_OPCODE(ip) @ extract opcode from rINST 863 GOTO_OPCODE(ip) @ jump to next instruction 864 865/* ------------------------------ */ 866 .balign 64 867.L_OP_MONITOR_EXIT: /* 0x1e */ 868/* File: armv5te/OP_MONITOR_EXIT.S */ 869 /* 870 * Unlock an object. 871 * 872 * Exceptions that occur when unlocking a monitor need to appear as 873 * if they happened at the following instruction. See the Dalvik 874 * instruction spec. 875 */ 876 /* monitor-exit vAA */ 877 mov r2, rINST, lsr #8 @ r2<- AA 878 EXPORT_PC() @ before fetch: export the PC 879 GET_VREG(r1, r2) @ r1<- vAA (object) 880 cmp r1, #0 @ null object? 881 beq 1f @ yes 882 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 883 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 884 cmp r0, #0 @ failed? 885 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 886 beq common_exceptionThrown @ yes, exception is pending 887 GET_INST_OPCODE(ip) @ extract opcode from rINST 888 GOTO_OPCODE(ip) @ jump to next instruction 8891: 890 FETCH_ADVANCE_INST(1) @ advance before throw 891 b common_errNullObject 892 893/* ------------------------------ */ 894 .balign 64 895.L_OP_CHECK_CAST: /* 0x1f */ 896/* File: armv5te/OP_CHECK_CAST.S */ 897 /* 898 * Check to see if a cast from one class to another is allowed. 899 */ 900 /* check-cast vAA, class@BBBB */ 901 mov r3, rINST, lsr #8 @ r3<- AA 902 FETCH(r2, 1) @ r2<- BBBB 903 GET_VREG(r9, r3) @ r9<- object 904 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 905 cmp r9, #0 @ is object null? 906 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 907 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 908 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 909 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 910 cmp r1, #0 @ have we resolved this before? 911 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 912.LOP_CHECK_CAST_resolved: 913 cmp r0, r1 @ same class (trivial success)? 914 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 915.LOP_CHECK_CAST_okay: 916 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 917 GET_INST_OPCODE(ip) @ extract opcode from rINST 918 GOTO_OPCODE(ip) @ jump to next instruction 919 920/* ------------------------------ */ 921 .balign 64 922.L_OP_INSTANCE_OF: /* 0x20 */ 923/* File: armv5te/OP_INSTANCE_OF.S */ 924 /* 925 * Check to see if an object reference is an instance of a class. 926 * 927 * Most common situation is a non-null object, being compared against 928 * an already-resolved class. 929 */ 930 /* instance-of vA, vB, class@CCCC */ 931 mov r3, rINST, lsr #12 @ r3<- B 932 mov r9, rINST, lsr #8 @ r9<- A+ 933 GET_VREG(r0, r3) @ r0<- vB (object) 934 and r9, r9, #15 @ r9<- A 935 cmp r0, #0 @ is object null? 936 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 937 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 938 FETCH(r3, 1) @ r3<- CCCC 939 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 940 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 941 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 942 cmp r1, #0 @ have we resolved this before? 943 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 944.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 945 cmp r0, r1 @ same class (trivial success)? 946 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 947 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 948 949/* ------------------------------ */ 950 .balign 64 951.L_OP_ARRAY_LENGTH: /* 0x21 */ 952/* File: armv5te/OP_ARRAY_LENGTH.S */ 953 /* 954 * Return the length of an array. 955 */ 956 mov r1, rINST, lsr #12 @ r1<- B 957 mov r2, rINST, lsr #8 @ r2<- A+ 958 GET_VREG(r0, r1) @ r0<- vB (object ref) 959 and r2, r2, #15 @ r2<- A 960 cmp r0, #0 @ is object null? 961 beq common_errNullObject @ yup, fail 962 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 963 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 964 GET_INST_OPCODE(ip) @ extract opcode from rINST 965 SET_VREG(r3, r2) @ vB<- length 966 GOTO_OPCODE(ip) @ jump to next instruction 967 968/* ------------------------------ */ 969 .balign 64 970.L_OP_NEW_INSTANCE: /* 0x22 */ 971/* File: armv5te/OP_NEW_INSTANCE.S */ 972 /* 973 * Create a new instance of a class. 974 */ 975 /* new-instance vAA, class@BBBB */ 976 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 977 FETCH(r1, 1) @ r1<- BBBB 978 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 979 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 980 EXPORT_PC() @ req'd for init, resolve, alloc 981 cmp r0, #0 @ already resolved? 982 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 983.LOP_NEW_INSTANCE_resolved: @ r0=class 984 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 985 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 986 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 987.LOP_NEW_INSTANCE_initialized: @ r0=class 988 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 989 bl dvmAllocObject @ r0<- new object 990 b .LOP_NEW_INSTANCE_finish @ continue 991 992/* ------------------------------ */ 993 .balign 64 994.L_OP_NEW_ARRAY: /* 0x23 */ 995/* File: armv5te/OP_NEW_ARRAY.S */ 996 /* 997 * Allocate an array of objects, specified with the array class 998 * and a count. 999 * 1000 * The verifier guarantees that this is an array class, so we don't 1001 * check for it here. 1002 */ 1003 /* new-array vA, vB, class@CCCC */ 1004 mov r0, rINST, lsr #12 @ r0<- B 1005 FETCH(r2, 1) @ r2<- CCCC 1006 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1007 GET_VREG(r1, r0) @ r1<- vB (array length) 1008 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1009 cmp r1, #0 @ check length 1010 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 1011 bmi common_errNegativeArraySize @ negative length, bail 1012 cmp r0, #0 @ already resolved? 1013 EXPORT_PC() @ req'd for resolve, alloc 1014 bne .LOP_NEW_ARRAY_finish @ resolved, continue 1015 b .LOP_NEW_ARRAY_resolve @ do resolve now 1016 1017/* ------------------------------ */ 1018 .balign 64 1019.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1020/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1021 /* 1022 * Create a new array with elements filled from registers. 1023 * 1024 * for: filled-new-array, filled-new-array/range 1025 */ 1026 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1027 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1028 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1029 FETCH(r1, 1) @ r1<- BBBB 1030 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1031 EXPORT_PC() @ need for resolve and alloc 1032 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1033 mov r10, rINST, lsr #8 @ r10<- AA or BA 1034 cmp r0, #0 @ already resolved? 1035 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10368: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1037 mov r2, #0 @ r2<- false 1038 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1039 bl dvmResolveClass @ r0<- call(clazz, ref) 1040 cmp r0, #0 @ got null? 1041 beq common_exceptionThrown @ yes, handle exception 1042 b .LOP_FILLED_NEW_ARRAY_continue 1043 1044/* ------------------------------ */ 1045 .balign 64 1046.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1047/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1048/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1049 /* 1050 * Create a new array with elements filled from registers. 1051 * 1052 * for: filled-new-array, filled-new-array/range 1053 */ 1054 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1055 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1056 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1057 FETCH(r1, 1) @ r1<- BBBB 1058 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1059 EXPORT_PC() @ need for resolve and alloc 1060 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1061 mov r10, rINST, lsr #8 @ r10<- AA or BA 1062 cmp r0, #0 @ already resolved? 1063 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10648: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1065 mov r2, #0 @ r2<- false 1066 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1067 bl dvmResolveClass @ r0<- call(clazz, ref) 1068 cmp r0, #0 @ got null? 1069 beq common_exceptionThrown @ yes, handle exception 1070 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1071 1072 1073/* ------------------------------ */ 1074 .balign 64 1075.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1076/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1077 /* fill-array-data vAA, +BBBBBBBB */ 1078 FETCH(r0, 1) @ r0<- bbbb (lo) 1079 FETCH(r1, 2) @ r1<- BBBB (hi) 1080 mov r3, rINST, lsr #8 @ r3<- AA 1081 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1082 GET_VREG(r0, r3) @ r0<- vAA (array object) 1083 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1084 EXPORT_PC(); 1085 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1086 cmp r0, #0 @ 0 means an exception is thrown 1087 beq common_exceptionThrown @ has exception 1088 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1089 GET_INST_OPCODE(ip) @ extract opcode from rINST 1090 GOTO_OPCODE(ip) @ jump to next instruction 1091 1092/* ------------------------------ */ 1093 .balign 64 1094.L_OP_THROW: /* 0x27 */ 1095/* File: armv5te/OP_THROW.S */ 1096 /* 1097 * Throw an exception object in the current thread. 1098 */ 1099 /* throw vAA */ 1100 mov r2, rINST, lsr #8 @ r2<- AA 1101 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1102 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1103 EXPORT_PC() @ exception handler can throw 1104 cmp r1, #0 @ null object? 1105 beq common_errNullObject @ yes, throw an NPE instead 1106 @ bypass dvmSetException, just store it 1107 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1108 b common_exceptionThrown 1109 1110/* ------------------------------ */ 1111 .balign 64 1112.L_OP_GOTO: /* 0x28 */ 1113/* File: armv5te/OP_GOTO.S */ 1114 /* 1115 * Unconditional branch, 8-bit offset. 1116 * 1117 * The branch distance is a signed code-unit offset, which we need to 1118 * double to get a byte offset. 1119 */ 1120 /* goto +AA */ 1121 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1122 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1123 mov r9, r9, lsl #1 @ r9<- byte offset 1124 bmi common_backwardBranch @ backward branch, do periodic checks 1125#if defined(WITH_JIT) 1126 GET_JIT_PROF_TABLE(r0) 1127 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1128 cmp r0,#0 1129 bne common_updateProfile 1130 GET_INST_OPCODE(ip) @ extract opcode from rINST 1131 GOTO_OPCODE(ip) @ jump to next instruction 1132#else 1133 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1134 GET_INST_OPCODE(ip) @ extract opcode from rINST 1135 GOTO_OPCODE(ip) @ jump to next instruction 1136#endif 1137 1138/* ------------------------------ */ 1139 .balign 64 1140.L_OP_GOTO_16: /* 0x29 */ 1141/* File: armv5te/OP_GOTO_16.S */ 1142 /* 1143 * Unconditional branch, 16-bit offset. 1144 * 1145 * The branch distance is a signed code-unit offset, which we need to 1146 * double to get a byte offset. 1147 */ 1148 /* goto/16 +AAAA */ 1149 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1150 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1151 bmi common_backwardBranch @ backward branch, do periodic checks 1152#if defined(WITH_JIT) 1153 GET_JIT_PROF_TABLE(r0) 1154 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1155 cmp r0,#0 1156 bne common_updateProfile 1157 GET_INST_OPCODE(ip) @ extract opcode from rINST 1158 GOTO_OPCODE(ip) @ jump to next instruction 1159#else 1160 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1161 GET_INST_OPCODE(ip) @ extract opcode from rINST 1162 GOTO_OPCODE(ip) @ jump to next instruction 1163#endif 1164 1165/* ------------------------------ */ 1166 .balign 64 1167.L_OP_GOTO_32: /* 0x2a */ 1168/* File: armv5te/OP_GOTO_32.S */ 1169 /* 1170 * Unconditional branch, 32-bit offset. 1171 * 1172 * The branch distance is a signed code-unit offset, which we need to 1173 * double to get a byte offset. 1174 * 1175 * Unlike most opcodes, this one is allowed to branch to itself, so 1176 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1177 * instruction doesn't affect the V flag, so we need to clear it 1178 * explicitly. 1179 */ 1180 /* goto/32 +AAAAAAAA */ 1181 FETCH(r0, 1) @ r0<- aaaa (lo) 1182 FETCH(r1, 2) @ r1<- AAAA (hi) 1183 cmp ip, ip @ (clear V flag during stall) 1184 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1185 mov r9, r0, asl #1 @ r9<- byte offset 1186 ble common_backwardBranch @ backward branch, do periodic checks 1187#if defined(WITH_JIT) 1188 GET_JIT_PROF_TABLE(r0) 1189 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1190 cmp r0,#0 1191 bne common_updateProfile 1192 GET_INST_OPCODE(ip) @ extract opcode from rINST 1193 GOTO_OPCODE(ip) @ jump to next instruction 1194#else 1195 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1196 GET_INST_OPCODE(ip) @ extract opcode from rINST 1197 GOTO_OPCODE(ip) @ jump to next instruction 1198#endif 1199 1200/* ------------------------------ */ 1201 .balign 64 1202.L_OP_PACKED_SWITCH: /* 0x2b */ 1203/* File: armv5te/OP_PACKED_SWITCH.S */ 1204 /* 1205 * Handle a packed-switch or sparse-switch instruction. In both cases 1206 * we decode it and hand it off to a helper function. 1207 * 1208 * We don't really expect backward branches in a switch statement, but 1209 * they're perfectly legal, so we check for them here. 1210 * 1211 * for: packed-switch, sparse-switch 1212 */ 1213 /* op vAA, +BBBB */ 1214 FETCH(r0, 1) @ r0<- bbbb (lo) 1215 FETCH(r1, 2) @ r1<- BBBB (hi) 1216 mov r3, rINST, lsr #8 @ r3<- AA 1217 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1218 GET_VREG(r1, r3) @ r1<- vAA 1219 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1220 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1221 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1222 bmi common_backwardBranch @ backward branch, do periodic checks 1223 beq common_backwardBranch @ (want to use BLE but V is unknown) 1224#if defined(WITH_JIT) 1225 GET_JIT_PROF_TABLE(r0) 1226 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1227 cmp r0,#0 1228 bne common_updateProfile 1229 GET_INST_OPCODE(ip) @ extract opcode from rINST 1230 GOTO_OPCODE(ip) @ jump to next instruction 1231#else 1232 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1233 GET_INST_OPCODE(ip) @ extract opcode from rINST 1234 GOTO_OPCODE(ip) @ jump to next instruction 1235#endif 1236 1237/* ------------------------------ */ 1238 .balign 64 1239.L_OP_SPARSE_SWITCH: /* 0x2c */ 1240/* File: armv5te/OP_SPARSE_SWITCH.S */ 1241/* File: armv5te/OP_PACKED_SWITCH.S */ 1242 /* 1243 * Handle a packed-switch or sparse-switch instruction. In both cases 1244 * we decode it and hand it off to a helper function. 1245 * 1246 * We don't really expect backward branches in a switch statement, but 1247 * they're perfectly legal, so we check for them here. 1248 * 1249 * for: packed-switch, sparse-switch 1250 */ 1251 /* op vAA, +BBBB */ 1252 FETCH(r0, 1) @ r0<- bbbb (lo) 1253 FETCH(r1, 2) @ r1<- BBBB (hi) 1254 mov r3, rINST, lsr #8 @ r3<- AA 1255 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1256 GET_VREG(r1, r3) @ r1<- vAA 1257 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1258 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1259 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1260 bmi common_backwardBranch @ backward branch, do periodic checks 1261 beq common_backwardBranch @ (want to use BLE but V is unknown) 1262#if defined(WITH_JIT) 1263 GET_JIT_PROF_TABLE(r0) 1264 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1265 cmp r0,#0 1266 bne common_updateProfile 1267 GET_INST_OPCODE(ip) @ extract opcode from rINST 1268 GOTO_OPCODE(ip) @ jump to next instruction 1269#else 1270 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1271 GET_INST_OPCODE(ip) @ extract opcode from rINST 1272 GOTO_OPCODE(ip) @ jump to next instruction 1273#endif 1274 1275 1276/* ------------------------------ */ 1277 .balign 64 1278.L_OP_CMPL_FLOAT: /* 0x2d */ 1279/* File: arm-vfp/OP_CMPL_FLOAT.S */ 1280 /* 1281 * Compare two floating-point values. Puts 0, 1, or -1 into the 1282 * destination register based on the results of the comparison. 1283 * 1284 * int compare(x, y) { 1285 * if (x == y) { 1286 * return 0; 1287 * } else if (x > y) { 1288 * return 1; 1289 * } else if (x < y) { 1290 * return -1; 1291 * } else { 1292 * return -1; 1293 * } 1294 * } 1295 */ 1296 /* op vAA, vBB, vCC */ 1297 FETCH(r0, 1) @ r0<- CCBB 1298 mov r9, rINST, lsr #8 @ r9<- AA 1299 and r2, r0, #255 @ r2<- BB 1300 mov r3, r0, lsr #8 @ r3<- CC 1301 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1302 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1303 flds s0, [r2] @ s0<- vBB 1304 flds s1, [r3] @ s1<- vCC 1305 fcmpes s0, s1 @ compare (vBB, vCC) 1306 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1307 mvn r0, #0 @ r0<- -1 (default) 1308 GET_INST_OPCODE(ip) @ extract opcode from rINST 1309 fmstat @ export status flags 1310 movgt r0, #1 @ (greater than) r1<- 1 1311 moveq r0, #0 @ (equal) r1<- 0 1312 b .LOP_CMPL_FLOAT_finish @ argh 1313 1314 1315/* ------------------------------ */ 1316 .balign 64 1317.L_OP_CMPG_FLOAT: /* 0x2e */ 1318/* File: arm-vfp/OP_CMPG_FLOAT.S */ 1319 /* 1320 * Compare two floating-point values. Puts 0, 1, or -1 into the 1321 * destination register based on the results of the comparison. 1322 * 1323 * int compare(x, y) { 1324 * if (x == y) { 1325 * return 0; 1326 * } else if (x < y) { 1327 * return -1; 1328 * } else if (x > y) { 1329 * return 1; 1330 * } else { 1331 * return 1; 1332 * } 1333 * } 1334 */ 1335 /* op vAA, vBB, vCC */ 1336 FETCH(r0, 1) @ r0<- CCBB 1337 mov r9, rINST, lsr #8 @ r9<- AA 1338 and r2, r0, #255 @ r2<- BB 1339 mov r3, r0, lsr #8 @ r3<- CC 1340 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1341 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1342 flds s0, [r2] @ s0<- vBB 1343 flds s1, [r3] @ s1<- vCC 1344 fcmpes s0, s1 @ compare (vBB, vCC) 1345 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1346 mov r0, #1 @ r0<- 1 (default) 1347 GET_INST_OPCODE(ip) @ extract opcode from rINST 1348 fmstat @ export status flags 1349 mvnmi r0, #0 @ (less than) r1<- -1 1350 moveq r0, #0 @ (equal) r1<- 0 1351 b .LOP_CMPG_FLOAT_finish @ argh 1352 1353 1354/* ------------------------------ */ 1355 .balign 64 1356.L_OP_CMPL_DOUBLE: /* 0x2f */ 1357/* File: arm-vfp/OP_CMPL_DOUBLE.S */ 1358 /* 1359 * Compare two floating-point values. Puts 0, 1, or -1 into the 1360 * destination register based on the results of the comparison. 1361 * 1362 * int compare(x, y) { 1363 * if (x == y) { 1364 * return 0; 1365 * } else if (x > y) { 1366 * return 1; 1367 * } else if (x < y) { 1368 * return -1; 1369 * } else { 1370 * return -1; 1371 * } 1372 * } 1373 */ 1374 /* op vAA, vBB, vCC */ 1375 FETCH(r0, 1) @ r0<- CCBB 1376 mov r9, rINST, lsr #8 @ r9<- AA 1377 and r2, r0, #255 @ r2<- BB 1378 mov r3, r0, lsr #8 @ r3<- CC 1379 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1380 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1381 fldd d0, [r2] @ d0<- vBB 1382 fldd d1, [r3] @ d1<- vCC 1383 fcmped d0, d1 @ compare (vBB, vCC) 1384 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1385 mvn r0, #0 @ r0<- -1 (default) 1386 GET_INST_OPCODE(ip) @ extract opcode from rINST 1387 fmstat @ export status flags 1388 movgt r0, #1 @ (greater than) r1<- 1 1389 moveq r0, #0 @ (equal) r1<- 0 1390 b .LOP_CMPL_DOUBLE_finish @ argh 1391 1392 1393/* ------------------------------ */ 1394 .balign 64 1395.L_OP_CMPG_DOUBLE: /* 0x30 */ 1396/* File: arm-vfp/OP_CMPG_DOUBLE.S */ 1397 /* 1398 * Compare two floating-point values. Puts 0, 1, or -1 into the 1399 * destination register based on the results of the comparison. 1400 * 1401 * int compare(x, y) { 1402 * if (x == y) { 1403 * return 0; 1404 * } else if (x < y) { 1405 * return -1; 1406 * } else if (x > y) { 1407 * return 1; 1408 * } else { 1409 * return 1; 1410 * } 1411 * } 1412 */ 1413 /* op vAA, vBB, vCC */ 1414 FETCH(r0, 1) @ r0<- CCBB 1415 mov r9, rINST, lsr #8 @ r9<- AA 1416 and r2, r0, #255 @ r2<- BB 1417 mov r3, r0, lsr #8 @ r3<- CC 1418 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1419 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1420 fldd d0, [r2] @ d0<- vBB 1421 fldd d1, [r3] @ d1<- vCC 1422 fcmped d0, d1 @ compare (vBB, vCC) 1423 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1424 mov r0, #1 @ r0<- 1 (default) 1425 GET_INST_OPCODE(ip) @ extract opcode from rINST 1426 fmstat @ export status flags 1427 mvnmi r0, #0 @ (less than) r1<- -1 1428 moveq r0, #0 @ (equal) r1<- 0 1429 b .LOP_CMPG_DOUBLE_finish @ argh 1430 1431 1432/* ------------------------------ */ 1433 .balign 64 1434.L_OP_CMP_LONG: /* 0x31 */ 1435/* File: armv5te/OP_CMP_LONG.S */ 1436 /* 1437 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1438 * register based on the results of the comparison. 1439 * 1440 * We load the full values with LDM, but in practice many values could 1441 * be resolved by only looking at the high word. This could be made 1442 * faster or slower by splitting the LDM into a pair of LDRs. 1443 * 1444 * If we just wanted to set condition flags, we could do this: 1445 * subs ip, r0, r2 1446 * sbcs ip, r1, r3 1447 * subeqs ip, r0, r2 1448 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1449 * integer value, which we can do with 2 conditional mov/mvn instructions 1450 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1451 * us a constant 5-cycle path plus a branch at the end to the 1452 * instruction epilogue code. The multi-compare approach below needs 1453 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1454 * in the worst case (the 64-bit values are equal). 1455 */ 1456 /* cmp-long vAA, vBB, vCC */ 1457 FETCH(r0, 1) @ r0<- CCBB 1458 mov r9, rINST, lsr #8 @ r9<- AA 1459 and r2, r0, #255 @ r2<- BB 1460 mov r3, r0, lsr #8 @ r3<- CC 1461 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1462 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1463 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1464 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1465 cmp r1, r3 @ compare (vBB+1, vCC+1) 1466 blt .LOP_CMP_LONG_less @ signed compare on high part 1467 bgt .LOP_CMP_LONG_greater 1468 subs r1, r0, r2 @ r1<- r0 - r2 1469 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1470 bne .LOP_CMP_LONG_less 1471 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1472 1473/* ------------------------------ */ 1474 .balign 64 1475.L_OP_IF_EQ: /* 0x32 */ 1476/* File: armv5te/OP_IF_EQ.S */ 1477/* File: armv5te/bincmp.S */ 1478 /* 1479 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1480 * fragment that specifies the *reverse* comparison to perform, e.g. 1481 * for "if-le" you would use "gt". 1482 * 1483 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1484 */ 1485 /* if-cmp vA, vB, +CCCC */ 1486 mov r0, rINST, lsr #8 @ r0<- A+ 1487 mov r1, rINST, lsr #12 @ r1<- B 1488 and r0, r0, #15 1489 GET_VREG(r3, r1) @ r3<- vB 1490 GET_VREG(r2, r0) @ r2<- vA 1491 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1492 cmp r2, r3 @ compare (vA, vB) 1493 bne 1f @ branch to 1 if comparison failed 1494 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1495 movs r9, r9, asl #1 @ convert to bytes, check sign 1496 bmi common_backwardBranch @ yes, do periodic checks 14971: 1498#if defined(WITH_JIT) 1499 GET_JIT_PROF_TABLE(r0) 1500 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1501 b common_testUpdateProfile 1502#else 1503 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1504 GET_INST_OPCODE(ip) @ extract opcode from rINST 1505 GOTO_OPCODE(ip) @ jump to next instruction 1506#endif 1507 1508 1509/* ------------------------------ */ 1510 .balign 64 1511.L_OP_IF_NE: /* 0x33 */ 1512/* File: armv5te/OP_IF_NE.S */ 1513/* File: armv5te/bincmp.S */ 1514 /* 1515 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1516 * fragment that specifies the *reverse* comparison to perform, e.g. 1517 * for "if-le" you would use "gt". 1518 * 1519 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1520 */ 1521 /* if-cmp vA, vB, +CCCC */ 1522 mov r0, rINST, lsr #8 @ r0<- A+ 1523 mov r1, rINST, lsr #12 @ r1<- B 1524 and r0, r0, #15 1525 GET_VREG(r3, r1) @ r3<- vB 1526 GET_VREG(r2, r0) @ r2<- vA 1527 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1528 cmp r2, r3 @ compare (vA, vB) 1529 beq 1f @ branch to 1 if comparison failed 1530 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1531 movs r9, r9, asl #1 @ convert to bytes, check sign 1532 bmi common_backwardBranch @ yes, do periodic checks 15331: 1534#if defined(WITH_JIT) 1535 GET_JIT_PROF_TABLE(r0) 1536 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1537 b common_testUpdateProfile 1538#else 1539 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1540 GET_INST_OPCODE(ip) @ extract opcode from rINST 1541 GOTO_OPCODE(ip) @ jump to next instruction 1542#endif 1543 1544 1545/* ------------------------------ */ 1546 .balign 64 1547.L_OP_IF_LT: /* 0x34 */ 1548/* File: armv5te/OP_IF_LT.S */ 1549/* File: armv5te/bincmp.S */ 1550 /* 1551 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1552 * fragment that specifies the *reverse* comparison to perform, e.g. 1553 * for "if-le" you would use "gt". 1554 * 1555 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1556 */ 1557 /* if-cmp vA, vB, +CCCC */ 1558 mov r0, rINST, lsr #8 @ r0<- A+ 1559 mov r1, rINST, lsr #12 @ r1<- B 1560 and r0, r0, #15 1561 GET_VREG(r3, r1) @ r3<- vB 1562 GET_VREG(r2, r0) @ r2<- vA 1563 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1564 cmp r2, r3 @ compare (vA, vB) 1565 bge 1f @ branch to 1 if comparison failed 1566 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1567 movs r9, r9, asl #1 @ convert to bytes, check sign 1568 bmi common_backwardBranch @ yes, do periodic checks 15691: 1570#if defined(WITH_JIT) 1571 GET_JIT_PROF_TABLE(r0) 1572 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1573 b common_testUpdateProfile 1574#else 1575 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1576 GET_INST_OPCODE(ip) @ extract opcode from rINST 1577 GOTO_OPCODE(ip) @ jump to next instruction 1578#endif 1579 1580 1581/* ------------------------------ */ 1582 .balign 64 1583.L_OP_IF_GE: /* 0x35 */ 1584/* File: armv5te/OP_IF_GE.S */ 1585/* File: armv5te/bincmp.S */ 1586 /* 1587 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1588 * fragment that specifies the *reverse* comparison to perform, e.g. 1589 * for "if-le" you would use "gt". 1590 * 1591 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1592 */ 1593 /* if-cmp vA, vB, +CCCC */ 1594 mov r0, rINST, lsr #8 @ r0<- A+ 1595 mov r1, rINST, lsr #12 @ r1<- B 1596 and r0, r0, #15 1597 GET_VREG(r3, r1) @ r3<- vB 1598 GET_VREG(r2, r0) @ r2<- vA 1599 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1600 cmp r2, r3 @ compare (vA, vB) 1601 blt 1f @ branch to 1 if comparison failed 1602 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1603 movs r9, r9, asl #1 @ convert to bytes, check sign 1604 bmi common_backwardBranch @ yes, do periodic checks 16051: 1606#if defined(WITH_JIT) 1607 GET_JIT_PROF_TABLE(r0) 1608 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1609 b common_testUpdateProfile 1610#else 1611 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1612 GET_INST_OPCODE(ip) @ extract opcode from rINST 1613 GOTO_OPCODE(ip) @ jump to next instruction 1614#endif 1615 1616 1617/* ------------------------------ */ 1618 .balign 64 1619.L_OP_IF_GT: /* 0x36 */ 1620/* File: armv5te/OP_IF_GT.S */ 1621/* File: armv5te/bincmp.S */ 1622 /* 1623 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1624 * fragment that specifies the *reverse* comparison to perform, e.g. 1625 * for "if-le" you would use "gt". 1626 * 1627 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1628 */ 1629 /* if-cmp vA, vB, +CCCC */ 1630 mov r0, rINST, lsr #8 @ r0<- A+ 1631 mov r1, rINST, lsr #12 @ r1<- B 1632 and r0, r0, #15 1633 GET_VREG(r3, r1) @ r3<- vB 1634 GET_VREG(r2, r0) @ r2<- vA 1635 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1636 cmp r2, r3 @ compare (vA, vB) 1637 ble 1f @ branch to 1 if comparison failed 1638 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1639 movs r9, r9, asl #1 @ convert to bytes, check sign 1640 bmi common_backwardBranch @ yes, do periodic checks 16411: 1642#if defined(WITH_JIT) 1643 GET_JIT_PROF_TABLE(r0) 1644 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1645 b common_testUpdateProfile 1646#else 1647 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1648 GET_INST_OPCODE(ip) @ extract opcode from rINST 1649 GOTO_OPCODE(ip) @ jump to next instruction 1650#endif 1651 1652 1653/* ------------------------------ */ 1654 .balign 64 1655.L_OP_IF_LE: /* 0x37 */ 1656/* File: armv5te/OP_IF_LE.S */ 1657/* File: armv5te/bincmp.S */ 1658 /* 1659 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1660 * fragment that specifies the *reverse* comparison to perform, e.g. 1661 * for "if-le" you would use "gt". 1662 * 1663 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1664 */ 1665 /* if-cmp vA, vB, +CCCC */ 1666 mov r0, rINST, lsr #8 @ r0<- A+ 1667 mov r1, rINST, lsr #12 @ r1<- B 1668 and r0, r0, #15 1669 GET_VREG(r3, r1) @ r3<- vB 1670 GET_VREG(r2, r0) @ r2<- vA 1671 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1672 cmp r2, r3 @ compare (vA, vB) 1673 bgt 1f @ branch to 1 if comparison failed 1674 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1675 movs r9, r9, asl #1 @ convert to bytes, check sign 1676 bmi common_backwardBranch @ yes, do periodic checks 16771: 1678#if defined(WITH_JIT) 1679 GET_JIT_PROF_TABLE(r0) 1680 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1681 b common_testUpdateProfile 1682#else 1683 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1684 GET_INST_OPCODE(ip) @ extract opcode from rINST 1685 GOTO_OPCODE(ip) @ jump to next instruction 1686#endif 1687 1688 1689/* ------------------------------ */ 1690 .balign 64 1691.L_OP_IF_EQZ: /* 0x38 */ 1692/* File: armv5te/OP_IF_EQZ.S */ 1693/* File: armv5te/zcmp.S */ 1694 /* 1695 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1696 * fragment that specifies the *reverse* comparison to perform, e.g. 1697 * for "if-le" you would use "gt". 1698 * 1699 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1700 */ 1701 /* if-cmp vAA, +BBBB */ 1702 mov r0, rINST, lsr #8 @ r0<- AA 1703 GET_VREG(r2, r0) @ r2<- vAA 1704 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1705 cmp r2, #0 @ compare (vA, 0) 1706 bne 1f @ branch to 1 if comparison failed 1707 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1708 movs r9, r9, asl #1 @ convert to bytes, check sign 1709 bmi common_backwardBranch @ backward branch, do periodic checks 17101: 1711#if defined(WITH_JIT) 1712 GET_JIT_PROF_TABLE(r0) 1713 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1714 cmp r0,#0 1715 bne common_updateProfile 1716 GET_INST_OPCODE(ip) @ extract opcode from rINST 1717 GOTO_OPCODE(ip) @ jump to next instruction 1718#else 1719 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1720 GET_INST_OPCODE(ip) @ extract opcode from rINST 1721 GOTO_OPCODE(ip) @ jump to next instruction 1722#endif 1723 1724 1725/* ------------------------------ */ 1726 .balign 64 1727.L_OP_IF_NEZ: /* 0x39 */ 1728/* File: armv5te/OP_IF_NEZ.S */ 1729/* File: armv5te/zcmp.S */ 1730 /* 1731 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1732 * fragment that specifies the *reverse* comparison to perform, e.g. 1733 * for "if-le" you would use "gt". 1734 * 1735 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1736 */ 1737 /* if-cmp vAA, +BBBB */ 1738 mov r0, rINST, lsr #8 @ r0<- AA 1739 GET_VREG(r2, r0) @ r2<- vAA 1740 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1741 cmp r2, #0 @ compare (vA, 0) 1742 beq 1f @ branch to 1 if comparison failed 1743 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1744 movs r9, r9, asl #1 @ convert to bytes, check sign 1745 bmi common_backwardBranch @ backward branch, do periodic checks 17461: 1747#if defined(WITH_JIT) 1748 GET_JIT_PROF_TABLE(r0) 1749 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1750 cmp r0,#0 1751 bne common_updateProfile 1752 GET_INST_OPCODE(ip) @ extract opcode from rINST 1753 GOTO_OPCODE(ip) @ jump to next instruction 1754#else 1755 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1756 GET_INST_OPCODE(ip) @ extract opcode from rINST 1757 GOTO_OPCODE(ip) @ jump to next instruction 1758#endif 1759 1760 1761/* ------------------------------ */ 1762 .balign 64 1763.L_OP_IF_LTZ: /* 0x3a */ 1764/* File: armv5te/OP_IF_LTZ.S */ 1765/* File: armv5te/zcmp.S */ 1766 /* 1767 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1768 * fragment that specifies the *reverse* comparison to perform, e.g. 1769 * for "if-le" you would use "gt". 1770 * 1771 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1772 */ 1773 /* if-cmp vAA, +BBBB */ 1774 mov r0, rINST, lsr #8 @ r0<- AA 1775 GET_VREG(r2, r0) @ r2<- vAA 1776 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1777 cmp r2, #0 @ compare (vA, 0) 1778 bge 1f @ branch to 1 if comparison failed 1779 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1780 movs r9, r9, asl #1 @ convert to bytes, check sign 1781 bmi common_backwardBranch @ backward branch, do periodic checks 17821: 1783#if defined(WITH_JIT) 1784 GET_JIT_PROF_TABLE(r0) 1785 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1786 cmp r0,#0 1787 bne common_updateProfile 1788 GET_INST_OPCODE(ip) @ extract opcode from rINST 1789 GOTO_OPCODE(ip) @ jump to next instruction 1790#else 1791 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1792 GET_INST_OPCODE(ip) @ extract opcode from rINST 1793 GOTO_OPCODE(ip) @ jump to next instruction 1794#endif 1795 1796 1797/* ------------------------------ */ 1798 .balign 64 1799.L_OP_IF_GEZ: /* 0x3b */ 1800/* File: armv5te/OP_IF_GEZ.S */ 1801/* File: armv5te/zcmp.S */ 1802 /* 1803 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1804 * fragment that specifies the *reverse* comparison to perform, e.g. 1805 * for "if-le" you would use "gt". 1806 * 1807 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1808 */ 1809 /* if-cmp vAA, +BBBB */ 1810 mov r0, rINST, lsr #8 @ r0<- AA 1811 GET_VREG(r2, r0) @ r2<- vAA 1812 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1813 cmp r2, #0 @ compare (vA, 0) 1814 blt 1f @ branch to 1 if comparison failed 1815 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1816 movs r9, r9, asl #1 @ convert to bytes, check sign 1817 bmi common_backwardBranch @ backward branch, do periodic checks 18181: 1819#if defined(WITH_JIT) 1820 GET_JIT_PROF_TABLE(r0) 1821 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1822 cmp r0,#0 1823 bne common_updateProfile 1824 GET_INST_OPCODE(ip) @ extract opcode from rINST 1825 GOTO_OPCODE(ip) @ jump to next instruction 1826#else 1827 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1828 GET_INST_OPCODE(ip) @ extract opcode from rINST 1829 GOTO_OPCODE(ip) @ jump to next instruction 1830#endif 1831 1832 1833/* ------------------------------ */ 1834 .balign 64 1835.L_OP_IF_GTZ: /* 0x3c */ 1836/* File: armv5te/OP_IF_GTZ.S */ 1837/* File: armv5te/zcmp.S */ 1838 /* 1839 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1840 * fragment that specifies the *reverse* comparison to perform, e.g. 1841 * for "if-le" you would use "gt". 1842 * 1843 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1844 */ 1845 /* if-cmp vAA, +BBBB */ 1846 mov r0, rINST, lsr #8 @ r0<- AA 1847 GET_VREG(r2, r0) @ r2<- vAA 1848 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1849 cmp r2, #0 @ compare (vA, 0) 1850 ble 1f @ branch to 1 if comparison failed 1851 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1852 movs r9, r9, asl #1 @ convert to bytes, check sign 1853 bmi common_backwardBranch @ backward branch, do periodic checks 18541: 1855#if defined(WITH_JIT) 1856 GET_JIT_PROF_TABLE(r0) 1857 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1858 cmp r0,#0 1859 bne common_updateProfile 1860 GET_INST_OPCODE(ip) @ extract opcode from rINST 1861 GOTO_OPCODE(ip) @ jump to next instruction 1862#else 1863 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1864 GET_INST_OPCODE(ip) @ extract opcode from rINST 1865 GOTO_OPCODE(ip) @ jump to next instruction 1866#endif 1867 1868 1869/* ------------------------------ */ 1870 .balign 64 1871.L_OP_IF_LEZ: /* 0x3d */ 1872/* File: armv5te/OP_IF_LEZ.S */ 1873/* File: armv5te/zcmp.S */ 1874 /* 1875 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1876 * fragment that specifies the *reverse* comparison to perform, e.g. 1877 * for "if-le" you would use "gt". 1878 * 1879 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1880 */ 1881 /* if-cmp vAA, +BBBB */ 1882 mov r0, rINST, lsr #8 @ r0<- AA 1883 GET_VREG(r2, r0) @ r2<- vAA 1884 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1885 cmp r2, #0 @ compare (vA, 0) 1886 bgt 1f @ branch to 1 if comparison failed 1887 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1888 movs r9, r9, asl #1 @ convert to bytes, check sign 1889 bmi common_backwardBranch @ backward branch, do periodic checks 18901: 1891#if defined(WITH_JIT) 1892 GET_JIT_PROF_TABLE(r0) 1893 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1894 cmp r0,#0 1895 bne common_updateProfile 1896 GET_INST_OPCODE(ip) @ extract opcode from rINST 1897 GOTO_OPCODE(ip) @ jump to next instruction 1898#else 1899 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1900 GET_INST_OPCODE(ip) @ extract opcode from rINST 1901 GOTO_OPCODE(ip) @ jump to next instruction 1902#endif 1903 1904 1905/* ------------------------------ */ 1906 .balign 64 1907.L_OP_UNUSED_3E: /* 0x3e */ 1908/* File: armv5te/OP_UNUSED_3E.S */ 1909/* File: armv5te/unused.S */ 1910 bl common_abort 1911 1912 1913/* ------------------------------ */ 1914 .balign 64 1915.L_OP_UNUSED_3F: /* 0x3f */ 1916/* File: armv5te/OP_UNUSED_3F.S */ 1917/* File: armv5te/unused.S */ 1918 bl common_abort 1919 1920 1921/* ------------------------------ */ 1922 .balign 64 1923.L_OP_UNUSED_40: /* 0x40 */ 1924/* File: armv5te/OP_UNUSED_40.S */ 1925/* File: armv5te/unused.S */ 1926 bl common_abort 1927 1928 1929/* ------------------------------ */ 1930 .balign 64 1931.L_OP_UNUSED_41: /* 0x41 */ 1932/* File: armv5te/OP_UNUSED_41.S */ 1933/* File: armv5te/unused.S */ 1934 bl common_abort 1935 1936 1937/* ------------------------------ */ 1938 .balign 64 1939.L_OP_UNUSED_42: /* 0x42 */ 1940/* File: armv5te/OP_UNUSED_42.S */ 1941/* File: armv5te/unused.S */ 1942 bl common_abort 1943 1944 1945/* ------------------------------ */ 1946 .balign 64 1947.L_OP_UNUSED_43: /* 0x43 */ 1948/* File: armv5te/OP_UNUSED_43.S */ 1949/* File: armv5te/unused.S */ 1950 bl common_abort 1951 1952 1953/* ------------------------------ */ 1954 .balign 64 1955.L_OP_AGET: /* 0x44 */ 1956/* File: armv5te/OP_AGET.S */ 1957 /* 1958 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1959 * 1960 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1961 * instructions. We use a pair of FETCH_Bs instead. 1962 * 1963 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1964 */ 1965 /* op vAA, vBB, vCC */ 1966 FETCH_B(r2, 1, 0) @ r2<- BB 1967 mov r9, rINST, lsr #8 @ r9<- AA 1968 FETCH_B(r3, 1, 1) @ r3<- CC 1969 GET_VREG(r0, r2) @ r0<- vBB (array object) 1970 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1971 cmp r0, #0 @ null array object? 1972 beq common_errNullObject @ yes, bail 1973 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1974 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 1975 cmp r1, r3 @ compare unsigned index, length 1976 bcs common_errArrayIndex @ index >= length, bail 1977 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1978 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 1979 GET_INST_OPCODE(ip) @ extract opcode from rINST 1980 SET_VREG(r2, r9) @ vAA<- r2 1981 GOTO_OPCODE(ip) @ jump to next instruction 1982 1983/* ------------------------------ */ 1984 .balign 64 1985.L_OP_AGET_WIDE: /* 0x45 */ 1986/* File: armv5te/OP_AGET_WIDE.S */ 1987 /* 1988 * Array get, 64 bits. vAA <- vBB[vCC]. 1989 * 1990 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 1991 */ 1992 /* aget-wide vAA, vBB, vCC */ 1993 FETCH(r0, 1) @ r0<- CCBB 1994 mov r9, rINST, lsr #8 @ r9<- AA 1995 and r2, r0, #255 @ r2<- BB 1996 mov r3, r0, lsr #8 @ r3<- CC 1997 GET_VREG(r0, r2) @ r0<- vBB (array object) 1998 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1999 cmp r0, #0 @ null array object? 2000 beq common_errNullObject @ yes, bail 2001 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2002 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2003 cmp r1, r3 @ compare unsigned index, length 2004 bcc .LOP_AGET_WIDE_finish @ okay, continue below 2005 b common_errArrayIndex @ index >= length, bail 2006 @ May want to swap the order of these two branches depending on how the 2007 @ branch prediction (if any) handles conditional forward branches vs. 2008 @ unconditional forward branches. 2009 2010/* ------------------------------ */ 2011 .balign 64 2012.L_OP_AGET_OBJECT: /* 0x46 */ 2013/* File: armv5te/OP_AGET_OBJECT.S */ 2014/* File: armv5te/OP_AGET.S */ 2015 /* 2016 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2017 * 2018 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2019 * instructions. We use a pair of FETCH_Bs instead. 2020 * 2021 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2022 */ 2023 /* op vAA, vBB, vCC */ 2024 FETCH_B(r2, 1, 0) @ r2<- BB 2025 mov r9, rINST, lsr #8 @ r9<- AA 2026 FETCH_B(r3, 1, 1) @ r3<- CC 2027 GET_VREG(r0, r2) @ r0<- vBB (array object) 2028 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2029 cmp r0, #0 @ null array object? 2030 beq common_errNullObject @ yes, bail 2031 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2032 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2033 cmp r1, r3 @ compare unsigned index, length 2034 bcs common_errArrayIndex @ index >= length, bail 2035 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2036 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2037 GET_INST_OPCODE(ip) @ extract opcode from rINST 2038 SET_VREG(r2, r9) @ vAA<- r2 2039 GOTO_OPCODE(ip) @ jump to next instruction 2040 2041 2042/* ------------------------------ */ 2043 .balign 64 2044.L_OP_AGET_BOOLEAN: /* 0x47 */ 2045/* File: armv5te/OP_AGET_BOOLEAN.S */ 2046/* File: armv5te/OP_AGET.S */ 2047 /* 2048 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2049 * 2050 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2051 * instructions. We use a pair of FETCH_Bs instead. 2052 * 2053 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2054 */ 2055 /* op vAA, vBB, vCC */ 2056 FETCH_B(r2, 1, 0) @ r2<- BB 2057 mov r9, rINST, lsr #8 @ r9<- AA 2058 FETCH_B(r3, 1, 1) @ r3<- CC 2059 GET_VREG(r0, r2) @ r0<- vBB (array object) 2060 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2061 cmp r0, #0 @ null array object? 2062 beq common_errNullObject @ yes, bail 2063 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2064 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2065 cmp r1, r3 @ compare unsigned index, length 2066 bcs common_errArrayIndex @ index >= length, bail 2067 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2068 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2069 GET_INST_OPCODE(ip) @ extract opcode from rINST 2070 SET_VREG(r2, r9) @ vAA<- r2 2071 GOTO_OPCODE(ip) @ jump to next instruction 2072 2073 2074/* ------------------------------ */ 2075 .balign 64 2076.L_OP_AGET_BYTE: /* 0x48 */ 2077/* File: armv5te/OP_AGET_BYTE.S */ 2078/* File: armv5te/OP_AGET.S */ 2079 /* 2080 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2081 * 2082 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2083 * instructions. We use a pair of FETCH_Bs instead. 2084 * 2085 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2086 */ 2087 /* op vAA, vBB, vCC */ 2088 FETCH_B(r2, 1, 0) @ r2<- BB 2089 mov r9, rINST, lsr #8 @ r9<- AA 2090 FETCH_B(r3, 1, 1) @ r3<- CC 2091 GET_VREG(r0, r2) @ r0<- vBB (array object) 2092 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2093 cmp r0, #0 @ null array object? 2094 beq common_errNullObject @ yes, bail 2095 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2096 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2097 cmp r1, r3 @ compare unsigned index, length 2098 bcs common_errArrayIndex @ index >= length, bail 2099 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2100 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2101 GET_INST_OPCODE(ip) @ extract opcode from rINST 2102 SET_VREG(r2, r9) @ vAA<- r2 2103 GOTO_OPCODE(ip) @ jump to next instruction 2104 2105 2106/* ------------------------------ */ 2107 .balign 64 2108.L_OP_AGET_CHAR: /* 0x49 */ 2109/* File: armv5te/OP_AGET_CHAR.S */ 2110/* File: armv5te/OP_AGET.S */ 2111 /* 2112 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2113 * 2114 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2115 * instructions. We use a pair of FETCH_Bs instead. 2116 * 2117 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2118 */ 2119 /* op vAA, vBB, vCC */ 2120 FETCH_B(r2, 1, 0) @ r2<- BB 2121 mov r9, rINST, lsr #8 @ r9<- AA 2122 FETCH_B(r3, 1, 1) @ r3<- CC 2123 GET_VREG(r0, r2) @ r0<- vBB (array object) 2124 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2125 cmp r0, #0 @ null array object? 2126 beq common_errNullObject @ yes, bail 2127 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2128 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2129 cmp r1, r3 @ compare unsigned index, length 2130 bcs common_errArrayIndex @ index >= length, bail 2131 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2132 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2133 GET_INST_OPCODE(ip) @ extract opcode from rINST 2134 SET_VREG(r2, r9) @ vAA<- r2 2135 GOTO_OPCODE(ip) @ jump to next instruction 2136 2137 2138/* ------------------------------ */ 2139 .balign 64 2140.L_OP_AGET_SHORT: /* 0x4a */ 2141/* File: armv5te/OP_AGET_SHORT.S */ 2142/* File: armv5te/OP_AGET.S */ 2143 /* 2144 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2145 * 2146 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2147 * instructions. We use a pair of FETCH_Bs instead. 2148 * 2149 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2150 */ 2151 /* op vAA, vBB, vCC */ 2152 FETCH_B(r2, 1, 0) @ r2<- BB 2153 mov r9, rINST, lsr #8 @ r9<- AA 2154 FETCH_B(r3, 1, 1) @ r3<- CC 2155 GET_VREG(r0, r2) @ r0<- vBB (array object) 2156 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2157 cmp r0, #0 @ null array object? 2158 beq common_errNullObject @ yes, bail 2159 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2160 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2161 cmp r1, r3 @ compare unsigned index, length 2162 bcs common_errArrayIndex @ index >= length, bail 2163 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2164 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2165 GET_INST_OPCODE(ip) @ extract opcode from rINST 2166 SET_VREG(r2, r9) @ vAA<- r2 2167 GOTO_OPCODE(ip) @ jump to next instruction 2168 2169 2170/* ------------------------------ */ 2171 .balign 64 2172.L_OP_APUT: /* 0x4b */ 2173/* File: armv5te/OP_APUT.S */ 2174 /* 2175 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2176 * 2177 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2178 * instructions. We use a pair of FETCH_Bs instead. 2179 * 2180 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2181 */ 2182 /* op vAA, vBB, vCC */ 2183 FETCH_B(r2, 1, 0) @ r2<- BB 2184 mov r9, rINST, lsr #8 @ r9<- AA 2185 FETCH_B(r3, 1, 1) @ r3<- CC 2186 GET_VREG(r0, r2) @ r0<- vBB (array object) 2187 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2188 cmp r0, #0 @ null array object? 2189 beq common_errNullObject @ yes, bail 2190 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2191 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2192 cmp r1, r3 @ compare unsigned index, length 2193 bcs common_errArrayIndex @ index >= length, bail 2194 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2195 GET_VREG(r2, r9) @ r2<- vAA 2196 GET_INST_OPCODE(ip) @ extract opcode from rINST 2197 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2198 GOTO_OPCODE(ip) @ jump to next instruction 2199 2200/* ------------------------------ */ 2201 .balign 64 2202.L_OP_APUT_WIDE: /* 0x4c */ 2203/* File: armv5te/OP_APUT_WIDE.S */ 2204 /* 2205 * Array put, 64 bits. vBB[vCC] <- vAA. 2206 * 2207 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 2208 */ 2209 /* aput-wide vAA, vBB, vCC */ 2210 FETCH(r0, 1) @ r0<- CCBB 2211 mov r9, rINST, lsr #8 @ r9<- AA 2212 and r2, r0, #255 @ r2<- BB 2213 mov r3, r0, lsr #8 @ r3<- CC 2214 GET_VREG(r0, r2) @ r0<- vBB (array object) 2215 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2216 cmp r0, #0 @ null array object? 2217 beq common_errNullObject @ yes, bail 2218 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2219 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2220 cmp r1, r3 @ compare unsigned index, length 2221 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2222 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2223 b common_errArrayIndex @ index >= length, bail 2224 @ May want to swap the order of these two branches depending on how the 2225 @ branch prediction (if any) handles conditional forward branches vs. 2226 @ unconditional forward branches. 2227 2228/* ------------------------------ */ 2229 .balign 64 2230.L_OP_APUT_OBJECT: /* 0x4d */ 2231/* File: armv5te/OP_APUT_OBJECT.S */ 2232 /* 2233 * Store an object into an array. vBB[vCC] <- vAA. 2234 */ 2235 /* op vAA, vBB, vCC */ 2236 FETCH(r0, 1) @ r0<- CCBB 2237 mov r9, rINST, lsr #8 @ r9<- AA 2238 and r2, r0, #255 @ r2<- BB 2239 mov r3, r0, lsr #8 @ r3<- CC 2240 GET_VREG(rINST, r2) @ rINST<- vBB (array object) 2241 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2242 cmp rINST, #0 @ null array object? 2243 GET_VREG(r9, r9) @ r9<- vAA 2244 beq common_errNullObject @ yes, bail 2245 ldr r3, [rINST, #offArrayObject_length] @ r3<- arrayObj->length 2246 add r10, rINST, r1, lsl #2 @ r10<- arrayObj + index*width 2247 cmp r1, r3 @ compare unsigned index, length 2248 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2249 b common_errArrayIndex @ index >= length, bail 2250 2251 2252/* ------------------------------ */ 2253 .balign 64 2254.L_OP_APUT_BOOLEAN: /* 0x4e */ 2255/* File: armv5te/OP_APUT_BOOLEAN.S */ 2256/* File: armv5te/OP_APUT.S */ 2257 /* 2258 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2259 * 2260 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2261 * instructions. We use a pair of FETCH_Bs instead. 2262 * 2263 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2264 */ 2265 /* op vAA, vBB, vCC */ 2266 FETCH_B(r2, 1, 0) @ r2<- BB 2267 mov r9, rINST, lsr #8 @ r9<- AA 2268 FETCH_B(r3, 1, 1) @ r3<- CC 2269 GET_VREG(r0, r2) @ r0<- vBB (array object) 2270 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2271 cmp r0, #0 @ null array object? 2272 beq common_errNullObject @ yes, bail 2273 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2274 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2275 cmp r1, r3 @ compare unsigned index, length 2276 bcs common_errArrayIndex @ index >= length, bail 2277 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2278 GET_VREG(r2, r9) @ r2<- vAA 2279 GET_INST_OPCODE(ip) @ extract opcode from rINST 2280 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2281 GOTO_OPCODE(ip) @ jump to next instruction 2282 2283 2284/* ------------------------------ */ 2285 .balign 64 2286.L_OP_APUT_BYTE: /* 0x4f */ 2287/* File: armv5te/OP_APUT_BYTE.S */ 2288/* File: armv5te/OP_APUT.S */ 2289 /* 2290 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2291 * 2292 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2293 * instructions. We use a pair of FETCH_Bs instead. 2294 * 2295 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2296 */ 2297 /* op vAA, vBB, vCC */ 2298 FETCH_B(r2, 1, 0) @ r2<- BB 2299 mov r9, rINST, lsr #8 @ r9<- AA 2300 FETCH_B(r3, 1, 1) @ r3<- CC 2301 GET_VREG(r0, r2) @ r0<- vBB (array object) 2302 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2303 cmp r0, #0 @ null array object? 2304 beq common_errNullObject @ yes, bail 2305 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2306 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2307 cmp r1, r3 @ compare unsigned index, length 2308 bcs common_errArrayIndex @ index >= length, bail 2309 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2310 GET_VREG(r2, r9) @ r2<- vAA 2311 GET_INST_OPCODE(ip) @ extract opcode from rINST 2312 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2313 GOTO_OPCODE(ip) @ jump to next instruction 2314 2315 2316/* ------------------------------ */ 2317 .balign 64 2318.L_OP_APUT_CHAR: /* 0x50 */ 2319/* File: armv5te/OP_APUT_CHAR.S */ 2320/* File: armv5te/OP_APUT.S */ 2321 /* 2322 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2323 * 2324 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2325 * instructions. We use a pair of FETCH_Bs instead. 2326 * 2327 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2328 */ 2329 /* op vAA, vBB, vCC */ 2330 FETCH_B(r2, 1, 0) @ r2<- BB 2331 mov r9, rINST, lsr #8 @ r9<- AA 2332 FETCH_B(r3, 1, 1) @ r3<- CC 2333 GET_VREG(r0, r2) @ r0<- vBB (array object) 2334 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2335 cmp r0, #0 @ null array object? 2336 beq common_errNullObject @ yes, bail 2337 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2338 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2339 cmp r1, r3 @ compare unsigned index, length 2340 bcs common_errArrayIndex @ index >= length, bail 2341 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2342 GET_VREG(r2, r9) @ r2<- vAA 2343 GET_INST_OPCODE(ip) @ extract opcode from rINST 2344 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2345 GOTO_OPCODE(ip) @ jump to next instruction 2346 2347 2348/* ------------------------------ */ 2349 .balign 64 2350.L_OP_APUT_SHORT: /* 0x51 */ 2351/* File: armv5te/OP_APUT_SHORT.S */ 2352/* File: armv5te/OP_APUT.S */ 2353 /* 2354 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2355 * 2356 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2357 * instructions. We use a pair of FETCH_Bs instead. 2358 * 2359 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2360 */ 2361 /* op vAA, vBB, vCC */ 2362 FETCH_B(r2, 1, 0) @ r2<- BB 2363 mov r9, rINST, lsr #8 @ r9<- AA 2364 FETCH_B(r3, 1, 1) @ r3<- CC 2365 GET_VREG(r0, r2) @ r0<- vBB (array object) 2366 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2367 cmp r0, #0 @ null array object? 2368 beq common_errNullObject @ yes, bail 2369 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2370 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2371 cmp r1, r3 @ compare unsigned index, length 2372 bcs common_errArrayIndex @ index >= length, bail 2373 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2374 GET_VREG(r2, r9) @ r2<- vAA 2375 GET_INST_OPCODE(ip) @ extract opcode from rINST 2376 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2377 GOTO_OPCODE(ip) @ jump to next instruction 2378 2379 2380/* ------------------------------ */ 2381 .balign 64 2382.L_OP_IGET: /* 0x52 */ 2383/* File: armv5te/OP_IGET.S */ 2384 /* 2385 * General 32-bit instance field get. 2386 * 2387 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2388 */ 2389 /* op vA, vB, field@CCCC */ 2390 mov r0, rINST, lsr #12 @ r0<- B 2391 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2392 FETCH(r1, 1) @ r1<- field ref CCCC 2393 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2394 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2395 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2396 cmp r0, #0 @ is resolved entry null? 2397 bne .LOP_IGET_finish @ no, already resolved 23988: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2399 EXPORT_PC() @ resolve() could throw 2400 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2401 bl dvmResolveInstField @ r0<- resolved InstField ptr 2402 cmp r0, #0 2403 bne .LOP_IGET_finish 2404 b common_exceptionThrown 2405 2406/* ------------------------------ */ 2407 .balign 64 2408.L_OP_IGET_WIDE: /* 0x53 */ 2409/* File: armv5te/OP_IGET_WIDE.S */ 2410 /* 2411 * Wide 32-bit instance field get. 2412 */ 2413 /* iget-wide vA, vB, field@CCCC */ 2414 mov r0, rINST, lsr #12 @ r0<- B 2415 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2416 FETCH(r1, 1) @ r1<- field ref CCCC 2417 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2418 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2419 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2420 cmp r0, #0 @ is resolved entry null? 2421 bne .LOP_IGET_WIDE_finish @ no, already resolved 24228: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2423 EXPORT_PC() @ resolve() could throw 2424 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2425 bl dvmResolveInstField @ r0<- resolved InstField ptr 2426 cmp r0, #0 2427 bne .LOP_IGET_WIDE_finish 2428 b common_exceptionThrown 2429 2430/* ------------------------------ */ 2431 .balign 64 2432.L_OP_IGET_OBJECT: /* 0x54 */ 2433/* File: armv5te/OP_IGET_OBJECT.S */ 2434/* File: armv5te/OP_IGET.S */ 2435 /* 2436 * General 32-bit instance field get. 2437 * 2438 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2439 */ 2440 /* op vA, vB, field@CCCC */ 2441 mov r0, rINST, lsr #12 @ r0<- B 2442 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2443 FETCH(r1, 1) @ r1<- field ref CCCC 2444 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2445 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2446 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2447 cmp r0, #0 @ is resolved entry null? 2448 bne .LOP_IGET_OBJECT_finish @ no, already resolved 24498: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2450 EXPORT_PC() @ resolve() could throw 2451 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2452 bl dvmResolveInstField @ r0<- resolved InstField ptr 2453 cmp r0, #0 2454 bne .LOP_IGET_OBJECT_finish 2455 b common_exceptionThrown 2456 2457 2458/* ------------------------------ */ 2459 .balign 64 2460.L_OP_IGET_BOOLEAN: /* 0x55 */ 2461/* File: armv5te/OP_IGET_BOOLEAN.S */ 2462@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2463/* File: armv5te/OP_IGET.S */ 2464 /* 2465 * General 32-bit instance field get. 2466 * 2467 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2468 */ 2469 /* op vA, vB, field@CCCC */ 2470 mov r0, rINST, lsr #12 @ r0<- B 2471 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2472 FETCH(r1, 1) @ r1<- field ref CCCC 2473 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2474 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2475 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2476 cmp r0, #0 @ is resolved entry null? 2477 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 24788: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2479 EXPORT_PC() @ resolve() could throw 2480 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2481 bl dvmResolveInstField @ r0<- resolved InstField ptr 2482 cmp r0, #0 2483 bne .LOP_IGET_BOOLEAN_finish 2484 b common_exceptionThrown 2485 2486 2487/* ------------------------------ */ 2488 .balign 64 2489.L_OP_IGET_BYTE: /* 0x56 */ 2490/* File: armv5te/OP_IGET_BYTE.S */ 2491@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2492/* File: armv5te/OP_IGET.S */ 2493 /* 2494 * General 32-bit instance field get. 2495 * 2496 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2497 */ 2498 /* op vA, vB, field@CCCC */ 2499 mov r0, rINST, lsr #12 @ r0<- B 2500 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2501 FETCH(r1, 1) @ r1<- field ref CCCC 2502 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2503 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2504 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2505 cmp r0, #0 @ is resolved entry null? 2506 bne .LOP_IGET_BYTE_finish @ no, already resolved 25078: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2508 EXPORT_PC() @ resolve() could throw 2509 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2510 bl dvmResolveInstField @ r0<- resolved InstField ptr 2511 cmp r0, #0 2512 bne .LOP_IGET_BYTE_finish 2513 b common_exceptionThrown 2514 2515 2516/* ------------------------------ */ 2517 .balign 64 2518.L_OP_IGET_CHAR: /* 0x57 */ 2519/* File: armv5te/OP_IGET_CHAR.S */ 2520@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2521/* File: armv5te/OP_IGET.S */ 2522 /* 2523 * General 32-bit instance field get. 2524 * 2525 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2526 */ 2527 /* op vA, vB, field@CCCC */ 2528 mov r0, rINST, lsr #12 @ r0<- B 2529 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2530 FETCH(r1, 1) @ r1<- field ref CCCC 2531 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2532 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2533 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2534 cmp r0, #0 @ is resolved entry null? 2535 bne .LOP_IGET_CHAR_finish @ no, already resolved 25368: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2537 EXPORT_PC() @ resolve() could throw 2538 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2539 bl dvmResolveInstField @ r0<- resolved InstField ptr 2540 cmp r0, #0 2541 bne .LOP_IGET_CHAR_finish 2542 b common_exceptionThrown 2543 2544 2545/* ------------------------------ */ 2546 .balign 64 2547.L_OP_IGET_SHORT: /* 0x58 */ 2548/* File: armv5te/OP_IGET_SHORT.S */ 2549@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2550/* File: armv5te/OP_IGET.S */ 2551 /* 2552 * General 32-bit instance field get. 2553 * 2554 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2555 */ 2556 /* op vA, vB, field@CCCC */ 2557 mov r0, rINST, lsr #12 @ r0<- B 2558 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2559 FETCH(r1, 1) @ r1<- field ref CCCC 2560 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2561 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2562 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2563 cmp r0, #0 @ is resolved entry null? 2564 bne .LOP_IGET_SHORT_finish @ no, already resolved 25658: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2566 EXPORT_PC() @ resolve() could throw 2567 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2568 bl dvmResolveInstField @ r0<- resolved InstField ptr 2569 cmp r0, #0 2570 bne .LOP_IGET_SHORT_finish 2571 b common_exceptionThrown 2572 2573 2574/* ------------------------------ */ 2575 .balign 64 2576.L_OP_IPUT: /* 0x59 */ 2577/* File: armv5te/OP_IPUT.S */ 2578 /* 2579 * General 32-bit instance field put. 2580 * 2581 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2582 */ 2583 /* op vA, vB, field@CCCC */ 2584 mov r0, rINST, lsr #12 @ r0<- B 2585 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2586 FETCH(r1, 1) @ r1<- field ref CCCC 2587 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2588 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2589 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2590 cmp r0, #0 @ is resolved entry null? 2591 bne .LOP_IPUT_finish @ no, already resolved 25928: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2593 EXPORT_PC() @ resolve() could throw 2594 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2595 bl dvmResolveInstField @ r0<- resolved InstField ptr 2596 cmp r0, #0 @ success? 2597 bne .LOP_IPUT_finish @ yes, finish up 2598 b common_exceptionThrown 2599 2600/* ------------------------------ */ 2601 .balign 64 2602.L_OP_IPUT_WIDE: /* 0x5a */ 2603/* File: armv5te/OP_IPUT_WIDE.S */ 2604 /* iput-wide vA, vB, field@CCCC */ 2605 mov r0, rINST, lsr #12 @ r0<- B 2606 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2607 FETCH(r1, 1) @ r1<- field ref CCCC 2608 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2609 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2610 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2611 cmp r0, #0 @ is resolved entry null? 2612 bne .LOP_IPUT_WIDE_finish @ no, already resolved 26138: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2614 EXPORT_PC() @ resolve() could throw 2615 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2616 bl dvmResolveInstField @ r0<- resolved InstField ptr 2617 cmp r0, #0 @ success? 2618 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2619 b common_exceptionThrown 2620 2621/* ------------------------------ */ 2622 .balign 64 2623.L_OP_IPUT_OBJECT: /* 0x5b */ 2624/* File: armv5te/OP_IPUT_OBJECT.S */ 2625 /* 2626 * 32-bit instance field put. 2627 * 2628 * for: iput-object, iput-object-volatile 2629 */ 2630 /* op vA, vB, field@CCCC */ 2631 mov r0, rINST, lsr #12 @ r0<- B 2632 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2633 FETCH(r1, 1) @ r1<- field ref CCCC 2634 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2635 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2636 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2637 cmp r0, #0 @ is resolved entry null? 2638 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 26398: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2640 EXPORT_PC() @ resolve() could throw 2641 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2642 bl dvmResolveInstField @ r0<- resolved InstField ptr 2643 cmp r0, #0 @ success? 2644 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2645 b common_exceptionThrown 2646 2647/* ------------------------------ */ 2648 .balign 64 2649.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2650/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2651@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2652/* File: armv5te/OP_IPUT.S */ 2653 /* 2654 * General 32-bit instance field put. 2655 * 2656 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2657 */ 2658 /* op vA, vB, field@CCCC */ 2659 mov r0, rINST, lsr #12 @ r0<- B 2660 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2661 FETCH(r1, 1) @ r1<- field ref CCCC 2662 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2663 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2664 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2665 cmp r0, #0 @ is resolved entry null? 2666 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 26678: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2668 EXPORT_PC() @ resolve() could throw 2669 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2670 bl dvmResolveInstField @ r0<- resolved InstField ptr 2671 cmp r0, #0 @ success? 2672 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2673 b common_exceptionThrown 2674 2675 2676/* ------------------------------ */ 2677 .balign 64 2678.L_OP_IPUT_BYTE: /* 0x5d */ 2679/* File: armv5te/OP_IPUT_BYTE.S */ 2680@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2681/* File: armv5te/OP_IPUT.S */ 2682 /* 2683 * General 32-bit instance field put. 2684 * 2685 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2686 */ 2687 /* op vA, vB, field@CCCC */ 2688 mov r0, rINST, lsr #12 @ r0<- B 2689 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2690 FETCH(r1, 1) @ r1<- field ref CCCC 2691 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2692 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2693 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2694 cmp r0, #0 @ is resolved entry null? 2695 bne .LOP_IPUT_BYTE_finish @ no, already resolved 26968: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2697 EXPORT_PC() @ resolve() could throw 2698 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2699 bl dvmResolveInstField @ r0<- resolved InstField ptr 2700 cmp r0, #0 @ success? 2701 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2702 b common_exceptionThrown 2703 2704 2705/* ------------------------------ */ 2706 .balign 64 2707.L_OP_IPUT_CHAR: /* 0x5e */ 2708/* File: armv5te/OP_IPUT_CHAR.S */ 2709@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2710/* File: armv5te/OP_IPUT.S */ 2711 /* 2712 * General 32-bit instance field put. 2713 * 2714 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2715 */ 2716 /* op vA, vB, field@CCCC */ 2717 mov r0, rINST, lsr #12 @ r0<- B 2718 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2719 FETCH(r1, 1) @ r1<- field ref CCCC 2720 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2721 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2722 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2723 cmp r0, #0 @ is resolved entry null? 2724 bne .LOP_IPUT_CHAR_finish @ no, already resolved 27258: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2726 EXPORT_PC() @ resolve() could throw 2727 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2728 bl dvmResolveInstField @ r0<- resolved InstField ptr 2729 cmp r0, #0 @ success? 2730 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2731 b common_exceptionThrown 2732 2733 2734/* ------------------------------ */ 2735 .balign 64 2736.L_OP_IPUT_SHORT: /* 0x5f */ 2737/* File: armv5te/OP_IPUT_SHORT.S */ 2738@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2739/* File: armv5te/OP_IPUT.S */ 2740 /* 2741 * General 32-bit instance field put. 2742 * 2743 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2744 */ 2745 /* op vA, vB, field@CCCC */ 2746 mov r0, rINST, lsr #12 @ r0<- B 2747 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2748 FETCH(r1, 1) @ r1<- field ref CCCC 2749 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2750 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2751 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2752 cmp r0, #0 @ is resolved entry null? 2753 bne .LOP_IPUT_SHORT_finish @ no, already resolved 27548: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2755 EXPORT_PC() @ resolve() could throw 2756 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2757 bl dvmResolveInstField @ r0<- resolved InstField ptr 2758 cmp r0, #0 @ success? 2759 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2760 b common_exceptionThrown 2761 2762 2763/* ------------------------------ */ 2764 .balign 64 2765.L_OP_SGET: /* 0x60 */ 2766/* File: armv5te/OP_SGET.S */ 2767 /* 2768 * General 32-bit SGET handler. 2769 * 2770 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2771 */ 2772 /* op vAA, field@BBBB */ 2773 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2774 FETCH(r1, 1) @ r1<- field ref BBBB 2775 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2776 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2777 cmp r0, #0 @ is resolved entry null? 2778 beq .LOP_SGET_resolve @ yes, do resolve 2779.LOP_SGET_finish: @ field ptr in r0 2780 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2781 @ no-op @ acquiring load 2782 mov r2, rINST, lsr #8 @ r2<- AA 2783 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2784 SET_VREG(r1, r2) @ fp[AA]<- r1 2785 GET_INST_OPCODE(ip) @ extract opcode from rINST 2786 GOTO_OPCODE(ip) @ jump to next instruction 2787 2788/* ------------------------------ */ 2789 .balign 64 2790.L_OP_SGET_WIDE: /* 0x61 */ 2791/* File: armv5te/OP_SGET_WIDE.S */ 2792 /* 2793 * 64-bit SGET handler. 2794 */ 2795 /* sget-wide vAA, field@BBBB */ 2796 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2797 FETCH(r1, 1) @ r1<- field ref BBBB 2798 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2799 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2800 cmp r0, #0 @ is resolved entry null? 2801 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2802.LOP_SGET_WIDE_finish: 2803 mov r9, rINST, lsr #8 @ r9<- AA 2804 .if 0 2805 add r0, r0, #offStaticField_value @ r0<- pointer to data 2806 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 2807 .else 2808 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 2809 .endif 2810 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2811 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2812 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 2813 GET_INST_OPCODE(ip) @ extract opcode from rINST 2814 GOTO_OPCODE(ip) @ jump to next instruction 2815 2816/* ------------------------------ */ 2817 .balign 64 2818.L_OP_SGET_OBJECT: /* 0x62 */ 2819/* File: armv5te/OP_SGET_OBJECT.S */ 2820/* File: armv5te/OP_SGET.S */ 2821 /* 2822 * General 32-bit SGET handler. 2823 * 2824 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2825 */ 2826 /* op vAA, field@BBBB */ 2827 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2828 FETCH(r1, 1) @ r1<- field ref BBBB 2829 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2830 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2831 cmp r0, #0 @ is resolved entry null? 2832 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2833.LOP_SGET_OBJECT_finish: @ field ptr in r0 2834 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2835 @ no-op @ acquiring load 2836 mov r2, rINST, lsr #8 @ r2<- AA 2837 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2838 SET_VREG(r1, r2) @ fp[AA]<- r1 2839 GET_INST_OPCODE(ip) @ extract opcode from rINST 2840 GOTO_OPCODE(ip) @ jump to next instruction 2841 2842 2843/* ------------------------------ */ 2844 .balign 64 2845.L_OP_SGET_BOOLEAN: /* 0x63 */ 2846/* File: armv5te/OP_SGET_BOOLEAN.S */ 2847/* File: armv5te/OP_SGET.S */ 2848 /* 2849 * General 32-bit SGET handler. 2850 * 2851 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2852 */ 2853 /* op vAA, field@BBBB */ 2854 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2855 FETCH(r1, 1) @ r1<- field ref BBBB 2856 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2857 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2858 cmp r0, #0 @ is resolved entry null? 2859 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2860.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2861 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2862 @ no-op @ acquiring load 2863 mov r2, rINST, lsr #8 @ r2<- AA 2864 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2865 SET_VREG(r1, r2) @ fp[AA]<- r1 2866 GET_INST_OPCODE(ip) @ extract opcode from rINST 2867 GOTO_OPCODE(ip) @ jump to next instruction 2868 2869 2870/* ------------------------------ */ 2871 .balign 64 2872.L_OP_SGET_BYTE: /* 0x64 */ 2873/* File: armv5te/OP_SGET_BYTE.S */ 2874/* File: armv5te/OP_SGET.S */ 2875 /* 2876 * General 32-bit SGET handler. 2877 * 2878 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2879 */ 2880 /* op vAA, field@BBBB */ 2881 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2882 FETCH(r1, 1) @ r1<- field ref BBBB 2883 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2884 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2885 cmp r0, #0 @ is resolved entry null? 2886 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2887.LOP_SGET_BYTE_finish: @ field ptr in r0 2888 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2889 @ no-op @ acquiring load 2890 mov r2, rINST, lsr #8 @ r2<- AA 2891 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2892 SET_VREG(r1, r2) @ fp[AA]<- r1 2893 GET_INST_OPCODE(ip) @ extract opcode from rINST 2894 GOTO_OPCODE(ip) @ jump to next instruction 2895 2896 2897/* ------------------------------ */ 2898 .balign 64 2899.L_OP_SGET_CHAR: /* 0x65 */ 2900/* File: armv5te/OP_SGET_CHAR.S */ 2901/* File: armv5te/OP_SGET.S */ 2902 /* 2903 * General 32-bit SGET handler. 2904 * 2905 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2906 */ 2907 /* op vAA, field@BBBB */ 2908 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2909 FETCH(r1, 1) @ r1<- field ref BBBB 2910 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2911 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2912 cmp r0, #0 @ is resolved entry null? 2913 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2914.LOP_SGET_CHAR_finish: @ field ptr in r0 2915 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2916 @ no-op @ acquiring load 2917 mov r2, rINST, lsr #8 @ r2<- AA 2918 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2919 SET_VREG(r1, r2) @ fp[AA]<- r1 2920 GET_INST_OPCODE(ip) @ extract opcode from rINST 2921 GOTO_OPCODE(ip) @ jump to next instruction 2922 2923 2924/* ------------------------------ */ 2925 .balign 64 2926.L_OP_SGET_SHORT: /* 0x66 */ 2927/* File: armv5te/OP_SGET_SHORT.S */ 2928/* File: armv5te/OP_SGET.S */ 2929 /* 2930 * General 32-bit SGET handler. 2931 * 2932 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2933 */ 2934 /* op vAA, field@BBBB */ 2935 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2936 FETCH(r1, 1) @ r1<- field ref BBBB 2937 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2938 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2939 cmp r0, #0 @ is resolved entry null? 2940 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 2941.LOP_SGET_SHORT_finish: @ field ptr in r0 2942 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2943 @ no-op @ acquiring load 2944 mov r2, rINST, lsr #8 @ r2<- AA 2945 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2946 SET_VREG(r1, r2) @ fp[AA]<- r1 2947 GET_INST_OPCODE(ip) @ extract opcode from rINST 2948 GOTO_OPCODE(ip) @ jump to next instruction 2949 2950 2951/* ------------------------------ */ 2952 .balign 64 2953.L_OP_SPUT: /* 0x67 */ 2954/* File: armv5te/OP_SPUT.S */ 2955 /* 2956 * General 32-bit SPUT handler. 2957 * 2958 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 2959 */ 2960 /* op vAA, field@BBBB */ 2961 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2962 FETCH(r1, 1) @ r1<- field ref BBBB 2963 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2964 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2965 cmp r0, #0 @ is resolved entry null? 2966 beq .LOP_SPUT_resolve @ yes, do resolve 2967.LOP_SPUT_finish: @ field ptr in r0 2968 mov r2, rINST, lsr #8 @ r2<- AA 2969 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2970 GET_VREG(r1, r2) @ r1<- fp[AA] 2971 GET_INST_OPCODE(ip) @ extract opcode from rINST 2972 @ no-op @ releasing store 2973 str r1, [r0, #offStaticField_value] @ field<- vAA 2974 GOTO_OPCODE(ip) @ jump to next instruction 2975 2976/* ------------------------------ */ 2977 .balign 64 2978.L_OP_SPUT_WIDE: /* 0x68 */ 2979/* File: armv5te/OP_SPUT_WIDE.S */ 2980 /* 2981 * 64-bit SPUT handler. 2982 */ 2983 /* sput-wide vAA, field@BBBB */ 2984 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 2985 FETCH(r1, 1) @ r1<- field ref BBBB 2986 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 2987 mov r9, rINST, lsr #8 @ r9<- AA 2988 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 2989 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2990 cmp r2, #0 @ is resolved entry null? 2991 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 2992.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9 2993 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2994 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 2995 GET_INST_OPCODE(r10) @ extract opcode from rINST 2996 .if 0 2997 add r2, r2, #offStaticField_value @ r2<- pointer to data 2998 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 2999 .else 3000 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 3001 .endif 3002 GOTO_OPCODE(r10) @ jump to next instruction 3003 3004/* ------------------------------ */ 3005 .balign 64 3006.L_OP_SPUT_OBJECT: /* 0x69 */ 3007/* File: armv5te/OP_SPUT_OBJECT.S */ 3008 /* 3009 * 32-bit SPUT handler for objects 3010 * 3011 * for: sput-object, sput-object-volatile 3012 */ 3013 /* op vAA, field@BBBB */ 3014 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3015 FETCH(r1, 1) @ r1<- field ref BBBB 3016 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3017 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3018 cmp r0, #0 @ is resolved entry null? 3019 bne .LOP_SPUT_OBJECT_finish @ no, continue 3020 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3021 EXPORT_PC() @ resolve() could throw, so export now 3022 ldr r0, [r9, #offMethod_clazz] @ r0<- method->clazz 3023 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 3024 cmp r0, #0 @ success? 3025 bne .LOP_SPUT_OBJECT_finish @ yes, finish 3026 b common_exceptionThrown @ no, handle exception 3027 3028 3029/* ------------------------------ */ 3030 .balign 64 3031.L_OP_SPUT_BOOLEAN: /* 0x6a */ 3032/* File: armv5te/OP_SPUT_BOOLEAN.S */ 3033/* File: armv5te/OP_SPUT.S */ 3034 /* 3035 * General 32-bit SPUT handler. 3036 * 3037 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3038 */ 3039 /* op vAA, field@BBBB */ 3040 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3041 FETCH(r1, 1) @ r1<- field ref BBBB 3042 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3043 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3044 cmp r0, #0 @ is resolved entry null? 3045 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 3046.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 3047 mov r2, rINST, lsr #8 @ r2<- AA 3048 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3049 GET_VREG(r1, r2) @ r1<- fp[AA] 3050 GET_INST_OPCODE(ip) @ extract opcode from rINST 3051 @ no-op @ releasing store 3052 str r1, [r0, #offStaticField_value] @ field<- vAA 3053 GOTO_OPCODE(ip) @ jump to next instruction 3054 3055 3056/* ------------------------------ */ 3057 .balign 64 3058.L_OP_SPUT_BYTE: /* 0x6b */ 3059/* File: armv5te/OP_SPUT_BYTE.S */ 3060/* File: armv5te/OP_SPUT.S */ 3061 /* 3062 * General 32-bit SPUT handler. 3063 * 3064 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3065 */ 3066 /* op vAA, field@BBBB */ 3067 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3068 FETCH(r1, 1) @ r1<- field ref BBBB 3069 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3070 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3071 cmp r0, #0 @ is resolved entry null? 3072 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 3073.LOP_SPUT_BYTE_finish: @ field ptr in r0 3074 mov r2, rINST, lsr #8 @ r2<- AA 3075 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3076 GET_VREG(r1, r2) @ r1<- fp[AA] 3077 GET_INST_OPCODE(ip) @ extract opcode from rINST 3078 @ no-op @ releasing store 3079 str r1, [r0, #offStaticField_value] @ field<- vAA 3080 GOTO_OPCODE(ip) @ jump to next instruction 3081 3082 3083/* ------------------------------ */ 3084 .balign 64 3085.L_OP_SPUT_CHAR: /* 0x6c */ 3086/* File: armv5te/OP_SPUT_CHAR.S */ 3087/* File: armv5te/OP_SPUT.S */ 3088 /* 3089 * General 32-bit SPUT handler. 3090 * 3091 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3092 */ 3093 /* op vAA, field@BBBB */ 3094 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3095 FETCH(r1, 1) @ r1<- field ref BBBB 3096 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3097 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3098 cmp r0, #0 @ is resolved entry null? 3099 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 3100.LOP_SPUT_CHAR_finish: @ field ptr in r0 3101 mov r2, rINST, lsr #8 @ r2<- AA 3102 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3103 GET_VREG(r1, r2) @ r1<- fp[AA] 3104 GET_INST_OPCODE(ip) @ extract opcode from rINST 3105 @ no-op @ releasing store 3106 str r1, [r0, #offStaticField_value] @ field<- vAA 3107 GOTO_OPCODE(ip) @ jump to next instruction 3108 3109 3110/* ------------------------------ */ 3111 .balign 64 3112.L_OP_SPUT_SHORT: /* 0x6d */ 3113/* File: armv5te/OP_SPUT_SHORT.S */ 3114/* File: armv5te/OP_SPUT.S */ 3115 /* 3116 * General 32-bit SPUT handler. 3117 * 3118 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3119 */ 3120 /* op vAA, field@BBBB */ 3121 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3122 FETCH(r1, 1) @ r1<- field ref BBBB 3123 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3124 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3125 cmp r0, #0 @ is resolved entry null? 3126 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 3127.LOP_SPUT_SHORT_finish: @ field ptr in r0 3128 mov r2, rINST, lsr #8 @ r2<- AA 3129 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3130 GET_VREG(r1, r2) @ r1<- fp[AA] 3131 GET_INST_OPCODE(ip) @ extract opcode from rINST 3132 @ no-op @ releasing store 3133 str r1, [r0, #offStaticField_value] @ field<- vAA 3134 GOTO_OPCODE(ip) @ jump to next instruction 3135 3136 3137/* ------------------------------ */ 3138 .balign 64 3139.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3140/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3141 /* 3142 * Handle a virtual method call. 3143 * 3144 * for: invoke-virtual, invoke-virtual/range 3145 */ 3146 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3147 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3148 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3149 FETCH(r1, 1) @ r1<- BBBB 3150 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3151 FETCH(r10, 2) @ r10<- GFED or CCCC 3152 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3153 .if (!0) 3154 and r10, r10, #15 @ r10<- D (or stays CCCC) 3155 .endif 3156 cmp r0, #0 @ already resolved? 3157 EXPORT_PC() @ must export for invoke 3158 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3159 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3160 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3161 mov r2, #METHOD_VIRTUAL @ resolver method type 3162 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3163 cmp r0, #0 @ got null? 3164 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3165 b common_exceptionThrown @ yes, handle exception 3166 3167/* ------------------------------ */ 3168 .balign 64 3169.L_OP_INVOKE_SUPER: /* 0x6f */ 3170/* File: armv5te/OP_INVOKE_SUPER.S */ 3171 /* 3172 * Handle a "super" method call. 3173 * 3174 * for: invoke-super, invoke-super/range 3175 */ 3176 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3177 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3178 FETCH(r10, 2) @ r10<- GFED or CCCC 3179 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3180 .if (!0) 3181 and r10, r10, #15 @ r10<- D (or stays CCCC) 3182 .endif 3183 FETCH(r1, 1) @ r1<- BBBB 3184 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3185 GET_VREG(r2, r10) @ r2<- "this" ptr 3186 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3187 cmp r2, #0 @ null "this"? 3188 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3189 beq common_errNullObject @ null "this", throw exception 3190 cmp r0, #0 @ already resolved? 3191 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3192 EXPORT_PC() @ must export for invoke 3193 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3194 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3195 3196/* ------------------------------ */ 3197 .balign 64 3198.L_OP_INVOKE_DIRECT: /* 0x70 */ 3199/* File: armv5te/OP_INVOKE_DIRECT.S */ 3200 /* 3201 * Handle a direct method call. 3202 * 3203 * (We could defer the "is 'this' pointer null" test to the common 3204 * method invocation code, and use a flag to indicate that static 3205 * calls don't count. If we do this as part of copying the arguments 3206 * out we could avoiding loading the first arg twice.) 3207 * 3208 * for: invoke-direct, invoke-direct/range 3209 */ 3210 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3211 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3212 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3213 FETCH(r1, 1) @ r1<- BBBB 3214 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3215 FETCH(r10, 2) @ r10<- GFED or CCCC 3216 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3217 .if (!0) 3218 and r10, r10, #15 @ r10<- D (or stays CCCC) 3219 .endif 3220 cmp r0, #0 @ already resolved? 3221 EXPORT_PC() @ must export for invoke 3222 GET_VREG(r2, r10) @ r2<- "this" ptr 3223 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3224.LOP_INVOKE_DIRECT_finish: 3225 cmp r2, #0 @ null "this" ref? 3226 bne common_invokeMethodNoRange @ no, continue on 3227 b common_errNullObject @ yes, throw exception 3228 3229/* ------------------------------ */ 3230 .balign 64 3231.L_OP_INVOKE_STATIC: /* 0x71 */ 3232/* File: armv5te/OP_INVOKE_STATIC.S */ 3233 /* 3234 * Handle a static method call. 3235 * 3236 * for: invoke-static, invoke-static/range 3237 */ 3238 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3239 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3240 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3241 FETCH(r1, 1) @ r1<- BBBB 3242 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3243 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3244 cmp r0, #0 @ already resolved? 3245 EXPORT_PC() @ must export for invoke 3246 bne common_invokeMethodNoRange @ yes, continue on 32470: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3248 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3249 mov r2, #METHOD_STATIC @ resolver method type 3250 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3251 cmp r0, #0 @ got null? 3252 bne common_invokeMethodNoRange @ no, continue 3253 b common_exceptionThrown @ yes, handle exception 3254 3255/* ------------------------------ */ 3256 .balign 64 3257.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3258/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3259 /* 3260 * Handle an interface method call. 3261 * 3262 * for: invoke-interface, invoke-interface/range 3263 */ 3264 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3265 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3266 FETCH(r2, 2) @ r2<- FEDC or CCCC 3267 FETCH(r1, 1) @ r1<- BBBB 3268 .if (!0) 3269 and r2, r2, #15 @ r2<- C (or stays CCCC) 3270 .endif 3271 EXPORT_PC() @ must export for invoke 3272 GET_VREG(r0, r2) @ r0<- first arg ("this") 3273 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3274 cmp r0, #0 @ null obj? 3275 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3276 beq common_errNullObject @ yes, fail 3277 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3278 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3279 cmp r0, #0 @ failed? 3280 beq common_exceptionThrown @ yes, handle exception 3281 b common_invokeMethodNoRange @ jump to common handler 3282 3283/* ------------------------------ */ 3284 .balign 64 3285.L_OP_UNUSED_73: /* 0x73 */ 3286/* File: armv5te/OP_UNUSED_73.S */ 3287/* File: armv5te/unused.S */ 3288 bl common_abort 3289 3290 3291/* ------------------------------ */ 3292 .balign 64 3293.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3294/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3295/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3296 /* 3297 * Handle a virtual method call. 3298 * 3299 * for: invoke-virtual, invoke-virtual/range 3300 */ 3301 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3302 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3303 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3304 FETCH(r1, 1) @ r1<- BBBB 3305 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3306 FETCH(r10, 2) @ r10<- GFED or CCCC 3307 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3308 .if (!1) 3309 and r10, r10, #15 @ r10<- D (or stays CCCC) 3310 .endif 3311 cmp r0, #0 @ already resolved? 3312 EXPORT_PC() @ must export for invoke 3313 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3314 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3315 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3316 mov r2, #METHOD_VIRTUAL @ resolver method type 3317 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3318 cmp r0, #0 @ got null? 3319 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3320 b common_exceptionThrown @ yes, handle exception 3321 3322 3323/* ------------------------------ */ 3324 .balign 64 3325.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3326/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3327/* File: armv5te/OP_INVOKE_SUPER.S */ 3328 /* 3329 * Handle a "super" method call. 3330 * 3331 * for: invoke-super, invoke-super/range 3332 */ 3333 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3334 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3335 FETCH(r10, 2) @ r10<- GFED or CCCC 3336 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3337 .if (!1) 3338 and r10, r10, #15 @ r10<- D (or stays CCCC) 3339 .endif 3340 FETCH(r1, 1) @ r1<- BBBB 3341 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3342 GET_VREG(r2, r10) @ r2<- "this" ptr 3343 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3344 cmp r2, #0 @ null "this"? 3345 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3346 beq common_errNullObject @ null "this", throw exception 3347 cmp r0, #0 @ already resolved? 3348 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3349 EXPORT_PC() @ must export for invoke 3350 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3351 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3352 3353 3354/* ------------------------------ */ 3355 .balign 64 3356.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3357/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3358/* File: armv5te/OP_INVOKE_DIRECT.S */ 3359 /* 3360 * Handle a direct method call. 3361 * 3362 * (We could defer the "is 'this' pointer null" test to the common 3363 * method invocation code, and use a flag to indicate that static 3364 * calls don't count. If we do this as part of copying the arguments 3365 * out we could avoiding loading the first arg twice.) 3366 * 3367 * for: invoke-direct, invoke-direct/range 3368 */ 3369 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3370 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3371 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3372 FETCH(r1, 1) @ r1<- BBBB 3373 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3374 FETCH(r10, 2) @ r10<- GFED or CCCC 3375 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3376 .if (!1) 3377 and r10, r10, #15 @ r10<- D (or stays CCCC) 3378 .endif 3379 cmp r0, #0 @ already resolved? 3380 EXPORT_PC() @ must export for invoke 3381 GET_VREG(r2, r10) @ r2<- "this" ptr 3382 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3383.LOP_INVOKE_DIRECT_RANGE_finish: 3384 cmp r2, #0 @ null "this" ref? 3385 bne common_invokeMethodRange @ no, continue on 3386 b common_errNullObject @ yes, throw exception 3387 3388 3389/* ------------------------------ */ 3390 .balign 64 3391.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3392/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3393/* File: armv5te/OP_INVOKE_STATIC.S */ 3394 /* 3395 * Handle a static method call. 3396 * 3397 * for: invoke-static, invoke-static/range 3398 */ 3399 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3400 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3401 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3402 FETCH(r1, 1) @ r1<- BBBB 3403 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3404 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3405 cmp r0, #0 @ already resolved? 3406 EXPORT_PC() @ must export for invoke 3407 bne common_invokeMethodRange @ yes, continue on 34080: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3409 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3410 mov r2, #METHOD_STATIC @ resolver method type 3411 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3412 cmp r0, #0 @ got null? 3413 bne common_invokeMethodRange @ no, continue 3414 b common_exceptionThrown @ yes, handle exception 3415 3416 3417/* ------------------------------ */ 3418 .balign 64 3419.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3420/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3421/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3422 /* 3423 * Handle an interface method call. 3424 * 3425 * for: invoke-interface, invoke-interface/range 3426 */ 3427 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3428 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3429 FETCH(r2, 2) @ r2<- FEDC or CCCC 3430 FETCH(r1, 1) @ r1<- BBBB 3431 .if (!1) 3432 and r2, r2, #15 @ r2<- C (or stays CCCC) 3433 .endif 3434 EXPORT_PC() @ must export for invoke 3435 GET_VREG(r0, r2) @ r0<- first arg ("this") 3436 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3437 cmp r0, #0 @ null obj? 3438 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3439 beq common_errNullObject @ yes, fail 3440 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3441 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3442 cmp r0, #0 @ failed? 3443 beq common_exceptionThrown @ yes, handle exception 3444 b common_invokeMethodRange @ jump to common handler 3445 3446 3447/* ------------------------------ */ 3448 .balign 64 3449.L_OP_UNUSED_79: /* 0x79 */ 3450/* File: armv5te/OP_UNUSED_79.S */ 3451/* File: armv5te/unused.S */ 3452 bl common_abort 3453 3454 3455/* ------------------------------ */ 3456 .balign 64 3457.L_OP_UNUSED_7A: /* 0x7a */ 3458/* File: armv5te/OP_UNUSED_7A.S */ 3459/* File: armv5te/unused.S */ 3460 bl common_abort 3461 3462 3463/* ------------------------------ */ 3464 .balign 64 3465.L_OP_NEG_INT: /* 0x7b */ 3466/* File: armv5te/OP_NEG_INT.S */ 3467/* File: armv5te/unop.S */ 3468 /* 3469 * Generic 32-bit unary operation. Provide an "instr" line that 3470 * specifies an instruction that performs "result = op r0". 3471 * This could be an ARM instruction or a function call. 3472 * 3473 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3474 * int-to-byte, int-to-char, int-to-short 3475 */ 3476 /* unop vA, vB */ 3477 mov r3, rINST, lsr #12 @ r3<- B 3478 mov r9, rINST, lsr #8 @ r9<- A+ 3479 GET_VREG(r0, r3) @ r0<- vB 3480 and r9, r9, #15 3481 @ optional op; may set condition codes 3482 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3483 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3484 GET_INST_OPCODE(ip) @ extract opcode from rINST 3485 SET_VREG(r0, r9) @ vAA<- r0 3486 GOTO_OPCODE(ip) @ jump to next instruction 3487 /* 9-10 instructions */ 3488 3489 3490/* ------------------------------ */ 3491 .balign 64 3492.L_OP_NOT_INT: /* 0x7c */ 3493/* File: armv5te/OP_NOT_INT.S */ 3494/* File: armv5te/unop.S */ 3495 /* 3496 * Generic 32-bit unary operation. Provide an "instr" line that 3497 * specifies an instruction that performs "result = op r0". 3498 * This could be an ARM instruction or a function call. 3499 * 3500 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3501 * int-to-byte, int-to-char, int-to-short 3502 */ 3503 /* unop vA, vB */ 3504 mov r3, rINST, lsr #12 @ r3<- B 3505 mov r9, rINST, lsr #8 @ r9<- A+ 3506 GET_VREG(r0, r3) @ r0<- vB 3507 and r9, r9, #15 3508 @ optional op; may set condition codes 3509 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3510 mvn r0, r0 @ r0<- op, r0-r3 changed 3511 GET_INST_OPCODE(ip) @ extract opcode from rINST 3512 SET_VREG(r0, r9) @ vAA<- r0 3513 GOTO_OPCODE(ip) @ jump to next instruction 3514 /* 9-10 instructions */ 3515 3516 3517/* ------------------------------ */ 3518 .balign 64 3519.L_OP_NEG_LONG: /* 0x7d */ 3520/* File: armv5te/OP_NEG_LONG.S */ 3521/* File: armv5te/unopWide.S */ 3522 /* 3523 * Generic 64-bit unary operation. Provide an "instr" line that 3524 * specifies an instruction that performs "result = op r0/r1". 3525 * This could be an ARM instruction or a function call. 3526 * 3527 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3528 */ 3529 /* unop vA, vB */ 3530 mov r9, rINST, lsr #8 @ r9<- A+ 3531 mov r3, rINST, lsr #12 @ r3<- B 3532 and r9, r9, #15 3533 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3534 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3535 ldmia r3, {r0-r1} @ r0/r1<- vAA 3536 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3537 rsbs r0, r0, #0 @ optional op; may set condition codes 3538 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3539 GET_INST_OPCODE(ip) @ extract opcode from rINST 3540 stmia r9, {r0-r1} @ vAA<- r0/r1 3541 GOTO_OPCODE(ip) @ jump to next instruction 3542 /* 12-13 instructions */ 3543 3544 3545/* ------------------------------ */ 3546 .balign 64 3547.L_OP_NOT_LONG: /* 0x7e */ 3548/* File: armv5te/OP_NOT_LONG.S */ 3549/* File: armv5te/unopWide.S */ 3550 /* 3551 * Generic 64-bit unary operation. Provide an "instr" line that 3552 * specifies an instruction that performs "result = op r0/r1". 3553 * This could be an ARM instruction or a function call. 3554 * 3555 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3556 */ 3557 /* unop vA, vB */ 3558 mov r9, rINST, lsr #8 @ r9<- A+ 3559 mov r3, rINST, lsr #12 @ r3<- B 3560 and r9, r9, #15 3561 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3562 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3563 ldmia r3, {r0-r1} @ r0/r1<- vAA 3564 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3565 mvn r0, r0 @ optional op; may set condition codes 3566 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3567 GET_INST_OPCODE(ip) @ extract opcode from rINST 3568 stmia r9, {r0-r1} @ vAA<- r0/r1 3569 GOTO_OPCODE(ip) @ jump to next instruction 3570 /* 12-13 instructions */ 3571 3572 3573/* ------------------------------ */ 3574 .balign 64 3575.L_OP_NEG_FLOAT: /* 0x7f */ 3576/* File: armv5te/OP_NEG_FLOAT.S */ 3577/* File: armv5te/unop.S */ 3578 /* 3579 * Generic 32-bit unary operation. Provide an "instr" line that 3580 * specifies an instruction that performs "result = op r0". 3581 * This could be an ARM instruction or a function call. 3582 * 3583 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3584 * int-to-byte, int-to-char, int-to-short 3585 */ 3586 /* unop vA, vB */ 3587 mov r3, rINST, lsr #12 @ r3<- B 3588 mov r9, rINST, lsr #8 @ r9<- A+ 3589 GET_VREG(r0, r3) @ r0<- vB 3590 and r9, r9, #15 3591 @ optional op; may set condition codes 3592 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3593 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3594 GET_INST_OPCODE(ip) @ extract opcode from rINST 3595 SET_VREG(r0, r9) @ vAA<- r0 3596 GOTO_OPCODE(ip) @ jump to next instruction 3597 /* 9-10 instructions */ 3598 3599 3600/* ------------------------------ */ 3601 .balign 64 3602.L_OP_NEG_DOUBLE: /* 0x80 */ 3603/* File: armv5te/OP_NEG_DOUBLE.S */ 3604/* File: armv5te/unopWide.S */ 3605 /* 3606 * Generic 64-bit unary operation. Provide an "instr" line that 3607 * specifies an instruction that performs "result = op r0/r1". 3608 * This could be an ARM instruction or a function call. 3609 * 3610 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3611 */ 3612 /* unop vA, vB */ 3613 mov r9, rINST, lsr #8 @ r9<- A+ 3614 mov r3, rINST, lsr #12 @ r3<- B 3615 and r9, r9, #15 3616 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3617 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3618 ldmia r3, {r0-r1} @ r0/r1<- vAA 3619 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3620 @ optional op; may set condition codes 3621 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3622 GET_INST_OPCODE(ip) @ extract opcode from rINST 3623 stmia r9, {r0-r1} @ vAA<- r0/r1 3624 GOTO_OPCODE(ip) @ jump to next instruction 3625 /* 12-13 instructions */ 3626 3627 3628/* ------------------------------ */ 3629 .balign 64 3630.L_OP_INT_TO_LONG: /* 0x81 */ 3631/* File: armv5te/OP_INT_TO_LONG.S */ 3632/* File: armv5te/unopWider.S */ 3633 /* 3634 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3635 * that specifies an instruction that performs "result = op r0", where 3636 * "result" is a 64-bit quantity in r0/r1. 3637 * 3638 * For: int-to-long, int-to-double, float-to-long, float-to-double 3639 */ 3640 /* unop vA, vB */ 3641 mov r9, rINST, lsr #8 @ r9<- A+ 3642 mov r3, rINST, lsr #12 @ r3<- B 3643 and r9, r9, #15 3644 GET_VREG(r0, r3) @ r0<- vB 3645 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3646 @ optional op; may set condition codes 3647 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3648 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3649 GET_INST_OPCODE(ip) @ extract opcode from rINST 3650 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3651 GOTO_OPCODE(ip) @ jump to next instruction 3652 /* 10-11 instructions */ 3653 3654 3655/* ------------------------------ */ 3656 .balign 64 3657.L_OP_INT_TO_FLOAT: /* 0x82 */ 3658/* File: arm-vfp/OP_INT_TO_FLOAT.S */ 3659/* File: arm-vfp/funop.S */ 3660 /* 3661 * Generic 32-bit unary floating-point operation. Provide an "instr" 3662 * line that specifies an instruction that performs "s1 = op s0". 3663 * 3664 * for: int-to-float, float-to-int 3665 */ 3666 /* unop vA, vB */ 3667 mov r3, rINST, lsr #12 @ r3<- B 3668 mov r9, rINST, lsr #8 @ r9<- A+ 3669 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3670 flds s0, [r3] @ s0<- vB 3671 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3672 and r9, r9, #15 @ r9<- A 3673 fsitos s1, s0 @ s1<- op 3674 GET_INST_OPCODE(ip) @ extract opcode from rINST 3675 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3676 fsts s1, [r9] @ vA<- s1 3677 GOTO_OPCODE(ip) @ jump to next instruction 3678 3679 3680/* ------------------------------ */ 3681 .balign 64 3682.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3683/* File: arm-vfp/OP_INT_TO_DOUBLE.S */ 3684/* File: arm-vfp/funopWider.S */ 3685 /* 3686 * Generic 32bit-to-64bit floating point unary operation. Provide an 3687 * "instr" line that specifies an instruction that performs "d0 = op s0". 3688 * 3689 * For: int-to-double, float-to-double 3690 */ 3691 /* unop vA, vB */ 3692 mov r3, rINST, lsr #12 @ r3<- B 3693 mov r9, rINST, lsr #8 @ r9<- A+ 3694 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3695 flds s0, [r3] @ s0<- vB 3696 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3697 and r9, r9, #15 @ r9<- A 3698 fsitod d0, s0 @ d0<- op 3699 GET_INST_OPCODE(ip) @ extract opcode from rINST 3700 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3701 fstd d0, [r9] @ vA<- d0 3702 GOTO_OPCODE(ip) @ jump to next instruction 3703 3704 3705/* ------------------------------ */ 3706 .balign 64 3707.L_OP_LONG_TO_INT: /* 0x84 */ 3708/* File: armv5te/OP_LONG_TO_INT.S */ 3709/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3710/* File: armv5te/OP_MOVE.S */ 3711 /* for move, move-object, long-to-int */ 3712 /* op vA, vB */ 3713 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3714 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3715 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3716 GET_VREG(r2, r1) @ r2<- fp[B] 3717 and r0, r0, #15 3718 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3719 SET_VREG(r2, r0) @ fp[A]<- r2 3720 GOTO_OPCODE(ip) @ execute next instruction 3721 3722 3723/* ------------------------------ */ 3724 .balign 64 3725.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3726/* File: armv5te/OP_LONG_TO_FLOAT.S */ 3727/* File: armv5te/unopNarrower.S */ 3728 /* 3729 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3730 * that specifies an instruction that performs "result = op r0/r1", where 3731 * "result" is a 32-bit quantity in r0. 3732 * 3733 * For: long-to-float, double-to-int, double-to-float 3734 * 3735 * (This would work for long-to-int, but that instruction is actually 3736 * an exact match for OP_MOVE.) 3737 */ 3738 /* unop vA, vB */ 3739 mov r3, rINST, lsr #12 @ r3<- B 3740 mov r9, rINST, lsr #8 @ r9<- A+ 3741 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3742 and r9, r9, #15 3743 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3744 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3745 @ optional op; may set condition codes 3746 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3747 GET_INST_OPCODE(ip) @ extract opcode from rINST 3748 SET_VREG(r0, r9) @ vA<- r0 3749 GOTO_OPCODE(ip) @ jump to next instruction 3750 /* 10-11 instructions */ 3751 3752 3753/* ------------------------------ */ 3754 .balign 64 3755.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3756/* File: armv5te/OP_LONG_TO_DOUBLE.S */ 3757/* File: armv5te/unopWide.S */ 3758 /* 3759 * Generic 64-bit unary operation. Provide an "instr" line that 3760 * specifies an instruction that performs "result = op r0/r1". 3761 * This could be an ARM instruction or a function call. 3762 * 3763 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3764 */ 3765 /* unop vA, vB */ 3766 mov r9, rINST, lsr #8 @ r9<- A+ 3767 mov r3, rINST, lsr #12 @ r3<- B 3768 and r9, r9, #15 3769 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3770 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3771 ldmia r3, {r0-r1} @ r0/r1<- vAA 3772 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3773 @ optional op; may set condition codes 3774 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3775 GET_INST_OPCODE(ip) @ extract opcode from rINST 3776 stmia r9, {r0-r1} @ vAA<- r0/r1 3777 GOTO_OPCODE(ip) @ jump to next instruction 3778 /* 12-13 instructions */ 3779 3780 3781/* ------------------------------ */ 3782 .balign 64 3783.L_OP_FLOAT_TO_INT: /* 0x87 */ 3784/* File: arm-vfp/OP_FLOAT_TO_INT.S */ 3785/* File: arm-vfp/funop.S */ 3786 /* 3787 * Generic 32-bit unary floating-point operation. Provide an "instr" 3788 * line that specifies an instruction that performs "s1 = op s0". 3789 * 3790 * for: int-to-float, float-to-int 3791 */ 3792 /* unop vA, vB */ 3793 mov r3, rINST, lsr #12 @ r3<- B 3794 mov r9, rINST, lsr #8 @ r9<- A+ 3795 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3796 flds s0, [r3] @ s0<- vB 3797 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3798 and r9, r9, #15 @ r9<- A 3799 ftosizs s1, s0 @ s1<- op 3800 GET_INST_OPCODE(ip) @ extract opcode from rINST 3801 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3802 fsts s1, [r9] @ vA<- s1 3803 GOTO_OPCODE(ip) @ jump to next instruction 3804 3805 3806/* ------------------------------ */ 3807 .balign 64 3808.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3809/* File: armv5te/OP_FLOAT_TO_LONG.S */ 3810@include "armv5te/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3811/* File: armv5te/unopWider.S */ 3812 /* 3813 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3814 * that specifies an instruction that performs "result = op r0", where 3815 * "result" is a 64-bit quantity in r0/r1. 3816 * 3817 * For: int-to-long, int-to-double, float-to-long, float-to-double 3818 */ 3819 /* unop vA, vB */ 3820 mov r9, rINST, lsr #8 @ r9<- A+ 3821 mov r3, rINST, lsr #12 @ r3<- B 3822 and r9, r9, #15 3823 GET_VREG(r0, r3) @ r0<- vB 3824 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3825 @ optional op; may set condition codes 3826 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3827 bl f2l_doconv @ r0<- op, r0-r3 changed 3828 GET_INST_OPCODE(ip) @ extract opcode from rINST 3829 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3830 GOTO_OPCODE(ip) @ jump to next instruction 3831 /* 10-11 instructions */ 3832 3833 3834 3835/* ------------------------------ */ 3836 .balign 64 3837.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3838/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */ 3839/* File: arm-vfp/funopWider.S */ 3840 /* 3841 * Generic 32bit-to-64bit floating point unary operation. Provide an 3842 * "instr" line that specifies an instruction that performs "d0 = op s0". 3843 * 3844 * For: int-to-double, float-to-double 3845 */ 3846 /* unop vA, vB */ 3847 mov r3, rINST, lsr #12 @ r3<- B 3848 mov r9, rINST, lsr #8 @ r9<- A+ 3849 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3850 flds s0, [r3] @ s0<- vB 3851 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3852 and r9, r9, #15 @ r9<- A 3853 fcvtds d0, s0 @ d0<- op 3854 GET_INST_OPCODE(ip) @ extract opcode from rINST 3855 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3856 fstd d0, [r9] @ vA<- d0 3857 GOTO_OPCODE(ip) @ jump to next instruction 3858 3859 3860/* ------------------------------ */ 3861 .balign 64 3862.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3863/* File: arm-vfp/OP_DOUBLE_TO_INT.S */ 3864/* File: arm-vfp/funopNarrower.S */ 3865 /* 3866 * Generic 64bit-to-32bit unary floating point operation. Provide an 3867 * "instr" line that specifies an instruction that performs "s0 = op d0". 3868 * 3869 * For: double-to-int, double-to-float 3870 */ 3871 /* unop vA, vB */ 3872 mov r3, rINST, lsr #12 @ r3<- B 3873 mov r9, rINST, lsr #8 @ r9<- A+ 3874 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3875 fldd d0, [r3] @ d0<- vB 3876 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3877 and r9, r9, #15 @ r9<- A 3878 ftosizd s0, d0 @ s0<- op 3879 GET_INST_OPCODE(ip) @ extract opcode from rINST 3880 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3881 fsts s0, [r9] @ vA<- s0 3882 GOTO_OPCODE(ip) @ jump to next instruction 3883 3884 3885/* ------------------------------ */ 3886 .balign 64 3887.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3888/* File: armv5te/OP_DOUBLE_TO_LONG.S */ 3889@include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"} 3890/* File: armv5te/unopWide.S */ 3891 /* 3892 * Generic 64-bit unary operation. Provide an "instr" line that 3893 * specifies an instruction that performs "result = op r0/r1". 3894 * This could be an ARM instruction or a function call. 3895 * 3896 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3897 */ 3898 /* unop vA, vB */ 3899 mov r9, rINST, lsr #8 @ r9<- A+ 3900 mov r3, rINST, lsr #12 @ r3<- B 3901 and r9, r9, #15 3902 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3903 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3904 ldmia r3, {r0-r1} @ r0/r1<- vAA 3905 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3906 @ optional op; may set condition codes 3907 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 3908 GET_INST_OPCODE(ip) @ extract opcode from rINST 3909 stmia r9, {r0-r1} @ vAA<- r0/r1 3910 GOTO_OPCODE(ip) @ jump to next instruction 3911 /* 12-13 instructions */ 3912 3913 3914 3915/* ------------------------------ */ 3916 .balign 64 3917.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3918/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */ 3919/* File: arm-vfp/funopNarrower.S */ 3920 /* 3921 * Generic 64bit-to-32bit unary floating point operation. Provide an 3922 * "instr" line that specifies an instruction that performs "s0 = op d0". 3923 * 3924 * For: double-to-int, double-to-float 3925 */ 3926 /* unop vA, vB */ 3927 mov r3, rINST, lsr #12 @ r3<- B 3928 mov r9, rINST, lsr #8 @ r9<- A+ 3929 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3930 fldd d0, [r3] @ d0<- vB 3931 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3932 and r9, r9, #15 @ r9<- A 3933 fcvtsd s0, d0 @ s0<- op 3934 GET_INST_OPCODE(ip) @ extract opcode from rINST 3935 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3936 fsts s0, [r9] @ vA<- s0 3937 GOTO_OPCODE(ip) @ jump to next instruction 3938 3939 3940/* ------------------------------ */ 3941 .balign 64 3942.L_OP_INT_TO_BYTE: /* 0x8d */ 3943/* File: armv5te/OP_INT_TO_BYTE.S */ 3944/* File: armv5te/unop.S */ 3945 /* 3946 * Generic 32-bit unary operation. Provide an "instr" line that 3947 * specifies an instruction that performs "result = op r0". 3948 * This could be an ARM instruction or a function call. 3949 * 3950 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3951 * int-to-byte, int-to-char, int-to-short 3952 */ 3953 /* unop vA, vB */ 3954 mov r3, rINST, lsr #12 @ r3<- B 3955 mov r9, rINST, lsr #8 @ r9<- A+ 3956 GET_VREG(r0, r3) @ r0<- vB 3957 and r9, r9, #15 3958 mov r0, r0, asl #24 @ optional op; may set condition codes 3959 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3960 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed 3961 GET_INST_OPCODE(ip) @ extract opcode from rINST 3962 SET_VREG(r0, r9) @ vAA<- r0 3963 GOTO_OPCODE(ip) @ jump to next instruction 3964 /* 9-10 instructions */ 3965 3966 3967/* ------------------------------ */ 3968 .balign 64 3969.L_OP_INT_TO_CHAR: /* 0x8e */ 3970/* File: armv5te/OP_INT_TO_CHAR.S */ 3971/* File: armv5te/unop.S */ 3972 /* 3973 * Generic 32-bit unary operation. Provide an "instr" line that 3974 * specifies an instruction that performs "result = op r0". 3975 * This could be an ARM instruction or a function call. 3976 * 3977 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3978 * int-to-byte, int-to-char, int-to-short 3979 */ 3980 /* unop vA, vB */ 3981 mov r3, rINST, lsr #12 @ r3<- B 3982 mov r9, rINST, lsr #8 @ r9<- A+ 3983 GET_VREG(r0, r3) @ r0<- vB 3984 and r9, r9, #15 3985 mov r0, r0, asl #16 @ optional op; may set condition codes 3986 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3987 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed 3988 GET_INST_OPCODE(ip) @ extract opcode from rINST 3989 SET_VREG(r0, r9) @ vAA<- r0 3990 GOTO_OPCODE(ip) @ jump to next instruction 3991 /* 9-10 instructions */ 3992 3993 3994/* ------------------------------ */ 3995 .balign 64 3996.L_OP_INT_TO_SHORT: /* 0x8f */ 3997/* File: armv5te/OP_INT_TO_SHORT.S */ 3998/* File: armv5te/unop.S */ 3999 /* 4000 * Generic 32-bit unary operation. Provide an "instr" line that 4001 * specifies an instruction that performs "result = op r0". 4002 * This could be an ARM instruction or a function call. 4003 * 4004 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4005 * int-to-byte, int-to-char, int-to-short 4006 */ 4007 /* unop vA, vB */ 4008 mov r3, rINST, lsr #12 @ r3<- B 4009 mov r9, rINST, lsr #8 @ r9<- A+ 4010 GET_VREG(r0, r3) @ r0<- vB 4011 and r9, r9, #15 4012 mov r0, r0, asl #16 @ optional op; may set condition codes 4013 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4014 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed 4015 GET_INST_OPCODE(ip) @ extract opcode from rINST 4016 SET_VREG(r0, r9) @ vAA<- r0 4017 GOTO_OPCODE(ip) @ jump to next instruction 4018 /* 9-10 instructions */ 4019 4020 4021/* ------------------------------ */ 4022 .balign 64 4023.L_OP_ADD_INT: /* 0x90 */ 4024/* File: armv5te/OP_ADD_INT.S */ 4025/* File: armv5te/binop.S */ 4026 /* 4027 * Generic 32-bit binary operation. Provide an "instr" line that 4028 * specifies an instruction that performs "result = r0 op r1". 4029 * This could be an ARM instruction or a function call. (If the result 4030 * comes back in a register other than r0, you can override "result".) 4031 * 4032 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4033 * vCC (r1). Useful for integer division and modulus. Note that we 4034 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4035 * handles it correctly. 4036 * 4037 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4038 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4039 * mul-float, div-float, rem-float 4040 */ 4041 /* binop vAA, vBB, vCC */ 4042 FETCH(r0, 1) @ r0<- CCBB 4043 mov r9, rINST, lsr #8 @ r9<- AA 4044 mov r3, r0, lsr #8 @ r3<- CC 4045 and r2, r0, #255 @ r2<- BB 4046 GET_VREG(r1, r3) @ r1<- vCC 4047 GET_VREG(r0, r2) @ r0<- vBB 4048 .if 0 4049 cmp r1, #0 @ is second operand zero? 4050 beq common_errDivideByZero 4051 .endif 4052 4053 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4054 @ optional op; may set condition codes 4055 add r0, r0, r1 @ r0<- op, r0-r3 changed 4056 GET_INST_OPCODE(ip) @ extract opcode from rINST 4057 SET_VREG(r0, r9) @ vAA<- r0 4058 GOTO_OPCODE(ip) @ jump to next instruction 4059 /* 11-14 instructions */ 4060 4061 4062/* ------------------------------ */ 4063 .balign 64 4064.L_OP_SUB_INT: /* 0x91 */ 4065/* File: armv5te/OP_SUB_INT.S */ 4066/* File: armv5te/binop.S */ 4067 /* 4068 * Generic 32-bit binary operation. Provide an "instr" line that 4069 * specifies an instruction that performs "result = r0 op r1". 4070 * This could be an ARM instruction or a function call. (If the result 4071 * comes back in a register other than r0, you can override "result".) 4072 * 4073 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4074 * vCC (r1). Useful for integer division and modulus. Note that we 4075 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4076 * handles it correctly. 4077 * 4078 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4079 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4080 * mul-float, div-float, rem-float 4081 */ 4082 /* binop vAA, vBB, vCC */ 4083 FETCH(r0, 1) @ r0<- CCBB 4084 mov r9, rINST, lsr #8 @ r9<- AA 4085 mov r3, r0, lsr #8 @ r3<- CC 4086 and r2, r0, #255 @ r2<- BB 4087 GET_VREG(r1, r3) @ r1<- vCC 4088 GET_VREG(r0, r2) @ r0<- vBB 4089 .if 0 4090 cmp r1, #0 @ is second operand zero? 4091 beq common_errDivideByZero 4092 .endif 4093 4094 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4095 @ optional op; may set condition codes 4096 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4097 GET_INST_OPCODE(ip) @ extract opcode from rINST 4098 SET_VREG(r0, r9) @ vAA<- r0 4099 GOTO_OPCODE(ip) @ jump to next instruction 4100 /* 11-14 instructions */ 4101 4102 4103/* ------------------------------ */ 4104 .balign 64 4105.L_OP_MUL_INT: /* 0x92 */ 4106/* File: armv5te/OP_MUL_INT.S */ 4107/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4108/* File: armv5te/binop.S */ 4109 /* 4110 * Generic 32-bit binary operation. Provide an "instr" line that 4111 * specifies an instruction that performs "result = r0 op r1". 4112 * This could be an ARM instruction or a function call. (If the result 4113 * comes back in a register other than r0, you can override "result".) 4114 * 4115 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4116 * vCC (r1). Useful for integer division and modulus. Note that we 4117 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4118 * handles it correctly. 4119 * 4120 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4121 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4122 * mul-float, div-float, rem-float 4123 */ 4124 /* binop vAA, vBB, vCC */ 4125 FETCH(r0, 1) @ r0<- CCBB 4126 mov r9, rINST, lsr #8 @ r9<- AA 4127 mov r3, r0, lsr #8 @ r3<- CC 4128 and r2, r0, #255 @ r2<- BB 4129 GET_VREG(r1, r3) @ r1<- vCC 4130 GET_VREG(r0, r2) @ r0<- vBB 4131 .if 0 4132 cmp r1, #0 @ is second operand zero? 4133 beq common_errDivideByZero 4134 .endif 4135 4136 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4137 @ optional op; may set condition codes 4138 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4139 GET_INST_OPCODE(ip) @ extract opcode from rINST 4140 SET_VREG(r0, r9) @ vAA<- r0 4141 GOTO_OPCODE(ip) @ jump to next instruction 4142 /* 11-14 instructions */ 4143 4144 4145/* ------------------------------ */ 4146 .balign 64 4147.L_OP_DIV_INT: /* 0x93 */ 4148/* File: armv5te/OP_DIV_INT.S */ 4149/* File: armv5te/binop.S */ 4150 /* 4151 * Generic 32-bit binary operation. Provide an "instr" line that 4152 * specifies an instruction that performs "result = r0 op r1". 4153 * This could be an ARM instruction or a function call. (If the result 4154 * comes back in a register other than r0, you can override "result".) 4155 * 4156 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4157 * vCC (r1). Useful for integer division and modulus. Note that we 4158 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4159 * handles it correctly. 4160 * 4161 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4162 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4163 * mul-float, div-float, rem-float 4164 */ 4165 /* binop vAA, vBB, vCC */ 4166 FETCH(r0, 1) @ r0<- CCBB 4167 mov r9, rINST, lsr #8 @ r9<- AA 4168 mov r3, r0, lsr #8 @ r3<- CC 4169 and r2, r0, #255 @ r2<- BB 4170 GET_VREG(r1, r3) @ r1<- vCC 4171 GET_VREG(r0, r2) @ r0<- vBB 4172 .if 1 4173 cmp r1, #0 @ is second operand zero? 4174 beq common_errDivideByZero 4175 .endif 4176 4177 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4178 @ optional op; may set condition codes 4179 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4180 GET_INST_OPCODE(ip) @ extract opcode from rINST 4181 SET_VREG(r0, r9) @ vAA<- r0 4182 GOTO_OPCODE(ip) @ jump to next instruction 4183 /* 11-14 instructions */ 4184 4185 4186/* ------------------------------ */ 4187 .balign 64 4188.L_OP_REM_INT: /* 0x94 */ 4189/* File: armv5te/OP_REM_INT.S */ 4190/* idivmod returns quotient in r0 and remainder in r1 */ 4191/* File: armv5te/binop.S */ 4192 /* 4193 * Generic 32-bit binary operation. Provide an "instr" line that 4194 * specifies an instruction that performs "result = r0 op r1". 4195 * This could be an ARM instruction or a function call. (If the result 4196 * comes back in a register other than r0, you can override "result".) 4197 * 4198 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4199 * vCC (r1). Useful for integer division and modulus. Note that we 4200 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4201 * handles it correctly. 4202 * 4203 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4204 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4205 * mul-float, div-float, rem-float 4206 */ 4207 /* binop vAA, vBB, vCC */ 4208 FETCH(r0, 1) @ r0<- CCBB 4209 mov r9, rINST, lsr #8 @ r9<- AA 4210 mov r3, r0, lsr #8 @ r3<- CC 4211 and r2, r0, #255 @ r2<- BB 4212 GET_VREG(r1, r3) @ r1<- vCC 4213 GET_VREG(r0, r2) @ r0<- vBB 4214 .if 1 4215 cmp r1, #0 @ is second operand zero? 4216 beq common_errDivideByZero 4217 .endif 4218 4219 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4220 @ optional op; may set condition codes 4221 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4222 GET_INST_OPCODE(ip) @ extract opcode from rINST 4223 SET_VREG(r1, r9) @ vAA<- r1 4224 GOTO_OPCODE(ip) @ jump to next instruction 4225 /* 11-14 instructions */ 4226 4227 4228/* ------------------------------ */ 4229 .balign 64 4230.L_OP_AND_INT: /* 0x95 */ 4231/* File: armv5te/OP_AND_INT.S */ 4232/* File: armv5te/binop.S */ 4233 /* 4234 * Generic 32-bit binary operation. Provide an "instr" line that 4235 * specifies an instruction that performs "result = r0 op r1". 4236 * This could be an ARM instruction or a function call. (If the result 4237 * comes back in a register other than r0, you can override "result".) 4238 * 4239 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4240 * vCC (r1). Useful for integer division and modulus. Note that we 4241 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4242 * handles it correctly. 4243 * 4244 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4245 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4246 * mul-float, div-float, rem-float 4247 */ 4248 /* binop vAA, vBB, vCC */ 4249 FETCH(r0, 1) @ r0<- CCBB 4250 mov r9, rINST, lsr #8 @ r9<- AA 4251 mov r3, r0, lsr #8 @ r3<- CC 4252 and r2, r0, #255 @ r2<- BB 4253 GET_VREG(r1, r3) @ r1<- vCC 4254 GET_VREG(r0, r2) @ r0<- vBB 4255 .if 0 4256 cmp r1, #0 @ is second operand zero? 4257 beq common_errDivideByZero 4258 .endif 4259 4260 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4261 @ optional op; may set condition codes 4262 and r0, r0, r1 @ r0<- op, r0-r3 changed 4263 GET_INST_OPCODE(ip) @ extract opcode from rINST 4264 SET_VREG(r0, r9) @ vAA<- r0 4265 GOTO_OPCODE(ip) @ jump to next instruction 4266 /* 11-14 instructions */ 4267 4268 4269/* ------------------------------ */ 4270 .balign 64 4271.L_OP_OR_INT: /* 0x96 */ 4272/* File: armv5te/OP_OR_INT.S */ 4273/* File: armv5te/binop.S */ 4274 /* 4275 * Generic 32-bit binary operation. Provide an "instr" line that 4276 * specifies an instruction that performs "result = r0 op r1". 4277 * This could be an ARM instruction or a function call. (If the result 4278 * comes back in a register other than r0, you can override "result".) 4279 * 4280 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4281 * vCC (r1). Useful for integer division and modulus. Note that we 4282 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4283 * handles it correctly. 4284 * 4285 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4286 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4287 * mul-float, div-float, rem-float 4288 */ 4289 /* binop vAA, vBB, vCC */ 4290 FETCH(r0, 1) @ r0<- CCBB 4291 mov r9, rINST, lsr #8 @ r9<- AA 4292 mov r3, r0, lsr #8 @ r3<- CC 4293 and r2, r0, #255 @ r2<- BB 4294 GET_VREG(r1, r3) @ r1<- vCC 4295 GET_VREG(r0, r2) @ r0<- vBB 4296 .if 0 4297 cmp r1, #0 @ is second operand zero? 4298 beq common_errDivideByZero 4299 .endif 4300 4301 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4302 @ optional op; may set condition codes 4303 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4304 GET_INST_OPCODE(ip) @ extract opcode from rINST 4305 SET_VREG(r0, r9) @ vAA<- r0 4306 GOTO_OPCODE(ip) @ jump to next instruction 4307 /* 11-14 instructions */ 4308 4309 4310/* ------------------------------ */ 4311 .balign 64 4312.L_OP_XOR_INT: /* 0x97 */ 4313/* File: armv5te/OP_XOR_INT.S */ 4314/* File: armv5te/binop.S */ 4315 /* 4316 * Generic 32-bit binary operation. Provide an "instr" line that 4317 * specifies an instruction that performs "result = r0 op r1". 4318 * This could be an ARM instruction or a function call. (If the result 4319 * comes back in a register other than r0, you can override "result".) 4320 * 4321 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4322 * vCC (r1). Useful for integer division and modulus. Note that we 4323 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4324 * handles it correctly. 4325 * 4326 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4327 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4328 * mul-float, div-float, rem-float 4329 */ 4330 /* binop vAA, vBB, vCC */ 4331 FETCH(r0, 1) @ r0<- CCBB 4332 mov r9, rINST, lsr #8 @ r9<- AA 4333 mov r3, r0, lsr #8 @ r3<- CC 4334 and r2, r0, #255 @ r2<- BB 4335 GET_VREG(r1, r3) @ r1<- vCC 4336 GET_VREG(r0, r2) @ r0<- vBB 4337 .if 0 4338 cmp r1, #0 @ is second operand zero? 4339 beq common_errDivideByZero 4340 .endif 4341 4342 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4343 @ optional op; may set condition codes 4344 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4345 GET_INST_OPCODE(ip) @ extract opcode from rINST 4346 SET_VREG(r0, r9) @ vAA<- r0 4347 GOTO_OPCODE(ip) @ jump to next instruction 4348 /* 11-14 instructions */ 4349 4350 4351/* ------------------------------ */ 4352 .balign 64 4353.L_OP_SHL_INT: /* 0x98 */ 4354/* File: armv5te/OP_SHL_INT.S */ 4355/* File: armv5te/binop.S */ 4356 /* 4357 * Generic 32-bit binary operation. Provide an "instr" line that 4358 * specifies an instruction that performs "result = r0 op r1". 4359 * This could be an ARM instruction or a function call. (If the result 4360 * comes back in a register other than r0, you can override "result".) 4361 * 4362 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4363 * vCC (r1). Useful for integer division and modulus. Note that we 4364 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4365 * handles it correctly. 4366 * 4367 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4368 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4369 * mul-float, div-float, rem-float 4370 */ 4371 /* binop vAA, vBB, vCC */ 4372 FETCH(r0, 1) @ r0<- CCBB 4373 mov r9, rINST, lsr #8 @ r9<- AA 4374 mov r3, r0, lsr #8 @ r3<- CC 4375 and r2, r0, #255 @ r2<- BB 4376 GET_VREG(r1, r3) @ r1<- vCC 4377 GET_VREG(r0, r2) @ r0<- vBB 4378 .if 0 4379 cmp r1, #0 @ is second operand zero? 4380 beq common_errDivideByZero 4381 .endif 4382 4383 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4384 and r1, r1, #31 @ optional op; may set condition codes 4385 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4386 GET_INST_OPCODE(ip) @ extract opcode from rINST 4387 SET_VREG(r0, r9) @ vAA<- r0 4388 GOTO_OPCODE(ip) @ jump to next instruction 4389 /* 11-14 instructions */ 4390 4391 4392/* ------------------------------ */ 4393 .balign 64 4394.L_OP_SHR_INT: /* 0x99 */ 4395/* File: armv5te/OP_SHR_INT.S */ 4396/* File: armv5te/binop.S */ 4397 /* 4398 * Generic 32-bit binary operation. Provide an "instr" line that 4399 * specifies an instruction that performs "result = r0 op r1". 4400 * This could be an ARM instruction or a function call. (If the result 4401 * comes back in a register other than r0, you can override "result".) 4402 * 4403 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4404 * vCC (r1). Useful for integer division and modulus. Note that we 4405 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4406 * handles it correctly. 4407 * 4408 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4409 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4410 * mul-float, div-float, rem-float 4411 */ 4412 /* binop vAA, vBB, vCC */ 4413 FETCH(r0, 1) @ r0<- CCBB 4414 mov r9, rINST, lsr #8 @ r9<- AA 4415 mov r3, r0, lsr #8 @ r3<- CC 4416 and r2, r0, #255 @ r2<- BB 4417 GET_VREG(r1, r3) @ r1<- vCC 4418 GET_VREG(r0, r2) @ r0<- vBB 4419 .if 0 4420 cmp r1, #0 @ is second operand zero? 4421 beq common_errDivideByZero 4422 .endif 4423 4424 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4425 and r1, r1, #31 @ optional op; may set condition codes 4426 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4427 GET_INST_OPCODE(ip) @ extract opcode from rINST 4428 SET_VREG(r0, r9) @ vAA<- r0 4429 GOTO_OPCODE(ip) @ jump to next instruction 4430 /* 11-14 instructions */ 4431 4432 4433/* ------------------------------ */ 4434 .balign 64 4435.L_OP_USHR_INT: /* 0x9a */ 4436/* File: armv5te/OP_USHR_INT.S */ 4437/* File: armv5te/binop.S */ 4438 /* 4439 * Generic 32-bit binary operation. Provide an "instr" line that 4440 * specifies an instruction that performs "result = r0 op r1". 4441 * This could be an ARM instruction or a function call. (If the result 4442 * comes back in a register other than r0, you can override "result".) 4443 * 4444 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4445 * vCC (r1). Useful for integer division and modulus. Note that we 4446 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4447 * handles it correctly. 4448 * 4449 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4450 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4451 * mul-float, div-float, rem-float 4452 */ 4453 /* binop vAA, vBB, vCC */ 4454 FETCH(r0, 1) @ r0<- CCBB 4455 mov r9, rINST, lsr #8 @ r9<- AA 4456 mov r3, r0, lsr #8 @ r3<- CC 4457 and r2, r0, #255 @ r2<- BB 4458 GET_VREG(r1, r3) @ r1<- vCC 4459 GET_VREG(r0, r2) @ r0<- vBB 4460 .if 0 4461 cmp r1, #0 @ is second operand zero? 4462 beq common_errDivideByZero 4463 .endif 4464 4465 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4466 and r1, r1, #31 @ optional op; may set condition codes 4467 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4468 GET_INST_OPCODE(ip) @ extract opcode from rINST 4469 SET_VREG(r0, r9) @ vAA<- r0 4470 GOTO_OPCODE(ip) @ jump to next instruction 4471 /* 11-14 instructions */ 4472 4473 4474/* ------------------------------ */ 4475 .balign 64 4476.L_OP_ADD_LONG: /* 0x9b */ 4477/* File: armv5te/OP_ADD_LONG.S */ 4478/* File: armv5te/binopWide.S */ 4479 /* 4480 * Generic 64-bit binary operation. Provide an "instr" line that 4481 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4482 * This could be an ARM instruction or a function call. (If the result 4483 * comes back in a register other than r0, you can override "result".) 4484 * 4485 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4486 * vCC (r1). Useful for integer division and modulus. 4487 * 4488 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4489 * xor-long, add-double, sub-double, mul-double, div-double, 4490 * rem-double 4491 * 4492 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4493 */ 4494 /* binop vAA, vBB, vCC */ 4495 FETCH(r0, 1) @ r0<- CCBB 4496 mov r9, rINST, lsr #8 @ r9<- AA 4497 and r2, r0, #255 @ r2<- BB 4498 mov r3, r0, lsr #8 @ r3<- CC 4499 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4500 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4501 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4502 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4503 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4504 .if 0 4505 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4506 beq common_errDivideByZero 4507 .endif 4508 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4509 4510 adds r0, r0, r2 @ optional op; may set condition codes 4511 adc r1, r1, r3 @ result<- op, r0-r3 changed 4512 GET_INST_OPCODE(ip) @ extract opcode from rINST 4513 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4514 GOTO_OPCODE(ip) @ jump to next instruction 4515 /* 14-17 instructions */ 4516 4517 4518/* ------------------------------ */ 4519 .balign 64 4520.L_OP_SUB_LONG: /* 0x9c */ 4521/* File: armv5te/OP_SUB_LONG.S */ 4522/* File: armv5te/binopWide.S */ 4523 /* 4524 * Generic 64-bit binary operation. Provide an "instr" line that 4525 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4526 * This could be an ARM instruction or a function call. (If the result 4527 * comes back in a register other than r0, you can override "result".) 4528 * 4529 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4530 * vCC (r1). Useful for integer division and modulus. 4531 * 4532 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4533 * xor-long, add-double, sub-double, mul-double, div-double, 4534 * rem-double 4535 * 4536 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4537 */ 4538 /* binop vAA, vBB, vCC */ 4539 FETCH(r0, 1) @ r0<- CCBB 4540 mov r9, rINST, lsr #8 @ r9<- AA 4541 and r2, r0, #255 @ r2<- BB 4542 mov r3, r0, lsr #8 @ r3<- CC 4543 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4544 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4545 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4546 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4547 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4548 .if 0 4549 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4550 beq common_errDivideByZero 4551 .endif 4552 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4553 4554 subs r0, r0, r2 @ optional op; may set condition codes 4555 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4556 GET_INST_OPCODE(ip) @ extract opcode from rINST 4557 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4558 GOTO_OPCODE(ip) @ jump to next instruction 4559 /* 14-17 instructions */ 4560 4561 4562/* ------------------------------ */ 4563 .balign 64 4564.L_OP_MUL_LONG: /* 0x9d */ 4565/* File: armv5te/OP_MUL_LONG.S */ 4566 /* 4567 * Signed 64-bit integer multiply. 4568 * 4569 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4570 * WX 4571 * x YZ 4572 * -------- 4573 * ZW ZX 4574 * YW YX 4575 * 4576 * The low word of the result holds ZX, the high word holds 4577 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4578 * it doesn't fit in the low 64 bits. 4579 * 4580 * Unlike most ARM math operations, multiply instructions have 4581 * restrictions on using the same register more than once (Rd and Rm 4582 * cannot be the same). 4583 */ 4584 /* mul-long vAA, vBB, vCC */ 4585 FETCH(r0, 1) @ r0<- CCBB 4586 and r2, r0, #255 @ r2<- BB 4587 mov r3, r0, lsr #8 @ r3<- CC 4588 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4589 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4590 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4591 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4592 mul ip, r2, r1 @ ip<- ZxW 4593 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4594 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4595 mov r0, rINST, lsr #8 @ r0<- AA 4596 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4597 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4598 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4599 b .LOP_MUL_LONG_finish 4600 4601/* ------------------------------ */ 4602 .balign 64 4603.L_OP_DIV_LONG: /* 0x9e */ 4604/* File: armv5te/OP_DIV_LONG.S */ 4605/* File: armv5te/binopWide.S */ 4606 /* 4607 * Generic 64-bit binary operation. Provide an "instr" line that 4608 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4609 * This could be an ARM instruction or a function call. (If the result 4610 * comes back in a register other than r0, you can override "result".) 4611 * 4612 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4613 * vCC (r1). Useful for integer division and modulus. 4614 * 4615 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4616 * xor-long, add-double, sub-double, mul-double, div-double, 4617 * rem-double 4618 * 4619 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4620 */ 4621 /* binop vAA, vBB, vCC */ 4622 FETCH(r0, 1) @ r0<- CCBB 4623 mov r9, rINST, lsr #8 @ r9<- AA 4624 and r2, r0, #255 @ r2<- BB 4625 mov r3, r0, lsr #8 @ r3<- CC 4626 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4627 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4628 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4629 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4630 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4631 .if 1 4632 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4633 beq common_errDivideByZero 4634 .endif 4635 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4636 4637 @ optional op; may set condition codes 4638 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4639 GET_INST_OPCODE(ip) @ extract opcode from rINST 4640 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4641 GOTO_OPCODE(ip) @ jump to next instruction 4642 /* 14-17 instructions */ 4643 4644 4645/* ------------------------------ */ 4646 .balign 64 4647.L_OP_REM_LONG: /* 0x9f */ 4648/* File: armv5te/OP_REM_LONG.S */ 4649/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4650/* File: armv5te/binopWide.S */ 4651 /* 4652 * Generic 64-bit binary operation. Provide an "instr" line that 4653 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4654 * This could be an ARM instruction or a function call. (If the result 4655 * comes back in a register other than r0, you can override "result".) 4656 * 4657 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4658 * vCC (r1). Useful for integer division and modulus. 4659 * 4660 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4661 * xor-long, add-double, sub-double, mul-double, div-double, 4662 * rem-double 4663 * 4664 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4665 */ 4666 /* binop vAA, vBB, vCC */ 4667 FETCH(r0, 1) @ r0<- CCBB 4668 mov r9, rINST, lsr #8 @ r9<- AA 4669 and r2, r0, #255 @ r2<- BB 4670 mov r3, r0, lsr #8 @ r3<- CC 4671 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4672 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4673 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4674 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4675 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4676 .if 1 4677 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4678 beq common_errDivideByZero 4679 .endif 4680 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4681 4682 @ optional op; may set condition codes 4683 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4684 GET_INST_OPCODE(ip) @ extract opcode from rINST 4685 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4686 GOTO_OPCODE(ip) @ jump to next instruction 4687 /* 14-17 instructions */ 4688 4689 4690/* ------------------------------ */ 4691 .balign 64 4692.L_OP_AND_LONG: /* 0xa0 */ 4693/* File: armv5te/OP_AND_LONG.S */ 4694/* File: armv5te/binopWide.S */ 4695 /* 4696 * Generic 64-bit binary operation. Provide an "instr" line that 4697 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4698 * This could be an ARM instruction or a function call. (If the result 4699 * comes back in a register other than r0, you can override "result".) 4700 * 4701 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4702 * vCC (r1). Useful for integer division and modulus. 4703 * 4704 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4705 * xor-long, add-double, sub-double, mul-double, div-double, 4706 * rem-double 4707 * 4708 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4709 */ 4710 /* binop vAA, vBB, vCC */ 4711 FETCH(r0, 1) @ r0<- CCBB 4712 mov r9, rINST, lsr #8 @ r9<- AA 4713 and r2, r0, #255 @ r2<- BB 4714 mov r3, r0, lsr #8 @ r3<- CC 4715 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4716 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4717 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4718 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4719 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4720 .if 0 4721 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4722 beq common_errDivideByZero 4723 .endif 4724 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4725 4726 and r0, r0, r2 @ optional op; may set condition codes 4727 and r1, r1, r3 @ result<- op, r0-r3 changed 4728 GET_INST_OPCODE(ip) @ extract opcode from rINST 4729 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4730 GOTO_OPCODE(ip) @ jump to next instruction 4731 /* 14-17 instructions */ 4732 4733 4734/* ------------------------------ */ 4735 .balign 64 4736.L_OP_OR_LONG: /* 0xa1 */ 4737/* File: armv5te/OP_OR_LONG.S */ 4738/* File: armv5te/binopWide.S */ 4739 /* 4740 * Generic 64-bit binary operation. Provide an "instr" line that 4741 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4742 * This could be an ARM instruction or a function call. (If the result 4743 * comes back in a register other than r0, you can override "result".) 4744 * 4745 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4746 * vCC (r1). Useful for integer division and modulus. 4747 * 4748 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4749 * xor-long, add-double, sub-double, mul-double, div-double, 4750 * rem-double 4751 * 4752 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4753 */ 4754 /* binop vAA, vBB, vCC */ 4755 FETCH(r0, 1) @ r0<- CCBB 4756 mov r9, rINST, lsr #8 @ r9<- AA 4757 and r2, r0, #255 @ r2<- BB 4758 mov r3, r0, lsr #8 @ r3<- CC 4759 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4760 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4761 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4762 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4763 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4764 .if 0 4765 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4766 beq common_errDivideByZero 4767 .endif 4768 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4769 4770 orr r0, r0, r2 @ optional op; may set condition codes 4771 orr r1, r1, r3 @ result<- op, r0-r3 changed 4772 GET_INST_OPCODE(ip) @ extract opcode from rINST 4773 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4774 GOTO_OPCODE(ip) @ jump to next instruction 4775 /* 14-17 instructions */ 4776 4777 4778/* ------------------------------ */ 4779 .balign 64 4780.L_OP_XOR_LONG: /* 0xa2 */ 4781/* File: armv5te/OP_XOR_LONG.S */ 4782/* File: armv5te/binopWide.S */ 4783 /* 4784 * Generic 64-bit binary operation. Provide an "instr" line that 4785 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4786 * This could be an ARM instruction or a function call. (If the result 4787 * comes back in a register other than r0, you can override "result".) 4788 * 4789 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4790 * vCC (r1). Useful for integer division and modulus. 4791 * 4792 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4793 * xor-long, add-double, sub-double, mul-double, div-double, 4794 * rem-double 4795 * 4796 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4797 */ 4798 /* binop vAA, vBB, vCC */ 4799 FETCH(r0, 1) @ r0<- CCBB 4800 mov r9, rINST, lsr #8 @ r9<- AA 4801 and r2, r0, #255 @ r2<- BB 4802 mov r3, r0, lsr #8 @ r3<- CC 4803 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4804 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4805 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4806 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4807 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4808 .if 0 4809 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4810 beq common_errDivideByZero 4811 .endif 4812 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4813 4814 eor r0, r0, r2 @ optional op; may set condition codes 4815 eor r1, r1, r3 @ result<- op, r0-r3 changed 4816 GET_INST_OPCODE(ip) @ extract opcode from rINST 4817 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4818 GOTO_OPCODE(ip) @ jump to next instruction 4819 /* 14-17 instructions */ 4820 4821 4822/* ------------------------------ */ 4823 .balign 64 4824.L_OP_SHL_LONG: /* 0xa3 */ 4825/* File: armv5te/OP_SHL_LONG.S */ 4826 /* 4827 * Long integer shift. This is different from the generic 32/64-bit 4828 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4829 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4830 * 6 bits of the shift distance. 4831 */ 4832 /* shl-long vAA, vBB, vCC */ 4833 FETCH(r0, 1) @ r0<- CCBB 4834 mov r9, rINST, lsr #8 @ r9<- AA 4835 and r3, r0, #255 @ r3<- BB 4836 mov r0, r0, lsr #8 @ r0<- CC 4837 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4838 GET_VREG(r2, r0) @ r2<- vCC 4839 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4840 and r2, r2, #63 @ r2<- r2 & 0x3f 4841 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4842 4843 mov r1, r1, asl r2 @ r1<- r1 << r2 4844 rsb r3, r2, #32 @ r3<- 32 - r2 4845 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 4846 subs ip, r2, #32 @ ip<- r2 - 32 4847 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 4848 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4849 b .LOP_SHL_LONG_finish 4850 4851/* ------------------------------ */ 4852 .balign 64 4853.L_OP_SHR_LONG: /* 0xa4 */ 4854/* File: armv5te/OP_SHR_LONG.S */ 4855 /* 4856 * Long integer shift. This is different from the generic 32/64-bit 4857 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4858 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4859 * 6 bits of the shift distance. 4860 */ 4861 /* shr-long vAA, vBB, vCC */ 4862 FETCH(r0, 1) @ r0<- CCBB 4863 mov r9, rINST, lsr #8 @ r9<- AA 4864 and r3, r0, #255 @ r3<- BB 4865 mov r0, r0, lsr #8 @ r0<- CC 4866 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4867 GET_VREG(r2, r0) @ r2<- vCC 4868 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4869 and r2, r2, #63 @ r0<- r0 & 0x3f 4870 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4871 4872 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4873 rsb r3, r2, #32 @ r3<- 32 - r2 4874 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4875 subs ip, r2, #32 @ ip<- r2 - 32 4876 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 4877 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4878 b .LOP_SHR_LONG_finish 4879 4880/* ------------------------------ */ 4881 .balign 64 4882.L_OP_USHR_LONG: /* 0xa5 */ 4883/* File: armv5te/OP_USHR_LONG.S */ 4884 /* 4885 * Long integer shift. This is different from the generic 32/64-bit 4886 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4887 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4888 * 6 bits of the shift distance. 4889 */ 4890 /* ushr-long vAA, vBB, vCC */ 4891 FETCH(r0, 1) @ r0<- CCBB 4892 mov r9, rINST, lsr #8 @ r9<- AA 4893 and r3, r0, #255 @ r3<- BB 4894 mov r0, r0, lsr #8 @ r0<- CC 4895 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4896 GET_VREG(r2, r0) @ r2<- vCC 4897 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4898 and r2, r2, #63 @ r0<- r0 & 0x3f 4899 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4900 4901 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4902 rsb r3, r2, #32 @ r3<- 32 - r2 4903 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4904 subs ip, r2, #32 @ ip<- r2 - 32 4905 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 4906 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4907 b .LOP_USHR_LONG_finish 4908 4909/* ------------------------------ */ 4910 .balign 64 4911.L_OP_ADD_FLOAT: /* 0xa6 */ 4912/* File: arm-vfp/OP_ADD_FLOAT.S */ 4913/* File: arm-vfp/fbinop.S */ 4914 /* 4915 * Generic 32-bit floating-point operation. Provide an "instr" line that 4916 * specifies an instruction that performs "s2 = s0 op s1". Because we 4917 * use the "softfp" ABI, this must be an instruction, not a function call. 4918 * 4919 * For: add-float, sub-float, mul-float, div-float 4920 */ 4921 /* floatop vAA, vBB, vCC */ 4922 FETCH(r0, 1) @ r0<- CCBB 4923 mov r9, rINST, lsr #8 @ r9<- AA 4924 mov r3, r0, lsr #8 @ r3<- CC 4925 and r2, r0, #255 @ r2<- BB 4926 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4927 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4928 flds s1, [r3] @ s1<- vCC 4929 flds s0, [r2] @ s0<- vBB 4930 4931 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4932 fadds s2, s0, s1 @ s2<- op 4933 GET_INST_OPCODE(ip) @ extract opcode from rINST 4934 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4935 fsts s2, [r9] @ vAA<- s2 4936 GOTO_OPCODE(ip) @ jump to next instruction 4937 4938 4939/* ------------------------------ */ 4940 .balign 64 4941.L_OP_SUB_FLOAT: /* 0xa7 */ 4942/* File: arm-vfp/OP_SUB_FLOAT.S */ 4943/* File: arm-vfp/fbinop.S */ 4944 /* 4945 * Generic 32-bit floating-point operation. Provide an "instr" line that 4946 * specifies an instruction that performs "s2 = s0 op s1". Because we 4947 * use the "softfp" ABI, this must be an instruction, not a function call. 4948 * 4949 * For: add-float, sub-float, mul-float, div-float 4950 */ 4951 /* floatop vAA, vBB, vCC */ 4952 FETCH(r0, 1) @ r0<- CCBB 4953 mov r9, rINST, lsr #8 @ r9<- AA 4954 mov r3, r0, lsr #8 @ r3<- CC 4955 and r2, r0, #255 @ r2<- BB 4956 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4957 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4958 flds s1, [r3] @ s1<- vCC 4959 flds s0, [r2] @ s0<- vBB 4960 4961 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4962 fsubs s2, s0, s1 @ s2<- op 4963 GET_INST_OPCODE(ip) @ extract opcode from rINST 4964 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4965 fsts s2, [r9] @ vAA<- s2 4966 GOTO_OPCODE(ip) @ jump to next instruction 4967 4968 4969/* ------------------------------ */ 4970 .balign 64 4971.L_OP_MUL_FLOAT: /* 0xa8 */ 4972/* File: arm-vfp/OP_MUL_FLOAT.S */ 4973/* File: arm-vfp/fbinop.S */ 4974 /* 4975 * Generic 32-bit floating-point operation. Provide an "instr" line that 4976 * specifies an instruction that performs "s2 = s0 op s1". Because we 4977 * use the "softfp" ABI, this must be an instruction, not a function call. 4978 * 4979 * For: add-float, sub-float, mul-float, div-float 4980 */ 4981 /* floatop vAA, vBB, vCC */ 4982 FETCH(r0, 1) @ r0<- CCBB 4983 mov r9, rINST, lsr #8 @ r9<- AA 4984 mov r3, r0, lsr #8 @ r3<- CC 4985 and r2, r0, #255 @ r2<- BB 4986 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4987 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4988 flds s1, [r3] @ s1<- vCC 4989 flds s0, [r2] @ s0<- vBB 4990 4991 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4992 fmuls s2, s0, s1 @ s2<- op 4993 GET_INST_OPCODE(ip) @ extract opcode from rINST 4994 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4995 fsts s2, [r9] @ vAA<- s2 4996 GOTO_OPCODE(ip) @ jump to next instruction 4997 4998 4999/* ------------------------------ */ 5000 .balign 64 5001.L_OP_DIV_FLOAT: /* 0xa9 */ 5002/* File: arm-vfp/OP_DIV_FLOAT.S */ 5003/* File: arm-vfp/fbinop.S */ 5004 /* 5005 * Generic 32-bit floating-point operation. Provide an "instr" line that 5006 * specifies an instruction that performs "s2 = s0 op s1". Because we 5007 * use the "softfp" ABI, this must be an instruction, not a function call. 5008 * 5009 * For: add-float, sub-float, mul-float, div-float 5010 */ 5011 /* floatop vAA, vBB, vCC */ 5012 FETCH(r0, 1) @ r0<- CCBB 5013 mov r9, rINST, lsr #8 @ r9<- AA 5014 mov r3, r0, lsr #8 @ r3<- CC 5015 and r2, r0, #255 @ r2<- BB 5016 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5017 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5018 flds s1, [r3] @ s1<- vCC 5019 flds s0, [r2] @ s0<- vBB 5020 5021 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5022 fdivs s2, s0, s1 @ s2<- op 5023 GET_INST_OPCODE(ip) @ extract opcode from rINST 5024 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5025 fsts s2, [r9] @ vAA<- s2 5026 GOTO_OPCODE(ip) @ jump to next instruction 5027 5028 5029/* ------------------------------ */ 5030 .balign 64 5031.L_OP_REM_FLOAT: /* 0xaa */ 5032/* File: armv5te/OP_REM_FLOAT.S */ 5033/* EABI doesn't define a float remainder function, but libm does */ 5034/* File: armv5te/binop.S */ 5035 /* 5036 * Generic 32-bit binary operation. Provide an "instr" line that 5037 * specifies an instruction that performs "result = r0 op r1". 5038 * This could be an ARM instruction or a function call. (If the result 5039 * comes back in a register other than r0, you can override "result".) 5040 * 5041 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5042 * vCC (r1). Useful for integer division and modulus. Note that we 5043 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5044 * handles it correctly. 5045 * 5046 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5047 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5048 * mul-float, div-float, rem-float 5049 */ 5050 /* binop vAA, vBB, vCC */ 5051 FETCH(r0, 1) @ r0<- CCBB 5052 mov r9, rINST, lsr #8 @ r9<- AA 5053 mov r3, r0, lsr #8 @ r3<- CC 5054 and r2, r0, #255 @ r2<- BB 5055 GET_VREG(r1, r3) @ r1<- vCC 5056 GET_VREG(r0, r2) @ r0<- vBB 5057 .if 0 5058 cmp r1, #0 @ is second operand zero? 5059 beq common_errDivideByZero 5060 .endif 5061 5062 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5063 @ optional op; may set condition codes 5064 bl fmodf @ r0<- op, r0-r3 changed 5065 GET_INST_OPCODE(ip) @ extract opcode from rINST 5066 SET_VREG(r0, r9) @ vAA<- r0 5067 GOTO_OPCODE(ip) @ jump to next instruction 5068 /* 11-14 instructions */ 5069 5070 5071/* ------------------------------ */ 5072 .balign 64 5073.L_OP_ADD_DOUBLE: /* 0xab */ 5074/* File: arm-vfp/OP_ADD_DOUBLE.S */ 5075/* File: arm-vfp/fbinopWide.S */ 5076 /* 5077 * Generic 64-bit double-precision floating point binary operation. 5078 * Provide an "instr" line that specifies an instruction that performs 5079 * "d2 = d0 op d1". 5080 * 5081 * for: add-double, sub-double, mul-double, div-double 5082 */ 5083 /* doubleop vAA, vBB, vCC */ 5084 FETCH(r0, 1) @ r0<- CCBB 5085 mov r9, rINST, lsr #8 @ r9<- AA 5086 mov r3, r0, lsr #8 @ r3<- CC 5087 and r2, r0, #255 @ r2<- BB 5088 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5089 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5090 fldd d1, [r3] @ d1<- vCC 5091 fldd d0, [r2] @ d0<- vBB 5092 5093 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5094 faddd d2, d0, d1 @ s2<- op 5095 GET_INST_OPCODE(ip) @ extract opcode from rINST 5096 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5097 fstd d2, [r9] @ vAA<- d2 5098 GOTO_OPCODE(ip) @ jump to next instruction 5099 5100 5101/* ------------------------------ */ 5102 .balign 64 5103.L_OP_SUB_DOUBLE: /* 0xac */ 5104/* File: arm-vfp/OP_SUB_DOUBLE.S */ 5105/* File: arm-vfp/fbinopWide.S */ 5106 /* 5107 * Generic 64-bit double-precision floating point binary operation. 5108 * Provide an "instr" line that specifies an instruction that performs 5109 * "d2 = d0 op d1". 5110 * 5111 * for: add-double, sub-double, mul-double, div-double 5112 */ 5113 /* doubleop vAA, vBB, vCC */ 5114 FETCH(r0, 1) @ r0<- CCBB 5115 mov r9, rINST, lsr #8 @ r9<- AA 5116 mov r3, r0, lsr #8 @ r3<- CC 5117 and r2, r0, #255 @ r2<- BB 5118 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5119 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5120 fldd d1, [r3] @ d1<- vCC 5121 fldd d0, [r2] @ d0<- vBB 5122 5123 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5124 fsubd d2, d0, d1 @ s2<- op 5125 GET_INST_OPCODE(ip) @ extract opcode from rINST 5126 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5127 fstd d2, [r9] @ vAA<- d2 5128 GOTO_OPCODE(ip) @ jump to next instruction 5129 5130 5131/* ------------------------------ */ 5132 .balign 64 5133.L_OP_MUL_DOUBLE: /* 0xad */ 5134/* File: arm-vfp/OP_MUL_DOUBLE.S */ 5135/* File: arm-vfp/fbinopWide.S */ 5136 /* 5137 * Generic 64-bit double-precision floating point binary operation. 5138 * Provide an "instr" line that specifies an instruction that performs 5139 * "d2 = d0 op d1". 5140 * 5141 * for: add-double, sub-double, mul-double, div-double 5142 */ 5143 /* doubleop vAA, vBB, vCC */ 5144 FETCH(r0, 1) @ r0<- CCBB 5145 mov r9, rINST, lsr #8 @ r9<- AA 5146 mov r3, r0, lsr #8 @ r3<- CC 5147 and r2, r0, #255 @ r2<- BB 5148 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5149 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5150 fldd d1, [r3] @ d1<- vCC 5151 fldd d0, [r2] @ d0<- vBB 5152 5153 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5154 fmuld d2, d0, d1 @ s2<- op 5155 GET_INST_OPCODE(ip) @ extract opcode from rINST 5156 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5157 fstd d2, [r9] @ vAA<- d2 5158 GOTO_OPCODE(ip) @ jump to next instruction 5159 5160 5161/* ------------------------------ */ 5162 .balign 64 5163.L_OP_DIV_DOUBLE: /* 0xae */ 5164/* File: arm-vfp/OP_DIV_DOUBLE.S */ 5165/* File: arm-vfp/fbinopWide.S */ 5166 /* 5167 * Generic 64-bit double-precision floating point binary operation. 5168 * Provide an "instr" line that specifies an instruction that performs 5169 * "d2 = d0 op d1". 5170 * 5171 * for: add-double, sub-double, mul-double, div-double 5172 */ 5173 /* doubleop vAA, vBB, vCC */ 5174 FETCH(r0, 1) @ r0<- CCBB 5175 mov r9, rINST, lsr #8 @ r9<- AA 5176 mov r3, r0, lsr #8 @ r3<- CC 5177 and r2, r0, #255 @ r2<- BB 5178 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5179 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5180 fldd d1, [r3] @ d1<- vCC 5181 fldd d0, [r2] @ d0<- vBB 5182 5183 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5184 fdivd d2, d0, d1 @ s2<- op 5185 GET_INST_OPCODE(ip) @ extract opcode from rINST 5186 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5187 fstd d2, [r9] @ vAA<- d2 5188 GOTO_OPCODE(ip) @ jump to next instruction 5189 5190 5191/* ------------------------------ */ 5192 .balign 64 5193.L_OP_REM_DOUBLE: /* 0xaf */ 5194/* File: armv5te/OP_REM_DOUBLE.S */ 5195/* EABI doesn't define a double remainder function, but libm does */ 5196/* File: armv5te/binopWide.S */ 5197 /* 5198 * Generic 64-bit binary operation. Provide an "instr" line that 5199 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5200 * This could be an ARM instruction or a function call. (If the result 5201 * comes back in a register other than r0, you can override "result".) 5202 * 5203 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5204 * vCC (r1). Useful for integer division and modulus. 5205 * 5206 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5207 * xor-long, add-double, sub-double, mul-double, div-double, 5208 * rem-double 5209 * 5210 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5211 */ 5212 /* binop vAA, vBB, vCC */ 5213 FETCH(r0, 1) @ r0<- CCBB 5214 mov r9, rINST, lsr #8 @ r9<- AA 5215 and r2, r0, #255 @ r2<- BB 5216 mov r3, r0, lsr #8 @ r3<- CC 5217 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5218 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5219 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5220 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5221 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5222 .if 0 5223 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5224 beq common_errDivideByZero 5225 .endif 5226 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5227 5228 @ optional op; may set condition codes 5229 bl fmod @ result<- op, r0-r3 changed 5230 GET_INST_OPCODE(ip) @ extract opcode from rINST 5231 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5232 GOTO_OPCODE(ip) @ jump to next instruction 5233 /* 14-17 instructions */ 5234 5235 5236/* ------------------------------ */ 5237 .balign 64 5238.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5239/* File: armv5te/OP_ADD_INT_2ADDR.S */ 5240/* File: armv5te/binop2addr.S */ 5241 /* 5242 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5243 * that specifies an instruction that performs "result = r0 op r1". 5244 * This could be an ARM instruction or a function call. (If the result 5245 * comes back in a register other than r0, you can override "result".) 5246 * 5247 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5248 * vCC (r1). Useful for integer division and modulus. 5249 * 5250 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5251 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5252 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5253 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5254 */ 5255 /* binop/2addr vA, vB */ 5256 mov r9, rINST, lsr #8 @ r9<- A+ 5257 mov r3, rINST, lsr #12 @ r3<- B 5258 and r9, r9, #15 5259 GET_VREG(r1, r3) @ r1<- vB 5260 GET_VREG(r0, r9) @ r0<- vA 5261 .if 0 5262 cmp r1, #0 @ is second operand zero? 5263 beq common_errDivideByZero 5264 .endif 5265 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5266 5267 @ optional op; may set condition codes 5268 add r0, r0, r1 @ r0<- op, r0-r3 changed 5269 GET_INST_OPCODE(ip) @ extract opcode from rINST 5270 SET_VREG(r0, r9) @ vAA<- r0 5271 GOTO_OPCODE(ip) @ jump to next instruction 5272 /* 10-13 instructions */ 5273 5274 5275/* ------------------------------ */ 5276 .balign 64 5277.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5278/* File: armv5te/OP_SUB_INT_2ADDR.S */ 5279/* File: armv5te/binop2addr.S */ 5280 /* 5281 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5282 * that specifies an instruction that performs "result = r0 op r1". 5283 * This could be an ARM instruction or a function call. (If the result 5284 * comes back in a register other than r0, you can override "result".) 5285 * 5286 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5287 * vCC (r1). Useful for integer division and modulus. 5288 * 5289 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5290 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5291 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5292 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5293 */ 5294 /* binop/2addr vA, vB */ 5295 mov r9, rINST, lsr #8 @ r9<- A+ 5296 mov r3, rINST, lsr #12 @ r3<- B 5297 and r9, r9, #15 5298 GET_VREG(r1, r3) @ r1<- vB 5299 GET_VREG(r0, r9) @ r0<- vA 5300 .if 0 5301 cmp r1, #0 @ is second operand zero? 5302 beq common_errDivideByZero 5303 .endif 5304 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5305 5306 @ optional op; may set condition codes 5307 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5308 GET_INST_OPCODE(ip) @ extract opcode from rINST 5309 SET_VREG(r0, r9) @ vAA<- r0 5310 GOTO_OPCODE(ip) @ jump to next instruction 5311 /* 10-13 instructions */ 5312 5313 5314/* ------------------------------ */ 5315 .balign 64 5316.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5317/* File: armv5te/OP_MUL_INT_2ADDR.S */ 5318/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5319/* File: armv5te/binop2addr.S */ 5320 /* 5321 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5322 * that specifies an instruction that performs "result = r0 op r1". 5323 * This could be an ARM instruction or a function call. (If the result 5324 * comes back in a register other than r0, you can override "result".) 5325 * 5326 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5327 * vCC (r1). Useful for integer division and modulus. 5328 * 5329 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5330 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5331 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5332 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5333 */ 5334 /* binop/2addr vA, vB */ 5335 mov r9, rINST, lsr #8 @ r9<- A+ 5336 mov r3, rINST, lsr #12 @ r3<- B 5337 and r9, r9, #15 5338 GET_VREG(r1, r3) @ r1<- vB 5339 GET_VREG(r0, r9) @ r0<- vA 5340 .if 0 5341 cmp r1, #0 @ is second operand zero? 5342 beq common_errDivideByZero 5343 .endif 5344 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5345 5346 @ optional op; may set condition codes 5347 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5348 GET_INST_OPCODE(ip) @ extract opcode from rINST 5349 SET_VREG(r0, r9) @ vAA<- r0 5350 GOTO_OPCODE(ip) @ jump to next instruction 5351 /* 10-13 instructions */ 5352 5353 5354/* ------------------------------ */ 5355 .balign 64 5356.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5357/* File: armv5te/OP_DIV_INT_2ADDR.S */ 5358/* File: armv5te/binop2addr.S */ 5359 /* 5360 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5361 * that specifies an instruction that performs "result = r0 op r1". 5362 * This could be an ARM instruction or a function call. (If the result 5363 * comes back in a register other than r0, you can override "result".) 5364 * 5365 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5366 * vCC (r1). Useful for integer division and modulus. 5367 * 5368 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5369 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5370 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5371 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5372 */ 5373 /* binop/2addr vA, vB */ 5374 mov r9, rINST, lsr #8 @ r9<- A+ 5375 mov r3, rINST, lsr #12 @ r3<- B 5376 and r9, r9, #15 5377 GET_VREG(r1, r3) @ r1<- vB 5378 GET_VREG(r0, r9) @ r0<- vA 5379 .if 1 5380 cmp r1, #0 @ is second operand zero? 5381 beq common_errDivideByZero 5382 .endif 5383 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5384 5385 @ optional op; may set condition codes 5386 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5387 GET_INST_OPCODE(ip) @ extract opcode from rINST 5388 SET_VREG(r0, r9) @ vAA<- r0 5389 GOTO_OPCODE(ip) @ jump to next instruction 5390 /* 10-13 instructions */ 5391 5392 5393/* ------------------------------ */ 5394 .balign 64 5395.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5396/* File: armv5te/OP_REM_INT_2ADDR.S */ 5397/* idivmod returns quotient in r0 and remainder in r1 */ 5398/* File: armv5te/binop2addr.S */ 5399 /* 5400 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5401 * that specifies an instruction that performs "result = r0 op r1". 5402 * This could be an ARM instruction or a function call. (If the result 5403 * comes back in a register other than r0, you can override "result".) 5404 * 5405 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5406 * vCC (r1). Useful for integer division and modulus. 5407 * 5408 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5409 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5410 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5411 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5412 */ 5413 /* binop/2addr vA, vB */ 5414 mov r9, rINST, lsr #8 @ r9<- A+ 5415 mov r3, rINST, lsr #12 @ r3<- B 5416 and r9, r9, #15 5417 GET_VREG(r1, r3) @ r1<- vB 5418 GET_VREG(r0, r9) @ r0<- vA 5419 .if 1 5420 cmp r1, #0 @ is second operand zero? 5421 beq common_errDivideByZero 5422 .endif 5423 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5424 5425 @ optional op; may set condition codes 5426 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5427 GET_INST_OPCODE(ip) @ extract opcode from rINST 5428 SET_VREG(r1, r9) @ vAA<- r1 5429 GOTO_OPCODE(ip) @ jump to next instruction 5430 /* 10-13 instructions */ 5431 5432 5433/* ------------------------------ */ 5434 .balign 64 5435.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5436/* File: armv5te/OP_AND_INT_2ADDR.S */ 5437/* File: armv5te/binop2addr.S */ 5438 /* 5439 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5440 * that specifies an instruction that performs "result = r0 op r1". 5441 * This could be an ARM instruction or a function call. (If the result 5442 * comes back in a register other than r0, you can override "result".) 5443 * 5444 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5445 * vCC (r1). Useful for integer division and modulus. 5446 * 5447 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5448 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5449 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5450 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5451 */ 5452 /* binop/2addr vA, vB */ 5453 mov r9, rINST, lsr #8 @ r9<- A+ 5454 mov r3, rINST, lsr #12 @ r3<- B 5455 and r9, r9, #15 5456 GET_VREG(r1, r3) @ r1<- vB 5457 GET_VREG(r0, r9) @ r0<- vA 5458 .if 0 5459 cmp r1, #0 @ is second operand zero? 5460 beq common_errDivideByZero 5461 .endif 5462 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5463 5464 @ optional op; may set condition codes 5465 and r0, r0, r1 @ r0<- op, r0-r3 changed 5466 GET_INST_OPCODE(ip) @ extract opcode from rINST 5467 SET_VREG(r0, r9) @ vAA<- r0 5468 GOTO_OPCODE(ip) @ jump to next instruction 5469 /* 10-13 instructions */ 5470 5471 5472/* ------------------------------ */ 5473 .balign 64 5474.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5475/* File: armv5te/OP_OR_INT_2ADDR.S */ 5476/* File: armv5te/binop2addr.S */ 5477 /* 5478 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5479 * that specifies an instruction that performs "result = r0 op r1". 5480 * This could be an ARM instruction or a function call. (If the result 5481 * comes back in a register other than r0, you can override "result".) 5482 * 5483 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5484 * vCC (r1). Useful for integer division and modulus. 5485 * 5486 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5487 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5488 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5489 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5490 */ 5491 /* binop/2addr vA, vB */ 5492 mov r9, rINST, lsr #8 @ r9<- A+ 5493 mov r3, rINST, lsr #12 @ r3<- B 5494 and r9, r9, #15 5495 GET_VREG(r1, r3) @ r1<- vB 5496 GET_VREG(r0, r9) @ r0<- vA 5497 .if 0 5498 cmp r1, #0 @ is second operand zero? 5499 beq common_errDivideByZero 5500 .endif 5501 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5502 5503 @ optional op; may set condition codes 5504 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5505 GET_INST_OPCODE(ip) @ extract opcode from rINST 5506 SET_VREG(r0, r9) @ vAA<- r0 5507 GOTO_OPCODE(ip) @ jump to next instruction 5508 /* 10-13 instructions */ 5509 5510 5511/* ------------------------------ */ 5512 .balign 64 5513.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5514/* File: armv5te/OP_XOR_INT_2ADDR.S */ 5515/* File: armv5te/binop2addr.S */ 5516 /* 5517 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5518 * that specifies an instruction that performs "result = r0 op r1". 5519 * This could be an ARM instruction or a function call. (If the result 5520 * comes back in a register other than r0, you can override "result".) 5521 * 5522 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5523 * vCC (r1). Useful for integer division and modulus. 5524 * 5525 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5526 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5527 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5528 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5529 */ 5530 /* binop/2addr vA, vB */ 5531 mov r9, rINST, lsr #8 @ r9<- A+ 5532 mov r3, rINST, lsr #12 @ r3<- B 5533 and r9, r9, #15 5534 GET_VREG(r1, r3) @ r1<- vB 5535 GET_VREG(r0, r9) @ r0<- vA 5536 .if 0 5537 cmp r1, #0 @ is second operand zero? 5538 beq common_errDivideByZero 5539 .endif 5540 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5541 5542 @ optional op; may set condition codes 5543 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5544 GET_INST_OPCODE(ip) @ extract opcode from rINST 5545 SET_VREG(r0, r9) @ vAA<- r0 5546 GOTO_OPCODE(ip) @ jump to next instruction 5547 /* 10-13 instructions */ 5548 5549 5550/* ------------------------------ */ 5551 .balign 64 5552.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5553/* File: armv5te/OP_SHL_INT_2ADDR.S */ 5554/* File: armv5te/binop2addr.S */ 5555 /* 5556 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5557 * that specifies an instruction that performs "result = r0 op r1". 5558 * This could be an ARM instruction or a function call. (If the result 5559 * comes back in a register other than r0, you can override "result".) 5560 * 5561 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5562 * vCC (r1). Useful for integer division and modulus. 5563 * 5564 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5565 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5566 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5567 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5568 */ 5569 /* binop/2addr vA, vB */ 5570 mov r9, rINST, lsr #8 @ r9<- A+ 5571 mov r3, rINST, lsr #12 @ r3<- B 5572 and r9, r9, #15 5573 GET_VREG(r1, r3) @ r1<- vB 5574 GET_VREG(r0, r9) @ r0<- vA 5575 .if 0 5576 cmp r1, #0 @ is second operand zero? 5577 beq common_errDivideByZero 5578 .endif 5579 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5580 5581 and r1, r1, #31 @ optional op; may set condition codes 5582 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5583 GET_INST_OPCODE(ip) @ extract opcode from rINST 5584 SET_VREG(r0, r9) @ vAA<- r0 5585 GOTO_OPCODE(ip) @ jump to next instruction 5586 /* 10-13 instructions */ 5587 5588 5589/* ------------------------------ */ 5590 .balign 64 5591.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5592/* File: armv5te/OP_SHR_INT_2ADDR.S */ 5593/* File: armv5te/binop2addr.S */ 5594 /* 5595 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5596 * that specifies an instruction that performs "result = r0 op r1". 5597 * This could be an ARM instruction or a function call. (If the result 5598 * comes back in a register other than r0, you can override "result".) 5599 * 5600 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5601 * vCC (r1). Useful for integer division and modulus. 5602 * 5603 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5604 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5605 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5606 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5607 */ 5608 /* binop/2addr vA, vB */ 5609 mov r9, rINST, lsr #8 @ r9<- A+ 5610 mov r3, rINST, lsr #12 @ r3<- B 5611 and r9, r9, #15 5612 GET_VREG(r1, r3) @ r1<- vB 5613 GET_VREG(r0, r9) @ r0<- vA 5614 .if 0 5615 cmp r1, #0 @ is second operand zero? 5616 beq common_errDivideByZero 5617 .endif 5618 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5619 5620 and r1, r1, #31 @ optional op; may set condition codes 5621 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5622 GET_INST_OPCODE(ip) @ extract opcode from rINST 5623 SET_VREG(r0, r9) @ vAA<- r0 5624 GOTO_OPCODE(ip) @ jump to next instruction 5625 /* 10-13 instructions */ 5626 5627 5628/* ------------------------------ */ 5629 .balign 64 5630.L_OP_USHR_INT_2ADDR: /* 0xba */ 5631/* File: armv5te/OP_USHR_INT_2ADDR.S */ 5632/* File: armv5te/binop2addr.S */ 5633 /* 5634 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5635 * that specifies an instruction that performs "result = r0 op r1". 5636 * This could be an ARM instruction or a function call. (If the result 5637 * comes back in a register other than r0, you can override "result".) 5638 * 5639 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5640 * vCC (r1). Useful for integer division and modulus. 5641 * 5642 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5643 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5644 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5645 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5646 */ 5647 /* binop/2addr vA, vB */ 5648 mov r9, rINST, lsr #8 @ r9<- A+ 5649 mov r3, rINST, lsr #12 @ r3<- B 5650 and r9, r9, #15 5651 GET_VREG(r1, r3) @ r1<- vB 5652 GET_VREG(r0, r9) @ r0<- vA 5653 .if 0 5654 cmp r1, #0 @ is second operand zero? 5655 beq common_errDivideByZero 5656 .endif 5657 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5658 5659 and r1, r1, #31 @ optional op; may set condition codes 5660 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5661 GET_INST_OPCODE(ip) @ extract opcode from rINST 5662 SET_VREG(r0, r9) @ vAA<- r0 5663 GOTO_OPCODE(ip) @ jump to next instruction 5664 /* 10-13 instructions */ 5665 5666 5667/* ------------------------------ */ 5668 .balign 64 5669.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5670/* File: armv5te/OP_ADD_LONG_2ADDR.S */ 5671/* File: armv5te/binopWide2addr.S */ 5672 /* 5673 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5674 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5675 * This could be an ARM instruction or a function call. (If the result 5676 * comes back in a register other than r0, you can override "result".) 5677 * 5678 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5679 * vCC (r1). Useful for integer division and modulus. 5680 * 5681 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5682 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5683 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5684 * rem-double/2addr 5685 */ 5686 /* binop/2addr vA, vB */ 5687 mov r9, rINST, lsr #8 @ r9<- A+ 5688 mov r1, rINST, lsr #12 @ r1<- B 5689 and r9, r9, #15 5690 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5691 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5692 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5693 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5694 .if 0 5695 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5696 beq common_errDivideByZero 5697 .endif 5698 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5699 5700 adds r0, r0, r2 @ optional op; may set condition codes 5701 adc r1, r1, r3 @ result<- op, r0-r3 changed 5702 GET_INST_OPCODE(ip) @ extract opcode from rINST 5703 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5704 GOTO_OPCODE(ip) @ jump to next instruction 5705 /* 12-15 instructions */ 5706 5707 5708/* ------------------------------ */ 5709 .balign 64 5710.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5711/* File: armv5te/OP_SUB_LONG_2ADDR.S */ 5712/* File: armv5te/binopWide2addr.S */ 5713 /* 5714 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5715 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5716 * This could be an ARM instruction or a function call. (If the result 5717 * comes back in a register other than r0, you can override "result".) 5718 * 5719 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5720 * vCC (r1). Useful for integer division and modulus. 5721 * 5722 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5723 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5724 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5725 * rem-double/2addr 5726 */ 5727 /* binop/2addr vA, vB */ 5728 mov r9, rINST, lsr #8 @ r9<- A+ 5729 mov r1, rINST, lsr #12 @ r1<- B 5730 and r9, r9, #15 5731 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5732 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5733 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5734 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5735 .if 0 5736 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5737 beq common_errDivideByZero 5738 .endif 5739 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5740 5741 subs r0, r0, r2 @ optional op; may set condition codes 5742 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5743 GET_INST_OPCODE(ip) @ extract opcode from rINST 5744 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5745 GOTO_OPCODE(ip) @ jump to next instruction 5746 /* 12-15 instructions */ 5747 5748 5749/* ------------------------------ */ 5750 .balign 64 5751.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 5752/* File: armv5te/OP_MUL_LONG_2ADDR.S */ 5753 /* 5754 * Signed 64-bit integer multiply, "/2addr" version. 5755 * 5756 * See OP_MUL_LONG for an explanation. 5757 * 5758 * We get a little tight on registers, so to avoid looking up &fp[A] 5759 * again we stuff it into rINST. 5760 */ 5761 /* mul-long/2addr vA, vB */ 5762 mov r9, rINST, lsr #8 @ r9<- A+ 5763 mov r1, rINST, lsr #12 @ r1<- B 5764 and r9, r9, #15 5765 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5766 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 5767 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5768 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 5769 mul ip, r2, r1 @ ip<- ZxW 5770 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 5771 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 5772 mov r0, rINST @ r0<- &fp[A] (free up rINST) 5773 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5774 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 5775 GET_INST_OPCODE(ip) @ extract opcode from rINST 5776 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 5777 GOTO_OPCODE(ip) @ jump to next instruction 5778 5779/* ------------------------------ */ 5780 .balign 64 5781.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 5782/* File: armv5te/OP_DIV_LONG_2ADDR.S */ 5783/* File: armv5te/binopWide2addr.S */ 5784 /* 5785 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5786 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5787 * This could be an ARM instruction or a function call. (If the result 5788 * comes back in a register other than r0, you can override "result".) 5789 * 5790 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5791 * vCC (r1). Useful for integer division and modulus. 5792 * 5793 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5794 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5795 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5796 * rem-double/2addr 5797 */ 5798 /* binop/2addr vA, vB */ 5799 mov r9, rINST, lsr #8 @ r9<- A+ 5800 mov r1, rINST, lsr #12 @ r1<- B 5801 and r9, r9, #15 5802 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5803 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5804 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5805 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5806 .if 1 5807 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5808 beq common_errDivideByZero 5809 .endif 5810 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5811 5812 @ optional op; may set condition codes 5813 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5814 GET_INST_OPCODE(ip) @ extract opcode from rINST 5815 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5816 GOTO_OPCODE(ip) @ jump to next instruction 5817 /* 12-15 instructions */ 5818 5819 5820/* ------------------------------ */ 5821 .balign 64 5822.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5823/* File: armv5te/OP_REM_LONG_2ADDR.S */ 5824/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 5825/* File: armv5te/binopWide2addr.S */ 5826 /* 5827 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5828 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5829 * This could be an ARM instruction or a function call. (If the result 5830 * comes back in a register other than r0, you can override "result".) 5831 * 5832 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5833 * vCC (r1). Useful for integer division and modulus. 5834 * 5835 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5836 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5837 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5838 * rem-double/2addr 5839 */ 5840 /* binop/2addr vA, vB */ 5841 mov r9, rINST, lsr #8 @ r9<- A+ 5842 mov r1, rINST, lsr #12 @ r1<- B 5843 and r9, r9, #15 5844 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5845 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5846 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5847 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5848 .if 1 5849 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5850 beq common_errDivideByZero 5851 .endif 5852 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5853 5854 @ optional op; may set condition codes 5855 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5856 GET_INST_OPCODE(ip) @ extract opcode from rINST 5857 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 5858 GOTO_OPCODE(ip) @ jump to next instruction 5859 /* 12-15 instructions */ 5860 5861 5862/* ------------------------------ */ 5863 .balign 64 5864.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 5865/* File: armv5te/OP_AND_LONG_2ADDR.S */ 5866/* File: armv5te/binopWide2addr.S */ 5867 /* 5868 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5869 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5870 * This could be an ARM instruction or a function call. (If the result 5871 * comes back in a register other than r0, you can override "result".) 5872 * 5873 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5874 * vCC (r1). Useful for integer division and modulus. 5875 * 5876 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5877 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5878 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5879 * rem-double/2addr 5880 */ 5881 /* binop/2addr vA, vB */ 5882 mov r9, rINST, lsr #8 @ r9<- A+ 5883 mov r1, rINST, lsr #12 @ r1<- B 5884 and r9, r9, #15 5885 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5886 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5887 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5888 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5889 .if 0 5890 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5891 beq common_errDivideByZero 5892 .endif 5893 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5894 5895 and r0, r0, r2 @ optional op; may set condition codes 5896 and r1, r1, r3 @ result<- op, r0-r3 changed 5897 GET_INST_OPCODE(ip) @ extract opcode from rINST 5898 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5899 GOTO_OPCODE(ip) @ jump to next instruction 5900 /* 12-15 instructions */ 5901 5902 5903/* ------------------------------ */ 5904 .balign 64 5905.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 5906/* File: armv5te/OP_OR_LONG_2ADDR.S */ 5907/* File: armv5te/binopWide2addr.S */ 5908 /* 5909 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5910 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5911 * This could be an ARM instruction or a function call. (If the result 5912 * comes back in a register other than r0, you can override "result".) 5913 * 5914 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5915 * vCC (r1). Useful for integer division and modulus. 5916 * 5917 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5918 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5919 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5920 * rem-double/2addr 5921 */ 5922 /* binop/2addr vA, vB */ 5923 mov r9, rINST, lsr #8 @ r9<- A+ 5924 mov r1, rINST, lsr #12 @ r1<- B 5925 and r9, r9, #15 5926 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5927 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5928 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5929 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5930 .if 0 5931 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5932 beq common_errDivideByZero 5933 .endif 5934 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5935 5936 orr r0, r0, r2 @ optional op; may set condition codes 5937 orr r1, r1, r3 @ result<- op, r0-r3 changed 5938 GET_INST_OPCODE(ip) @ extract opcode from rINST 5939 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5940 GOTO_OPCODE(ip) @ jump to next instruction 5941 /* 12-15 instructions */ 5942 5943 5944/* ------------------------------ */ 5945 .balign 64 5946.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 5947/* File: armv5te/OP_XOR_LONG_2ADDR.S */ 5948/* File: armv5te/binopWide2addr.S */ 5949 /* 5950 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5951 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5952 * This could be an ARM instruction or a function call. (If the result 5953 * comes back in a register other than r0, you can override "result".) 5954 * 5955 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5956 * vCC (r1). Useful for integer division and modulus. 5957 * 5958 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5959 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5960 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5961 * rem-double/2addr 5962 */ 5963 /* binop/2addr vA, vB */ 5964 mov r9, rINST, lsr #8 @ r9<- A+ 5965 mov r1, rINST, lsr #12 @ r1<- B 5966 and r9, r9, #15 5967 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5968 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5969 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5970 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5971 .if 0 5972 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5973 beq common_errDivideByZero 5974 .endif 5975 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5976 5977 eor r0, r0, r2 @ optional op; may set condition codes 5978 eor r1, r1, r3 @ result<- op, r0-r3 changed 5979 GET_INST_OPCODE(ip) @ extract opcode from rINST 5980 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5981 GOTO_OPCODE(ip) @ jump to next instruction 5982 /* 12-15 instructions */ 5983 5984 5985/* ------------------------------ */ 5986 .balign 64 5987.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 5988/* File: armv5te/OP_SHL_LONG_2ADDR.S */ 5989 /* 5990 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 5991 * 32-bit shift distance. 5992 */ 5993 /* shl-long/2addr vA, vB */ 5994 mov r9, rINST, lsr #8 @ r9<- A+ 5995 mov r3, rINST, lsr #12 @ r3<- B 5996 and r9, r9, #15 5997 GET_VREG(r2, r3) @ r2<- vB 5998 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5999 and r2, r2, #63 @ r2<- r2 & 0x3f 6000 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6001 6002 mov r1, r1, asl r2 @ r1<- r1 << r2 6003 rsb r3, r2, #32 @ r3<- 32 - r2 6004 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 6005 subs ip, r2, #32 @ ip<- r2 - 32 6006 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6007 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 6008 mov r0, r0, asl r2 @ r0<- r0 << r2 6009 b .LOP_SHL_LONG_2ADDR_finish 6010 6011/* ------------------------------ */ 6012 .balign 64 6013.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 6014/* File: armv5te/OP_SHR_LONG_2ADDR.S */ 6015 /* 6016 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6017 * 32-bit shift distance. 6018 */ 6019 /* shr-long/2addr vA, vB */ 6020 mov r9, rINST, lsr #8 @ r9<- A+ 6021 mov r3, rINST, lsr #12 @ r3<- B 6022 and r9, r9, #15 6023 GET_VREG(r2, r3) @ r2<- vB 6024 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6025 and r2, r2, #63 @ r2<- r2 & 0x3f 6026 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6027 6028 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6029 rsb r3, r2, #32 @ r3<- 32 - r2 6030 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6031 subs ip, r2, #32 @ ip<- r2 - 32 6032 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6033 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6034 mov r1, r1, asr r2 @ r1<- r1 >> r2 6035 b .LOP_SHR_LONG_2ADDR_finish 6036 6037/* ------------------------------ */ 6038 .balign 64 6039.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6040/* File: armv5te/OP_USHR_LONG_2ADDR.S */ 6041 /* 6042 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6043 * 32-bit shift distance. 6044 */ 6045 /* ushr-long/2addr vA, vB */ 6046 mov r9, rINST, lsr #8 @ r9<- A+ 6047 mov r3, rINST, lsr #12 @ r3<- B 6048 and r9, r9, #15 6049 GET_VREG(r2, r3) @ r2<- vB 6050 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6051 and r2, r2, #63 @ r2<- r2 & 0x3f 6052 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6053 6054 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6055 rsb r3, r2, #32 @ r3<- 32 - r2 6056 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6057 subs ip, r2, #32 @ ip<- r2 - 32 6058 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6059 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6060 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6061 b .LOP_USHR_LONG_2ADDR_finish 6062 6063/* ------------------------------ */ 6064 .balign 64 6065.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6066/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */ 6067/* File: arm-vfp/fbinop2addr.S */ 6068 /* 6069 * Generic 32-bit floating point "/2addr" binary operation. Provide 6070 * an "instr" line that specifies an instruction that performs 6071 * "s2 = s0 op s1". 6072 * 6073 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6074 */ 6075 /* binop/2addr vA, vB */ 6076 mov r3, rINST, lsr #12 @ r3<- B 6077 mov r9, rINST, lsr #8 @ r9<- A+ 6078 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6079 and r9, r9, #15 @ r9<- A 6080 flds s1, [r3] @ s1<- vB 6081 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6082 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6083 flds s0, [r9] @ s0<- vA 6084 6085 fadds s2, s0, s1 @ s2<- op 6086 GET_INST_OPCODE(ip) @ extract opcode from rINST 6087 fsts s2, [r9] @ vAA<- s2 6088 GOTO_OPCODE(ip) @ jump to next instruction 6089 6090 6091/* ------------------------------ */ 6092 .balign 64 6093.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6094/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */ 6095/* File: arm-vfp/fbinop2addr.S */ 6096 /* 6097 * Generic 32-bit floating point "/2addr" binary operation. Provide 6098 * an "instr" line that specifies an instruction that performs 6099 * "s2 = s0 op s1". 6100 * 6101 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6102 */ 6103 /* binop/2addr vA, vB */ 6104 mov r3, rINST, lsr #12 @ r3<- B 6105 mov r9, rINST, lsr #8 @ r9<- A+ 6106 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6107 and r9, r9, #15 @ r9<- A 6108 flds s1, [r3] @ s1<- vB 6109 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6110 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6111 flds s0, [r9] @ s0<- vA 6112 6113 fsubs s2, s0, s1 @ s2<- op 6114 GET_INST_OPCODE(ip) @ extract opcode from rINST 6115 fsts s2, [r9] @ vAA<- s2 6116 GOTO_OPCODE(ip) @ jump to next instruction 6117 6118 6119/* ------------------------------ */ 6120 .balign 64 6121.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6122/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */ 6123/* File: arm-vfp/fbinop2addr.S */ 6124 /* 6125 * Generic 32-bit floating point "/2addr" binary operation. Provide 6126 * an "instr" line that specifies an instruction that performs 6127 * "s2 = s0 op s1". 6128 * 6129 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6130 */ 6131 /* binop/2addr vA, vB */ 6132 mov r3, rINST, lsr #12 @ r3<- B 6133 mov r9, rINST, lsr #8 @ r9<- A+ 6134 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6135 and r9, r9, #15 @ r9<- A 6136 flds s1, [r3] @ s1<- vB 6137 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6138 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6139 flds s0, [r9] @ s0<- vA 6140 6141 fmuls s2, s0, s1 @ s2<- op 6142 GET_INST_OPCODE(ip) @ extract opcode from rINST 6143 fsts s2, [r9] @ vAA<- s2 6144 GOTO_OPCODE(ip) @ jump to next instruction 6145 6146 6147/* ------------------------------ */ 6148 .balign 64 6149.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6150/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */ 6151/* File: arm-vfp/fbinop2addr.S */ 6152 /* 6153 * Generic 32-bit floating point "/2addr" binary operation. Provide 6154 * an "instr" line that specifies an instruction that performs 6155 * "s2 = s0 op s1". 6156 * 6157 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6158 */ 6159 /* binop/2addr vA, vB */ 6160 mov r3, rINST, lsr #12 @ r3<- B 6161 mov r9, rINST, lsr #8 @ r9<- A+ 6162 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6163 and r9, r9, #15 @ r9<- A 6164 flds s1, [r3] @ s1<- vB 6165 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6166 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6167 flds s0, [r9] @ s0<- vA 6168 6169 fdivs s2, s0, s1 @ s2<- op 6170 GET_INST_OPCODE(ip) @ extract opcode from rINST 6171 fsts s2, [r9] @ vAA<- s2 6172 GOTO_OPCODE(ip) @ jump to next instruction 6173 6174 6175/* ------------------------------ */ 6176 .balign 64 6177.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6178/* File: armv5te/OP_REM_FLOAT_2ADDR.S */ 6179/* EABI doesn't define a float remainder function, but libm does */ 6180/* File: armv5te/binop2addr.S */ 6181 /* 6182 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6183 * that specifies an instruction that performs "result = r0 op r1". 6184 * This could be an ARM instruction or a function call. (If the result 6185 * comes back in a register other than r0, you can override "result".) 6186 * 6187 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6188 * vCC (r1). Useful for integer division and modulus. 6189 * 6190 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6191 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6192 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6193 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6194 */ 6195 /* binop/2addr vA, vB */ 6196 mov r9, rINST, lsr #8 @ r9<- A+ 6197 mov r3, rINST, lsr #12 @ r3<- B 6198 and r9, r9, #15 6199 GET_VREG(r1, r3) @ r1<- vB 6200 GET_VREG(r0, r9) @ r0<- vA 6201 .if 0 6202 cmp r1, #0 @ is second operand zero? 6203 beq common_errDivideByZero 6204 .endif 6205 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6206 6207 @ optional op; may set condition codes 6208 bl fmodf @ r0<- op, r0-r3 changed 6209 GET_INST_OPCODE(ip) @ extract opcode from rINST 6210 SET_VREG(r0, r9) @ vAA<- r0 6211 GOTO_OPCODE(ip) @ jump to next instruction 6212 /* 10-13 instructions */ 6213 6214 6215/* ------------------------------ */ 6216 .balign 64 6217.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6218/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */ 6219/* File: arm-vfp/fbinopWide2addr.S */ 6220 /* 6221 * Generic 64-bit floating point "/2addr" binary operation. Provide 6222 * an "instr" line that specifies an instruction that performs 6223 * "d2 = d0 op d1". 6224 * 6225 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6226 * div-double/2addr 6227 */ 6228 /* binop/2addr vA, vB */ 6229 mov r3, rINST, lsr #12 @ r3<- B 6230 mov r9, rINST, lsr #8 @ r9<- A+ 6231 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6232 and r9, r9, #15 @ r9<- A 6233 fldd d1, [r3] @ d1<- vB 6234 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6235 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6236 fldd d0, [r9] @ d0<- vA 6237 6238 faddd d2, d0, d1 @ d2<- op 6239 GET_INST_OPCODE(ip) @ extract opcode from rINST 6240 fstd d2, [r9] @ vAA<- d2 6241 GOTO_OPCODE(ip) @ jump to next instruction 6242 6243 6244/* ------------------------------ */ 6245 .balign 64 6246.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6247/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */ 6248/* File: arm-vfp/fbinopWide2addr.S */ 6249 /* 6250 * Generic 64-bit floating point "/2addr" binary operation. Provide 6251 * an "instr" line that specifies an instruction that performs 6252 * "d2 = d0 op d1". 6253 * 6254 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6255 * div-double/2addr 6256 */ 6257 /* binop/2addr vA, vB */ 6258 mov r3, rINST, lsr #12 @ r3<- B 6259 mov r9, rINST, lsr #8 @ r9<- A+ 6260 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6261 and r9, r9, #15 @ r9<- A 6262 fldd d1, [r3] @ d1<- vB 6263 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6264 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6265 fldd d0, [r9] @ d0<- vA 6266 6267 fsubd d2, d0, d1 @ d2<- op 6268 GET_INST_OPCODE(ip) @ extract opcode from rINST 6269 fstd d2, [r9] @ vAA<- d2 6270 GOTO_OPCODE(ip) @ jump to next instruction 6271 6272 6273/* ------------------------------ */ 6274 .balign 64 6275.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6276/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */ 6277/* File: arm-vfp/fbinopWide2addr.S */ 6278 /* 6279 * Generic 64-bit floating point "/2addr" binary operation. Provide 6280 * an "instr" line that specifies an instruction that performs 6281 * "d2 = d0 op d1". 6282 * 6283 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6284 * div-double/2addr 6285 */ 6286 /* binop/2addr vA, vB */ 6287 mov r3, rINST, lsr #12 @ r3<- B 6288 mov r9, rINST, lsr #8 @ r9<- A+ 6289 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6290 and r9, r9, #15 @ r9<- A 6291 fldd d1, [r3] @ d1<- vB 6292 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6293 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6294 fldd d0, [r9] @ d0<- vA 6295 6296 fmuld d2, d0, d1 @ d2<- op 6297 GET_INST_OPCODE(ip) @ extract opcode from rINST 6298 fstd d2, [r9] @ vAA<- d2 6299 GOTO_OPCODE(ip) @ jump to next instruction 6300 6301 6302/* ------------------------------ */ 6303 .balign 64 6304.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6305/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */ 6306/* File: arm-vfp/fbinopWide2addr.S */ 6307 /* 6308 * Generic 64-bit floating point "/2addr" binary operation. Provide 6309 * an "instr" line that specifies an instruction that performs 6310 * "d2 = d0 op d1". 6311 * 6312 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6313 * div-double/2addr 6314 */ 6315 /* binop/2addr vA, vB */ 6316 mov r3, rINST, lsr #12 @ r3<- B 6317 mov r9, rINST, lsr #8 @ r9<- A+ 6318 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6319 and r9, r9, #15 @ r9<- A 6320 fldd d1, [r3] @ d1<- vB 6321 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6322 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6323 fldd d0, [r9] @ d0<- vA 6324 6325 fdivd d2, d0, d1 @ d2<- op 6326 GET_INST_OPCODE(ip) @ extract opcode from rINST 6327 fstd d2, [r9] @ vAA<- d2 6328 GOTO_OPCODE(ip) @ jump to next instruction 6329 6330 6331/* ------------------------------ */ 6332 .balign 64 6333.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6334/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */ 6335/* EABI doesn't define a double remainder function, but libm does */ 6336/* File: armv5te/binopWide2addr.S */ 6337 /* 6338 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6339 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6340 * This could be an ARM instruction or a function call. (If the result 6341 * comes back in a register other than r0, you can override "result".) 6342 * 6343 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6344 * vCC (r1). Useful for integer division and modulus. 6345 * 6346 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6347 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6348 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6349 * rem-double/2addr 6350 */ 6351 /* binop/2addr vA, vB */ 6352 mov r9, rINST, lsr #8 @ r9<- A+ 6353 mov r1, rINST, lsr #12 @ r1<- B 6354 and r9, r9, #15 6355 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6356 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6357 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6358 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6359 .if 0 6360 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6361 beq common_errDivideByZero 6362 .endif 6363 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6364 6365 @ optional op; may set condition codes 6366 bl fmod @ result<- op, r0-r3 changed 6367 GET_INST_OPCODE(ip) @ extract opcode from rINST 6368 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6369 GOTO_OPCODE(ip) @ jump to next instruction 6370 /* 12-15 instructions */ 6371 6372 6373/* ------------------------------ */ 6374 .balign 64 6375.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6376/* File: armv5te/OP_ADD_INT_LIT16.S */ 6377/* File: armv5te/binopLit16.S */ 6378 /* 6379 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6380 * that specifies an instruction that performs "result = r0 op r1". 6381 * This could be an ARM instruction or a function call. (If the result 6382 * comes back in a register other than r0, you can override "result".) 6383 * 6384 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6385 * vCC (r1). Useful for integer division and modulus. 6386 * 6387 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6388 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6389 */ 6390 /* binop/lit16 vA, vB, #+CCCC */ 6391 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6392 mov r2, rINST, lsr #12 @ r2<- B 6393 mov r9, rINST, lsr #8 @ r9<- A+ 6394 GET_VREG(r0, r2) @ r0<- vB 6395 and r9, r9, #15 6396 .if 0 6397 cmp r1, #0 @ is second operand zero? 6398 beq common_errDivideByZero 6399 .endif 6400 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6401 6402 add r0, r0, r1 @ r0<- op, r0-r3 changed 6403 GET_INST_OPCODE(ip) @ extract opcode from rINST 6404 SET_VREG(r0, r9) @ vAA<- r0 6405 GOTO_OPCODE(ip) @ jump to next instruction 6406 /* 10-13 instructions */ 6407 6408 6409/* ------------------------------ */ 6410 .balign 64 6411.L_OP_RSUB_INT: /* 0xd1 */ 6412/* File: armv5te/OP_RSUB_INT.S */ 6413/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6414/* File: armv5te/binopLit16.S */ 6415 /* 6416 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6417 * that specifies an instruction that performs "result = r0 op r1". 6418 * This could be an ARM instruction or a function call. (If the result 6419 * comes back in a register other than r0, you can override "result".) 6420 * 6421 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6422 * vCC (r1). Useful for integer division and modulus. 6423 * 6424 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6425 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6426 */ 6427 /* binop/lit16 vA, vB, #+CCCC */ 6428 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6429 mov r2, rINST, lsr #12 @ r2<- B 6430 mov r9, rINST, lsr #8 @ r9<- A+ 6431 GET_VREG(r0, r2) @ r0<- vB 6432 and r9, r9, #15 6433 .if 0 6434 cmp r1, #0 @ is second operand zero? 6435 beq common_errDivideByZero 6436 .endif 6437 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6438 6439 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6440 GET_INST_OPCODE(ip) @ extract opcode from rINST 6441 SET_VREG(r0, r9) @ vAA<- r0 6442 GOTO_OPCODE(ip) @ jump to next instruction 6443 /* 10-13 instructions */ 6444 6445 6446/* ------------------------------ */ 6447 .balign 64 6448.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6449/* File: armv5te/OP_MUL_INT_LIT16.S */ 6450/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6451/* File: armv5te/binopLit16.S */ 6452 /* 6453 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6454 * that specifies an instruction that performs "result = r0 op r1". 6455 * This could be an ARM instruction or a function call. (If the result 6456 * comes back in a register other than r0, you can override "result".) 6457 * 6458 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6459 * vCC (r1). Useful for integer division and modulus. 6460 * 6461 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6462 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6463 */ 6464 /* binop/lit16 vA, vB, #+CCCC */ 6465 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6466 mov r2, rINST, lsr #12 @ r2<- B 6467 mov r9, rINST, lsr #8 @ r9<- A+ 6468 GET_VREG(r0, r2) @ r0<- vB 6469 and r9, r9, #15 6470 .if 0 6471 cmp r1, #0 @ is second operand zero? 6472 beq common_errDivideByZero 6473 .endif 6474 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6475 6476 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6477 GET_INST_OPCODE(ip) @ extract opcode from rINST 6478 SET_VREG(r0, r9) @ vAA<- r0 6479 GOTO_OPCODE(ip) @ jump to next instruction 6480 /* 10-13 instructions */ 6481 6482 6483/* ------------------------------ */ 6484 .balign 64 6485.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6486/* File: armv5te/OP_DIV_INT_LIT16.S */ 6487/* File: armv5te/binopLit16.S */ 6488 /* 6489 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6490 * that specifies an instruction that performs "result = r0 op r1". 6491 * This could be an ARM instruction or a function call. (If the result 6492 * comes back in a register other than r0, you can override "result".) 6493 * 6494 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6495 * vCC (r1). Useful for integer division and modulus. 6496 * 6497 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6498 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6499 */ 6500 /* binop/lit16 vA, vB, #+CCCC */ 6501 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6502 mov r2, rINST, lsr #12 @ r2<- B 6503 mov r9, rINST, lsr #8 @ r9<- A+ 6504 GET_VREG(r0, r2) @ r0<- vB 6505 and r9, r9, #15 6506 .if 1 6507 cmp r1, #0 @ is second operand zero? 6508 beq common_errDivideByZero 6509 .endif 6510 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6511 6512 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6513 GET_INST_OPCODE(ip) @ extract opcode from rINST 6514 SET_VREG(r0, r9) @ vAA<- r0 6515 GOTO_OPCODE(ip) @ jump to next instruction 6516 /* 10-13 instructions */ 6517 6518 6519/* ------------------------------ */ 6520 .balign 64 6521.L_OP_REM_INT_LIT16: /* 0xd4 */ 6522/* File: armv5te/OP_REM_INT_LIT16.S */ 6523/* idivmod returns quotient in r0 and remainder in r1 */ 6524/* File: armv5te/binopLit16.S */ 6525 /* 6526 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6527 * that specifies an instruction that performs "result = r0 op r1". 6528 * This could be an ARM instruction or a function call. (If the result 6529 * comes back in a register other than r0, you can override "result".) 6530 * 6531 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6532 * vCC (r1). Useful for integer division and modulus. 6533 * 6534 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6535 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6536 */ 6537 /* binop/lit16 vA, vB, #+CCCC */ 6538 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6539 mov r2, rINST, lsr #12 @ r2<- B 6540 mov r9, rINST, lsr #8 @ r9<- A+ 6541 GET_VREG(r0, r2) @ r0<- vB 6542 and r9, r9, #15 6543 .if 1 6544 cmp r1, #0 @ is second operand zero? 6545 beq common_errDivideByZero 6546 .endif 6547 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6548 6549 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6550 GET_INST_OPCODE(ip) @ extract opcode from rINST 6551 SET_VREG(r1, r9) @ vAA<- r1 6552 GOTO_OPCODE(ip) @ jump to next instruction 6553 /* 10-13 instructions */ 6554 6555 6556/* ------------------------------ */ 6557 .balign 64 6558.L_OP_AND_INT_LIT16: /* 0xd5 */ 6559/* File: armv5te/OP_AND_INT_LIT16.S */ 6560/* File: armv5te/binopLit16.S */ 6561 /* 6562 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6563 * that specifies an instruction that performs "result = r0 op r1". 6564 * This could be an ARM instruction or a function call. (If the result 6565 * comes back in a register other than r0, you can override "result".) 6566 * 6567 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6568 * vCC (r1). Useful for integer division and modulus. 6569 * 6570 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6571 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6572 */ 6573 /* binop/lit16 vA, vB, #+CCCC */ 6574 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6575 mov r2, rINST, lsr #12 @ r2<- B 6576 mov r9, rINST, lsr #8 @ r9<- A+ 6577 GET_VREG(r0, r2) @ r0<- vB 6578 and r9, r9, #15 6579 .if 0 6580 cmp r1, #0 @ is second operand zero? 6581 beq common_errDivideByZero 6582 .endif 6583 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6584 6585 and r0, r0, r1 @ r0<- op, r0-r3 changed 6586 GET_INST_OPCODE(ip) @ extract opcode from rINST 6587 SET_VREG(r0, r9) @ vAA<- r0 6588 GOTO_OPCODE(ip) @ jump to next instruction 6589 /* 10-13 instructions */ 6590 6591 6592/* ------------------------------ */ 6593 .balign 64 6594.L_OP_OR_INT_LIT16: /* 0xd6 */ 6595/* File: armv5te/OP_OR_INT_LIT16.S */ 6596/* File: armv5te/binopLit16.S */ 6597 /* 6598 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6599 * that specifies an instruction that performs "result = r0 op r1". 6600 * This could be an ARM instruction or a function call. (If the result 6601 * comes back in a register other than r0, you can override "result".) 6602 * 6603 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6604 * vCC (r1). Useful for integer division and modulus. 6605 * 6606 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6607 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6608 */ 6609 /* binop/lit16 vA, vB, #+CCCC */ 6610 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6611 mov r2, rINST, lsr #12 @ r2<- B 6612 mov r9, rINST, lsr #8 @ r9<- A+ 6613 GET_VREG(r0, r2) @ r0<- vB 6614 and r9, r9, #15 6615 .if 0 6616 cmp r1, #0 @ is second operand zero? 6617 beq common_errDivideByZero 6618 .endif 6619 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6620 6621 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6622 GET_INST_OPCODE(ip) @ extract opcode from rINST 6623 SET_VREG(r0, r9) @ vAA<- r0 6624 GOTO_OPCODE(ip) @ jump to next instruction 6625 /* 10-13 instructions */ 6626 6627 6628/* ------------------------------ */ 6629 .balign 64 6630.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6631/* File: armv5te/OP_XOR_INT_LIT16.S */ 6632/* File: armv5te/binopLit16.S */ 6633 /* 6634 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6635 * that specifies an instruction that performs "result = r0 op r1". 6636 * This could be an ARM instruction or a function call. (If the result 6637 * comes back in a register other than r0, you can override "result".) 6638 * 6639 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6640 * vCC (r1). Useful for integer division and modulus. 6641 * 6642 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6643 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6644 */ 6645 /* binop/lit16 vA, vB, #+CCCC */ 6646 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6647 mov r2, rINST, lsr #12 @ r2<- B 6648 mov r9, rINST, lsr #8 @ r9<- A+ 6649 GET_VREG(r0, r2) @ r0<- vB 6650 and r9, r9, #15 6651 .if 0 6652 cmp r1, #0 @ is second operand zero? 6653 beq common_errDivideByZero 6654 .endif 6655 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6656 6657 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6658 GET_INST_OPCODE(ip) @ extract opcode from rINST 6659 SET_VREG(r0, r9) @ vAA<- r0 6660 GOTO_OPCODE(ip) @ jump to next instruction 6661 /* 10-13 instructions */ 6662 6663 6664/* ------------------------------ */ 6665 .balign 64 6666.L_OP_ADD_INT_LIT8: /* 0xd8 */ 6667/* File: armv5te/OP_ADD_INT_LIT8.S */ 6668/* File: armv5te/binopLit8.S */ 6669 /* 6670 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6671 * that specifies an instruction that performs "result = r0 op r1". 6672 * This could be an ARM instruction or a function call. (If the result 6673 * comes back in a register other than r0, you can override "result".) 6674 * 6675 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6676 * vCC (r1). Useful for integer division and modulus. 6677 * 6678 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6679 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6680 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6681 */ 6682 /* binop/lit8 vAA, vBB, #+CC */ 6683 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6684 mov r9, rINST, lsr #8 @ r9<- AA 6685 and r2, r3, #255 @ r2<- BB 6686 GET_VREG(r0, r2) @ r0<- vBB 6687 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6688 .if 0 6689 @cmp r1, #0 @ is second operand zero? 6690 beq common_errDivideByZero 6691 .endif 6692 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6693 6694 @ optional op; may set condition codes 6695 add r0, r0, r1 @ r0<- op, r0-r3 changed 6696 GET_INST_OPCODE(ip) @ extract opcode from rINST 6697 SET_VREG(r0, r9) @ vAA<- r0 6698 GOTO_OPCODE(ip) @ jump to next instruction 6699 /* 10-12 instructions */ 6700 6701 6702/* ------------------------------ */ 6703 .balign 64 6704.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 6705/* File: armv5te/OP_RSUB_INT_LIT8.S */ 6706/* File: armv5te/binopLit8.S */ 6707 /* 6708 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6709 * that specifies an instruction that performs "result = r0 op r1". 6710 * This could be an ARM instruction or a function call. (If the result 6711 * comes back in a register other than r0, you can override "result".) 6712 * 6713 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6714 * vCC (r1). Useful for integer division and modulus. 6715 * 6716 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6717 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6718 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6719 */ 6720 /* binop/lit8 vAA, vBB, #+CC */ 6721 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6722 mov r9, rINST, lsr #8 @ r9<- AA 6723 and r2, r3, #255 @ r2<- BB 6724 GET_VREG(r0, r2) @ r0<- vBB 6725 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6726 .if 0 6727 @cmp r1, #0 @ is second operand zero? 6728 beq common_errDivideByZero 6729 .endif 6730 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6731 6732 @ optional op; may set condition codes 6733 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6734 GET_INST_OPCODE(ip) @ extract opcode from rINST 6735 SET_VREG(r0, r9) @ vAA<- r0 6736 GOTO_OPCODE(ip) @ jump to next instruction 6737 /* 10-12 instructions */ 6738 6739 6740/* ------------------------------ */ 6741 .balign 64 6742.L_OP_MUL_INT_LIT8: /* 0xda */ 6743/* File: armv5te/OP_MUL_INT_LIT8.S */ 6744/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6745/* File: armv5te/binopLit8.S */ 6746 /* 6747 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6748 * that specifies an instruction that performs "result = r0 op r1". 6749 * This could be an ARM instruction or a function call. (If the result 6750 * comes back in a register other than r0, you can override "result".) 6751 * 6752 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6753 * vCC (r1). Useful for integer division and modulus. 6754 * 6755 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6756 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6757 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6758 */ 6759 /* binop/lit8 vAA, vBB, #+CC */ 6760 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6761 mov r9, rINST, lsr #8 @ r9<- AA 6762 and r2, r3, #255 @ r2<- BB 6763 GET_VREG(r0, r2) @ r0<- vBB 6764 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6765 .if 0 6766 @cmp r1, #0 @ is second operand zero? 6767 beq common_errDivideByZero 6768 .endif 6769 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6770 6771 @ optional op; may set condition codes 6772 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6773 GET_INST_OPCODE(ip) @ extract opcode from rINST 6774 SET_VREG(r0, r9) @ vAA<- r0 6775 GOTO_OPCODE(ip) @ jump to next instruction 6776 /* 10-12 instructions */ 6777 6778 6779/* ------------------------------ */ 6780 .balign 64 6781.L_OP_DIV_INT_LIT8: /* 0xdb */ 6782/* File: armv5te/OP_DIV_INT_LIT8.S */ 6783/* File: armv5te/binopLit8.S */ 6784 /* 6785 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6786 * that specifies an instruction that performs "result = r0 op r1". 6787 * This could be an ARM instruction or a function call. (If the result 6788 * comes back in a register other than r0, you can override "result".) 6789 * 6790 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6791 * vCC (r1). Useful for integer division and modulus. 6792 * 6793 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6794 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6795 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6796 */ 6797 /* binop/lit8 vAA, vBB, #+CC */ 6798 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6799 mov r9, rINST, lsr #8 @ r9<- AA 6800 and r2, r3, #255 @ r2<- BB 6801 GET_VREG(r0, r2) @ r0<- vBB 6802 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6803 .if 1 6804 @cmp r1, #0 @ is second operand zero? 6805 beq common_errDivideByZero 6806 .endif 6807 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6808 6809 @ optional op; may set condition codes 6810 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6811 GET_INST_OPCODE(ip) @ extract opcode from rINST 6812 SET_VREG(r0, r9) @ vAA<- r0 6813 GOTO_OPCODE(ip) @ jump to next instruction 6814 /* 10-12 instructions */ 6815 6816 6817/* ------------------------------ */ 6818 .balign 64 6819.L_OP_REM_INT_LIT8: /* 0xdc */ 6820/* File: armv5te/OP_REM_INT_LIT8.S */ 6821/* idivmod returns quotient in r0 and remainder in r1 */ 6822/* File: armv5te/binopLit8.S */ 6823 /* 6824 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6825 * that specifies an instruction that performs "result = r0 op r1". 6826 * This could be an ARM instruction or a function call. (If the result 6827 * comes back in a register other than r0, you can override "result".) 6828 * 6829 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6830 * vCC (r1). Useful for integer division and modulus. 6831 * 6832 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6833 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6834 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6835 */ 6836 /* binop/lit8 vAA, vBB, #+CC */ 6837 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6838 mov r9, rINST, lsr #8 @ r9<- AA 6839 and r2, r3, #255 @ r2<- BB 6840 GET_VREG(r0, r2) @ r0<- vBB 6841 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6842 .if 1 6843 @cmp r1, #0 @ is second operand zero? 6844 beq common_errDivideByZero 6845 .endif 6846 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6847 6848 @ optional op; may set condition codes 6849 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6850 GET_INST_OPCODE(ip) @ extract opcode from rINST 6851 SET_VREG(r1, r9) @ vAA<- r1 6852 GOTO_OPCODE(ip) @ jump to next instruction 6853 /* 10-12 instructions */ 6854 6855 6856/* ------------------------------ */ 6857 .balign 64 6858.L_OP_AND_INT_LIT8: /* 0xdd */ 6859/* File: armv5te/OP_AND_INT_LIT8.S */ 6860/* File: armv5te/binopLit8.S */ 6861 /* 6862 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6863 * that specifies an instruction that performs "result = r0 op r1". 6864 * This could be an ARM instruction or a function call. (If the result 6865 * comes back in a register other than r0, you can override "result".) 6866 * 6867 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6868 * vCC (r1). Useful for integer division and modulus. 6869 * 6870 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6871 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6872 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6873 */ 6874 /* binop/lit8 vAA, vBB, #+CC */ 6875 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6876 mov r9, rINST, lsr #8 @ r9<- AA 6877 and r2, r3, #255 @ r2<- BB 6878 GET_VREG(r0, r2) @ r0<- vBB 6879 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6880 .if 0 6881 @cmp r1, #0 @ is second operand zero? 6882 beq common_errDivideByZero 6883 .endif 6884 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6885 6886 @ optional op; may set condition codes 6887 and r0, r0, r1 @ r0<- op, r0-r3 changed 6888 GET_INST_OPCODE(ip) @ extract opcode from rINST 6889 SET_VREG(r0, r9) @ vAA<- r0 6890 GOTO_OPCODE(ip) @ jump to next instruction 6891 /* 10-12 instructions */ 6892 6893 6894/* ------------------------------ */ 6895 .balign 64 6896.L_OP_OR_INT_LIT8: /* 0xde */ 6897/* File: armv5te/OP_OR_INT_LIT8.S */ 6898/* File: armv5te/binopLit8.S */ 6899 /* 6900 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6901 * that specifies an instruction that performs "result = r0 op r1". 6902 * This could be an ARM instruction or a function call. (If the result 6903 * comes back in a register other than r0, you can override "result".) 6904 * 6905 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6906 * vCC (r1). Useful for integer division and modulus. 6907 * 6908 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6909 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6910 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6911 */ 6912 /* binop/lit8 vAA, vBB, #+CC */ 6913 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6914 mov r9, rINST, lsr #8 @ r9<- AA 6915 and r2, r3, #255 @ r2<- BB 6916 GET_VREG(r0, r2) @ r0<- vBB 6917 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6918 .if 0 6919 @cmp r1, #0 @ is second operand zero? 6920 beq common_errDivideByZero 6921 .endif 6922 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6923 6924 @ optional op; may set condition codes 6925 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6926 GET_INST_OPCODE(ip) @ extract opcode from rINST 6927 SET_VREG(r0, r9) @ vAA<- r0 6928 GOTO_OPCODE(ip) @ jump to next instruction 6929 /* 10-12 instructions */ 6930 6931 6932/* ------------------------------ */ 6933 .balign 64 6934.L_OP_XOR_INT_LIT8: /* 0xdf */ 6935/* File: armv5te/OP_XOR_INT_LIT8.S */ 6936/* File: armv5te/binopLit8.S */ 6937 /* 6938 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6939 * that specifies an instruction that performs "result = r0 op r1". 6940 * This could be an ARM instruction or a function call. (If the result 6941 * comes back in a register other than r0, you can override "result".) 6942 * 6943 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6944 * vCC (r1). Useful for integer division and modulus. 6945 * 6946 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6947 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6948 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6949 */ 6950 /* binop/lit8 vAA, vBB, #+CC */ 6951 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6952 mov r9, rINST, lsr #8 @ r9<- AA 6953 and r2, r3, #255 @ r2<- BB 6954 GET_VREG(r0, r2) @ r0<- vBB 6955 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6956 .if 0 6957 @cmp r1, #0 @ is second operand zero? 6958 beq common_errDivideByZero 6959 .endif 6960 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6961 6962 @ optional op; may set condition codes 6963 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6964 GET_INST_OPCODE(ip) @ extract opcode from rINST 6965 SET_VREG(r0, r9) @ vAA<- r0 6966 GOTO_OPCODE(ip) @ jump to next instruction 6967 /* 10-12 instructions */ 6968 6969 6970/* ------------------------------ */ 6971 .balign 64 6972.L_OP_SHL_INT_LIT8: /* 0xe0 */ 6973/* File: armv5te/OP_SHL_INT_LIT8.S */ 6974/* File: armv5te/binopLit8.S */ 6975 /* 6976 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6977 * that specifies an instruction that performs "result = r0 op r1". 6978 * This could be an ARM instruction or a function call. (If the result 6979 * comes back in a register other than r0, you can override "result".) 6980 * 6981 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6982 * vCC (r1). Useful for integer division and modulus. 6983 * 6984 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6985 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6986 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6987 */ 6988 /* binop/lit8 vAA, vBB, #+CC */ 6989 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6990 mov r9, rINST, lsr #8 @ r9<- AA 6991 and r2, r3, #255 @ r2<- BB 6992 GET_VREG(r0, r2) @ r0<- vBB 6993 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6994 .if 0 6995 @cmp r1, #0 @ is second operand zero? 6996 beq common_errDivideByZero 6997 .endif 6998 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6999 7000 and r1, r1, #31 @ optional op; may set condition codes 7001 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 7002 GET_INST_OPCODE(ip) @ extract opcode from rINST 7003 SET_VREG(r0, r9) @ vAA<- r0 7004 GOTO_OPCODE(ip) @ jump to next instruction 7005 /* 10-12 instructions */ 7006 7007 7008/* ------------------------------ */ 7009 .balign 64 7010.L_OP_SHR_INT_LIT8: /* 0xe1 */ 7011/* File: armv5te/OP_SHR_INT_LIT8.S */ 7012/* File: armv5te/binopLit8.S */ 7013 /* 7014 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7015 * that specifies an instruction that performs "result = r0 op r1". 7016 * This could be an ARM instruction or a function call. (If the result 7017 * comes back in a register other than r0, you can override "result".) 7018 * 7019 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7020 * vCC (r1). Useful for integer division and modulus. 7021 * 7022 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7023 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7024 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7025 */ 7026 /* binop/lit8 vAA, vBB, #+CC */ 7027 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7028 mov r9, rINST, lsr #8 @ r9<- AA 7029 and r2, r3, #255 @ r2<- BB 7030 GET_VREG(r0, r2) @ r0<- vBB 7031 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7032 .if 0 7033 @cmp r1, #0 @ is second operand zero? 7034 beq common_errDivideByZero 7035 .endif 7036 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7037 7038 and r1, r1, #31 @ optional op; may set condition codes 7039 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7040 GET_INST_OPCODE(ip) @ extract opcode from rINST 7041 SET_VREG(r0, r9) @ vAA<- r0 7042 GOTO_OPCODE(ip) @ jump to next instruction 7043 /* 10-12 instructions */ 7044 7045 7046/* ------------------------------ */ 7047 .balign 64 7048.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7049/* File: armv5te/OP_USHR_INT_LIT8.S */ 7050/* File: armv5te/binopLit8.S */ 7051 /* 7052 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7053 * that specifies an instruction that performs "result = r0 op r1". 7054 * This could be an ARM instruction or a function call. (If the result 7055 * comes back in a register other than r0, you can override "result".) 7056 * 7057 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7058 * vCC (r1). Useful for integer division and modulus. 7059 * 7060 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7061 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7062 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7063 */ 7064 /* binop/lit8 vAA, vBB, #+CC */ 7065 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7066 mov r9, rINST, lsr #8 @ r9<- AA 7067 and r2, r3, #255 @ r2<- BB 7068 GET_VREG(r0, r2) @ r0<- vBB 7069 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7070 .if 0 7071 @cmp r1, #0 @ is second operand zero? 7072 beq common_errDivideByZero 7073 .endif 7074 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7075 7076 and r1, r1, #31 @ optional op; may set condition codes 7077 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7078 GET_INST_OPCODE(ip) @ extract opcode from rINST 7079 SET_VREG(r0, r9) @ vAA<- r0 7080 GOTO_OPCODE(ip) @ jump to next instruction 7081 /* 10-12 instructions */ 7082 7083 7084/* ------------------------------ */ 7085 .balign 64 7086.L_OP_IGET_VOLATILE: /* 0xe3 */ 7087/* File: armv5te/OP_IGET_VOLATILE.S */ 7088/* File: armv5te/OP_IGET.S */ 7089 /* 7090 * General 32-bit instance field get. 7091 * 7092 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7093 */ 7094 /* op vA, vB, field@CCCC */ 7095 mov r0, rINST, lsr #12 @ r0<- B 7096 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7097 FETCH(r1, 1) @ r1<- field ref CCCC 7098 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7099 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7100 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7101 cmp r0, #0 @ is resolved entry null? 7102 bne .LOP_IGET_VOLATILE_finish @ no, already resolved 71038: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7104 EXPORT_PC() @ resolve() could throw 7105 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7106 bl dvmResolveInstField @ r0<- resolved InstField ptr 7107 cmp r0, #0 7108 bne .LOP_IGET_VOLATILE_finish 7109 b common_exceptionThrown 7110 7111 7112/* ------------------------------ */ 7113 .balign 64 7114.L_OP_IPUT_VOLATILE: /* 0xe4 */ 7115/* File: armv5te/OP_IPUT_VOLATILE.S */ 7116/* File: armv5te/OP_IPUT.S */ 7117 /* 7118 * General 32-bit instance field put. 7119 * 7120 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 7121 */ 7122 /* op vA, vB, field@CCCC */ 7123 mov r0, rINST, lsr #12 @ r0<- B 7124 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7125 FETCH(r1, 1) @ r1<- field ref CCCC 7126 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7127 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7128 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7129 cmp r0, #0 @ is resolved entry null? 7130 bne .LOP_IPUT_VOLATILE_finish @ no, already resolved 71318: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7132 EXPORT_PC() @ resolve() could throw 7133 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7134 bl dvmResolveInstField @ r0<- resolved InstField ptr 7135 cmp r0, #0 @ success? 7136 bne .LOP_IPUT_VOLATILE_finish @ yes, finish up 7137 b common_exceptionThrown 7138 7139 7140/* ------------------------------ */ 7141 .balign 64 7142.L_OP_SGET_VOLATILE: /* 0xe5 */ 7143/* File: armv5te/OP_SGET_VOLATILE.S */ 7144/* File: armv5te/OP_SGET.S */ 7145 /* 7146 * General 32-bit SGET handler. 7147 * 7148 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7149 */ 7150 /* op vAA, field@BBBB */ 7151 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7152 FETCH(r1, 1) @ r1<- field ref BBBB 7153 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7154 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7155 cmp r0, #0 @ is resolved entry null? 7156 beq .LOP_SGET_VOLATILE_resolve @ yes, do resolve 7157.LOP_SGET_VOLATILE_finish: @ field ptr in r0 7158 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7159 SMP_DMB @ acquiring load 7160 mov r2, rINST, lsr #8 @ r2<- AA 7161 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7162 SET_VREG(r1, r2) @ fp[AA]<- r1 7163 GET_INST_OPCODE(ip) @ extract opcode from rINST 7164 GOTO_OPCODE(ip) @ jump to next instruction 7165 7166 7167/* ------------------------------ */ 7168 .balign 64 7169.L_OP_SPUT_VOLATILE: /* 0xe6 */ 7170/* File: armv5te/OP_SPUT_VOLATILE.S */ 7171/* File: armv5te/OP_SPUT.S */ 7172 /* 7173 * General 32-bit SPUT handler. 7174 * 7175 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 7176 */ 7177 /* op vAA, field@BBBB */ 7178 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7179 FETCH(r1, 1) @ r1<- field ref BBBB 7180 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7181 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7182 cmp r0, #0 @ is resolved entry null? 7183 beq .LOP_SPUT_VOLATILE_resolve @ yes, do resolve 7184.LOP_SPUT_VOLATILE_finish: @ field ptr in r0 7185 mov r2, rINST, lsr #8 @ r2<- AA 7186 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7187 GET_VREG(r1, r2) @ r1<- fp[AA] 7188 GET_INST_OPCODE(ip) @ extract opcode from rINST 7189 SMP_DMB @ releasing store 7190 str r1, [r0, #offStaticField_value] @ field<- vAA 7191 GOTO_OPCODE(ip) @ jump to next instruction 7192 7193 7194/* ------------------------------ */ 7195 .balign 64 7196.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ 7197/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */ 7198/* File: armv5te/OP_IGET.S */ 7199 /* 7200 * General 32-bit instance field get. 7201 * 7202 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7203 */ 7204 /* op vA, vB, field@CCCC */ 7205 mov r0, rINST, lsr #12 @ r0<- B 7206 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7207 FETCH(r1, 1) @ r1<- field ref CCCC 7208 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7209 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7210 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7211 cmp r0, #0 @ is resolved entry null? 7212 bne .LOP_IGET_OBJECT_VOLATILE_finish @ no, already resolved 72138: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7214 EXPORT_PC() @ resolve() could throw 7215 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7216 bl dvmResolveInstField @ r0<- resolved InstField ptr 7217 cmp r0, #0 7218 bne .LOP_IGET_OBJECT_VOLATILE_finish 7219 b common_exceptionThrown 7220 7221 7222/* ------------------------------ */ 7223 .balign 64 7224.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */ 7225/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */ 7226/* File: armv5te/OP_IGET_WIDE.S */ 7227 /* 7228 * Wide 32-bit instance field get. 7229 */ 7230 /* iget-wide vA, vB, field@CCCC */ 7231 mov r0, rINST, lsr #12 @ r0<- B 7232 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7233 FETCH(r1, 1) @ r1<- field ref CCCC 7234 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7235 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7236 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7237 cmp r0, #0 @ is resolved entry null? 7238 bne .LOP_IGET_WIDE_VOLATILE_finish @ no, already resolved 72398: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7240 EXPORT_PC() @ resolve() could throw 7241 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7242 bl dvmResolveInstField @ r0<- resolved InstField ptr 7243 cmp r0, #0 7244 bne .LOP_IGET_WIDE_VOLATILE_finish 7245 b common_exceptionThrown 7246 7247 7248/* ------------------------------ */ 7249 .balign 64 7250.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */ 7251/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */ 7252/* File: armv5te/OP_IPUT_WIDE.S */ 7253 /* iput-wide vA, vB, field@CCCC */ 7254 mov r0, rINST, lsr #12 @ r0<- B 7255 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7256 FETCH(r1, 1) @ r1<- field ref CCCC 7257 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7258 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7259 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7260 cmp r0, #0 @ is resolved entry null? 7261 bne .LOP_IPUT_WIDE_VOLATILE_finish @ no, already resolved 72628: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7263 EXPORT_PC() @ resolve() could throw 7264 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7265 bl dvmResolveInstField @ r0<- resolved InstField ptr 7266 cmp r0, #0 @ success? 7267 bne .LOP_IPUT_WIDE_VOLATILE_finish @ yes, finish up 7268 b common_exceptionThrown 7269 7270 7271/* ------------------------------ */ 7272 .balign 64 7273.L_OP_SGET_WIDE_VOLATILE: /* 0xea */ 7274/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */ 7275/* File: armv5te/OP_SGET_WIDE.S */ 7276 /* 7277 * 64-bit SGET handler. 7278 */ 7279 /* sget-wide vAA, field@BBBB */ 7280 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7281 FETCH(r1, 1) @ r1<- field ref BBBB 7282 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7283 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7284 cmp r0, #0 @ is resolved entry null? 7285 beq .LOP_SGET_WIDE_VOLATILE_resolve @ yes, do resolve 7286.LOP_SGET_WIDE_VOLATILE_finish: 7287 mov r9, rINST, lsr #8 @ r9<- AA 7288 .if 1 7289 add r0, r0, #offStaticField_value @ r0<- pointer to data 7290 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 7291 .else 7292 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 7293 .endif 7294 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7295 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7296 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 7297 GET_INST_OPCODE(ip) @ extract opcode from rINST 7298 GOTO_OPCODE(ip) @ jump to next instruction 7299 7300 7301/* ------------------------------ */ 7302 .balign 64 7303.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */ 7304/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */ 7305/* File: armv5te/OP_SPUT_WIDE.S */ 7306 /* 7307 * 64-bit SPUT handler. 7308 */ 7309 /* sput-wide vAA, field@BBBB */ 7310 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 7311 FETCH(r1, 1) @ r1<- field ref BBBB 7312 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 7313 mov r9, rINST, lsr #8 @ r9<- AA 7314 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 7315 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7316 cmp r2, #0 @ is resolved entry null? 7317 beq .LOP_SPUT_WIDE_VOLATILE_resolve @ yes, do resolve 7318.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9 7319 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7320 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 7321 GET_INST_OPCODE(r10) @ extract opcode from rINST 7322 .if 1 7323 add r2, r2, #offStaticField_value @ r2<- pointer to data 7324 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 7325 .else 7326 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 7327 .endif 7328 GOTO_OPCODE(r10) @ jump to next instruction 7329 7330 7331/* ------------------------------ */ 7332 .balign 64 7333.L_OP_BREAKPOINT: /* 0xec */ 7334/* File: armv5te/OP_BREAKPOINT.S */ 7335/* File: armv5te/unused.S */ 7336 bl common_abort 7337 7338 7339/* ------------------------------ */ 7340 .balign 64 7341.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7342/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7343 /* 7344 * Handle a throw-verification-error instruction. This throws an 7345 * exception for an error discovered during verification. The 7346 * exception is indicated by AA, with some detail provided by BBBB. 7347 */ 7348 /* op AA, ref@BBBB */ 7349 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7350 FETCH(r2, 1) @ r2<- BBBB 7351 EXPORT_PC() @ export the PC 7352 mov r1, rINST, lsr #8 @ r1<- AA 7353 bl dvmThrowVerificationError @ always throws 7354 b common_exceptionThrown @ handle exception 7355 7356/* ------------------------------ */ 7357 .balign 64 7358.L_OP_EXECUTE_INLINE: /* 0xee */ 7359/* File: armv5te/OP_EXECUTE_INLINE.S */ 7360 /* 7361 * Execute a "native inline" instruction. 7362 * 7363 * We need to call an InlineOp4Func: 7364 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7365 * 7366 * The first four args are in r0-r3, pointer to return value storage 7367 * is on the stack. The function's return value is a flag that tells 7368 * us if an exception was thrown. 7369 */ 7370 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7371 FETCH(r10, 1) @ r10<- BBBB 7372 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7373 EXPORT_PC() @ can throw 7374 sub sp, sp, #8 @ make room for arg, +64 bit align 7375 mov r0, rINST, lsr #12 @ r0<- B 7376 str r1, [sp] @ push &glue->retval 7377 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7378 add sp, sp, #8 @ pop stack 7379 cmp r0, #0 @ test boolean result of inline 7380 beq common_exceptionThrown @ returned false, handle exception 7381 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7382 GET_INST_OPCODE(ip) @ extract opcode from rINST 7383 GOTO_OPCODE(ip) @ jump to next instruction 7384 7385/* ------------------------------ */ 7386 .balign 64 7387.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ 7388/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */ 7389 /* 7390 * Execute a "native inline" instruction, using "/range" semantics. 7391 * Same idea as execute-inline, but we get the args differently. 7392 * 7393 * We need to call an InlineOp4Func: 7394 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7395 * 7396 * The first four args are in r0-r3, pointer to return value storage 7397 * is on the stack. The function's return value is a flag that tells 7398 * us if an exception was thrown. 7399 */ 7400 /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */ 7401 FETCH(r10, 1) @ r10<- BBBB 7402 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7403 EXPORT_PC() @ can throw 7404 sub sp, sp, #8 @ make room for arg, +64 bit align 7405 mov r0, rINST, lsr #8 @ r0<- AA 7406 str r1, [sp] @ push &glue->retval 7407 bl .LOP_EXECUTE_INLINE_RANGE_continue @ make call; will return after 7408 add sp, sp, #8 @ pop stack 7409 cmp r0, #0 @ test boolean result of inline 7410 beq common_exceptionThrown @ returned false, handle exception 7411 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7412 GET_INST_OPCODE(ip) @ extract opcode from rINST 7413 GOTO_OPCODE(ip) @ jump to next instruction 7414 7415/* ------------------------------ */ 7416 .balign 64 7417.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7418/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7419 /* 7420 * invoke-direct-empty is a no-op in a "standard" interpreter. 7421 */ 7422 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7423 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7424 GOTO_OPCODE(ip) @ execute it 7425 7426/* ------------------------------ */ 7427 .balign 64 7428.L_OP_RETURN_VOID_BARRIER: /* 0xf1 */ 7429/* File: armv5te/OP_RETURN_VOID_BARRIER.S */ 7430 SMP_DMB_ST 7431 b common_returnFromMethod 7432 7433/* ------------------------------ */ 7434 .balign 64 7435.L_OP_IGET_QUICK: /* 0xf2 */ 7436/* File: armv5te/OP_IGET_QUICK.S */ 7437 /* For: iget-quick, iget-object-quick */ 7438 /* op vA, vB, offset@CCCC */ 7439 mov r2, rINST, lsr #12 @ r2<- B 7440 GET_VREG(r3, r2) @ r3<- object we're operating on 7441 FETCH(r1, 1) @ r1<- field byte offset 7442 cmp r3, #0 @ check object for null 7443 mov r2, rINST, lsr #8 @ r2<- A(+) 7444 beq common_errNullObject @ object was null 7445 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7446 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7447 and r2, r2, #15 7448 GET_INST_OPCODE(ip) @ extract opcode from rINST 7449 SET_VREG(r0, r2) @ fp[A]<- r0 7450 GOTO_OPCODE(ip) @ jump to next instruction 7451 7452/* ------------------------------ */ 7453 .balign 64 7454.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7455/* File: armv5te/OP_IGET_WIDE_QUICK.S */ 7456 /* iget-wide-quick vA, vB, offset@CCCC */ 7457 mov r2, rINST, lsr #12 @ r2<- B 7458 GET_VREG(r3, r2) @ r3<- object we're operating on 7459 FETCH(ip, 1) @ ip<- field byte offset 7460 cmp r3, #0 @ check object for null 7461 mov r2, rINST, lsr #8 @ r2<- A(+) 7462 beq common_errNullObject @ object was null 7463 ldrd r0, [r3, ip] @ r0<- obj.field (64 bits, aligned) 7464 and r2, r2, #15 7465 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7466 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7467 GET_INST_OPCODE(ip) @ extract opcode from rINST 7468 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7469 GOTO_OPCODE(ip) @ jump to next instruction 7470 7471/* ------------------------------ */ 7472 .balign 64 7473.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7474/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7475/* File: armv5te/OP_IGET_QUICK.S */ 7476 /* For: iget-quick, iget-object-quick */ 7477 /* op vA, vB, offset@CCCC */ 7478 mov r2, rINST, lsr #12 @ r2<- B 7479 GET_VREG(r3, r2) @ r3<- object we're operating on 7480 FETCH(r1, 1) @ r1<- field byte offset 7481 cmp r3, #0 @ check object for null 7482 mov r2, rINST, lsr #8 @ r2<- A(+) 7483 beq common_errNullObject @ object was null 7484 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7485 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7486 and r2, r2, #15 7487 GET_INST_OPCODE(ip) @ extract opcode from rINST 7488 SET_VREG(r0, r2) @ fp[A]<- r0 7489 GOTO_OPCODE(ip) @ jump to next instruction 7490 7491 7492/* ------------------------------ */ 7493 .balign 64 7494.L_OP_IPUT_QUICK: /* 0xf5 */ 7495/* File: armv5te/OP_IPUT_QUICK.S */ 7496 /* For: iput-quick */ 7497 /* op vA, vB, offset@CCCC */ 7498 mov r2, rINST, lsr #12 @ r2<- B 7499 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7500 FETCH(r1, 1) @ r1<- field byte offset 7501 cmp r3, #0 @ check object for null 7502 mov r2, rINST, lsr #8 @ r2<- A(+) 7503 beq common_errNullObject @ object was null 7504 and r2, r2, #15 7505 GET_VREG(r0, r2) @ r0<- fp[A] 7506 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7507 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7508 GET_INST_OPCODE(ip) @ extract opcode from rINST 7509 GOTO_OPCODE(ip) @ jump to next instruction 7510 7511/* ------------------------------ */ 7512 .balign 64 7513.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7514/* File: armv5te/OP_IPUT_WIDE_QUICK.S */ 7515 /* iput-wide-quick vA, vB, offset@CCCC */ 7516 mov r0, rINST, lsr #8 @ r0<- A(+) 7517 mov r1, rINST, lsr #12 @ r1<- B 7518 and r0, r0, #15 7519 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7520 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7521 cmp r2, #0 @ check object for null 7522 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7523 beq common_errNullObject @ object was null 7524 FETCH(r3, 1) @ r3<- field byte offset 7525 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7526 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7527 GET_INST_OPCODE(ip) @ extract opcode from rINST 7528 GOTO_OPCODE(ip) @ jump to next instruction 7529 7530/* ------------------------------ */ 7531 .balign 64 7532.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7533/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7534 /* For: iput-object-quick */ 7535 /* op vA, vB, offset@CCCC */ 7536 mov r2, rINST, lsr #12 @ r2<- B 7537 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7538 FETCH(r1, 1) @ r1<- field byte offset 7539 cmp r3, #0 @ check object for null 7540 mov r2, rINST, lsr #8 @ r2<- A(+) 7541 beq common_errNullObject @ object was null 7542 and r2, r2, #15 7543 GET_VREG(r0, r2) @ r0<- fp[A] 7544 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 7545 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7546 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7547 cmp r0, #0 7548 strneb r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head 7549 GET_INST_OPCODE(ip) @ extract opcode from rINST 7550 GOTO_OPCODE(ip) @ jump to next instruction 7551 7552/* ------------------------------ */ 7553 .balign 64 7554.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7555/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7556 /* 7557 * Handle an optimized virtual method call. 7558 * 7559 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7560 */ 7561 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7562 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7563 FETCH(r3, 2) @ r3<- FEDC or CCCC 7564 FETCH(r1, 1) @ r1<- BBBB 7565 .if (!0) 7566 and r3, r3, #15 @ r3<- C (or stays CCCC) 7567 .endif 7568 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7569 cmp r2, #0 @ is "this" null? 7570 beq common_errNullObject @ null "this", throw exception 7571 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7572 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7573 EXPORT_PC() @ invoke must export 7574 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7575 bl common_invokeMethodNoRange @ continue on 7576 7577/* ------------------------------ */ 7578 .balign 64 7579.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7580/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7581/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7582 /* 7583 * Handle an optimized virtual method call. 7584 * 7585 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7586 */ 7587 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7588 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7589 FETCH(r3, 2) @ r3<- FEDC or CCCC 7590 FETCH(r1, 1) @ r1<- BBBB 7591 .if (!1) 7592 and r3, r3, #15 @ r3<- C (or stays CCCC) 7593 .endif 7594 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7595 cmp r2, #0 @ is "this" null? 7596 beq common_errNullObject @ null "this", throw exception 7597 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7598 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7599 EXPORT_PC() @ invoke must export 7600 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7601 bl common_invokeMethodRange @ continue on 7602 7603 7604/* ------------------------------ */ 7605 .balign 64 7606.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7607/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7608 /* 7609 * Handle an optimized "super" method call. 7610 * 7611 * for: [opt] invoke-super-quick, invoke-super-quick/range 7612 */ 7613 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7614 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7615 FETCH(r10, 2) @ r10<- GFED or CCCC 7616 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7617 .if (!0) 7618 and r10, r10, #15 @ r10<- D (or stays CCCC) 7619 .endif 7620 FETCH(r1, 1) @ r1<- BBBB 7621 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7622 EXPORT_PC() @ must export for invoke 7623 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7624 GET_VREG(r3, r10) @ r3<- "this" 7625 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7626 cmp r3, #0 @ null "this" ref? 7627 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7628 beq common_errNullObject @ "this" is null, throw exception 7629 bl common_invokeMethodNoRange @ continue on 7630 7631/* ------------------------------ */ 7632 .balign 64 7633.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7634/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7635/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7636 /* 7637 * Handle an optimized "super" method call. 7638 * 7639 * for: [opt] invoke-super-quick, invoke-super-quick/range 7640 */ 7641 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7642 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7643 FETCH(r10, 2) @ r10<- GFED or CCCC 7644 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7645 .if (!1) 7646 and r10, r10, #15 @ r10<- D (or stays CCCC) 7647 .endif 7648 FETCH(r1, 1) @ r1<- BBBB 7649 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7650 EXPORT_PC() @ must export for invoke 7651 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7652 GET_VREG(r3, r10) @ r3<- "this" 7653 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7654 cmp r3, #0 @ null "this" ref? 7655 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7656 beq common_errNullObject @ "this" is null, throw exception 7657 bl common_invokeMethodRange @ continue on 7658 7659 7660/* ------------------------------ */ 7661 .balign 64 7662.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ 7663/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */ 7664/* File: armv5te/OP_IPUT_OBJECT.S */ 7665 /* 7666 * 32-bit instance field put. 7667 * 7668 * for: iput-object, iput-object-volatile 7669 */ 7670 /* op vA, vB, field@CCCC */ 7671 mov r0, rINST, lsr #12 @ r0<- B 7672 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7673 FETCH(r1, 1) @ r1<- field ref CCCC 7674 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7675 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7676 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7677 cmp r0, #0 @ is resolved entry null? 7678 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ no, already resolved 76798: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7680 EXPORT_PC() @ resolve() could throw 7681 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7682 bl dvmResolveInstField @ r0<- resolved InstField ptr 7683 cmp r0, #0 @ success? 7684 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ yes, finish up 7685 b common_exceptionThrown 7686 7687 7688/* ------------------------------ */ 7689 .balign 64 7690.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ 7691/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */ 7692/* File: armv5te/OP_SGET.S */ 7693 /* 7694 * General 32-bit SGET handler. 7695 * 7696 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7697 */ 7698 /* op vAA, field@BBBB */ 7699 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7700 FETCH(r1, 1) @ r1<- field ref BBBB 7701 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7702 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7703 cmp r0, #0 @ is resolved entry null? 7704 beq .LOP_SGET_OBJECT_VOLATILE_resolve @ yes, do resolve 7705.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0 7706 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7707 SMP_DMB @ acquiring load 7708 mov r2, rINST, lsr #8 @ r2<- AA 7709 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7710 SET_VREG(r1, r2) @ fp[AA]<- r1 7711 GET_INST_OPCODE(ip) @ extract opcode from rINST 7712 GOTO_OPCODE(ip) @ jump to next instruction 7713 7714 7715/* ------------------------------ */ 7716 .balign 64 7717.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ 7718/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */ 7719/* File: armv5te/OP_SPUT_OBJECT.S */ 7720 /* 7721 * 32-bit SPUT handler for objects 7722 * 7723 * for: sput-object, sput-object-volatile 7724 */ 7725 /* op vAA, field@BBBB */ 7726 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7727 FETCH(r1, 1) @ r1<- field ref BBBB 7728 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7729 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7730 cmp r0, #0 @ is resolved entry null? 7731 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ no, continue 7732 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 7733 EXPORT_PC() @ resolve() could throw, so export now 7734 ldr r0, [r9, #offMethod_clazz] @ r0<- method->clazz 7735 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 7736 cmp r0, #0 @ success? 7737 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish 7738 b common_exceptionThrown @ no, handle exception 7739 7740 7741 7742/* ------------------------------ */ 7743 .balign 64 7744.L_OP_DISPATCH_FF: /* 0xff */ 7745/* File: armv5te/OP_DISPATCH_FF.S */ 7746/* File: armv5te/unused.S */ 7747 bl common_abort 7748 7749 7750 7751 .balign 64 7752 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7753 .global dvmAsmInstructionEnd 7754dvmAsmInstructionEnd: 7755 7756/* 7757 * =========================================================================== 7758 * Sister implementations 7759 * =========================================================================== 7760 */ 7761 .global dvmAsmSisterStart 7762 .type dvmAsmSisterStart, %function 7763 .text 7764 .balign 4 7765dvmAsmSisterStart: 7766 7767/* continuation for OP_CONST_STRING */ 7768 7769 /* 7770 * Continuation if the String has not yet been resolved. 7771 * r1: BBBB (String ref) 7772 * r9: target register 7773 */ 7774.LOP_CONST_STRING_resolve: 7775 EXPORT_PC() 7776 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7777 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7778 bl dvmResolveString @ r0<- String reference 7779 cmp r0, #0 @ failed? 7780 beq common_exceptionThrown @ yup, handle the exception 7781 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7782 GET_INST_OPCODE(ip) @ extract opcode from rINST 7783 SET_VREG(r0, r9) @ vAA<- r0 7784 GOTO_OPCODE(ip) @ jump to next instruction 7785 7786/* continuation for OP_CONST_STRING_JUMBO */ 7787 7788 /* 7789 * Continuation if the String has not yet been resolved. 7790 * r1: BBBBBBBB (String ref) 7791 * r9: target register 7792 */ 7793.LOP_CONST_STRING_JUMBO_resolve: 7794 EXPORT_PC() 7795 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7796 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7797 bl dvmResolveString @ r0<- String reference 7798 cmp r0, #0 @ failed? 7799 beq common_exceptionThrown @ yup, handle the exception 7800 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7801 GET_INST_OPCODE(ip) @ extract opcode from rINST 7802 SET_VREG(r0, r9) @ vAA<- r0 7803 GOTO_OPCODE(ip) @ jump to next instruction 7804 7805/* continuation for OP_CONST_CLASS */ 7806 7807 /* 7808 * Continuation if the Class has not yet been resolved. 7809 * r1: BBBB (Class ref) 7810 * r9: target register 7811 */ 7812.LOP_CONST_CLASS_resolve: 7813 EXPORT_PC() 7814 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7815 mov r2, #1 @ r2<- true 7816 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7817 bl dvmResolveClass @ r0<- Class reference 7818 cmp r0, #0 @ failed? 7819 beq common_exceptionThrown @ yup, handle the exception 7820 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7821 GET_INST_OPCODE(ip) @ extract opcode from rINST 7822 SET_VREG(r0, r9) @ vAA<- r0 7823 GOTO_OPCODE(ip) @ jump to next instruction 7824 7825/* continuation for OP_CHECK_CAST */ 7826 7827 /* 7828 * Trivial test failed, need to perform full check. This is common. 7829 * r0 holds obj->clazz 7830 * r1 holds desired class resolved from BBBB 7831 * r9 holds object 7832 */ 7833.LOP_CHECK_CAST_fullcheck: 7834 mov r10, r1 @ avoid ClassObject getting clobbered 7835 bl dvmInstanceofNonTrivial @ r0<- boolean result 7836 cmp r0, #0 @ failed? 7837 bne .LOP_CHECK_CAST_okay @ no, success 7838 7839 @ A cast has failed. We need to throw a ClassCastException. 7840 EXPORT_PC() @ about to throw 7841 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz (actual class) 7842 mov r1, r10 @ r1<- desired class 7843 bl dvmThrowClassCastException 7844 b common_exceptionThrown 7845 7846 /* 7847 * Resolution required. This is the least-likely path. 7848 * 7849 * r2 holds BBBB 7850 * r9 holds object 7851 */ 7852.LOP_CHECK_CAST_resolve: 7853 EXPORT_PC() @ resolve() could throw 7854 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7855 mov r1, r2 @ r1<- BBBB 7856 mov r2, #0 @ r2<- false 7857 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7858 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7859 cmp r0, #0 @ got null? 7860 beq common_exceptionThrown @ yes, handle exception 7861 mov r1, r0 @ r1<- class resolved from BBB 7862 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7863 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7864 7865/* continuation for OP_INSTANCE_OF */ 7866 7867 /* 7868 * Trivial test failed, need to perform full check. This is common. 7869 * r0 holds obj->clazz 7870 * r1 holds class resolved from BBBB 7871 * r9 holds A 7872 */ 7873.LOP_INSTANCE_OF_fullcheck: 7874 bl dvmInstanceofNonTrivial @ r0<- boolean result 7875 @ fall through to OP_INSTANCE_OF_store 7876 7877 /* 7878 * r0 holds boolean result 7879 * r9 holds A 7880 */ 7881.LOP_INSTANCE_OF_store: 7882 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7883 SET_VREG(r0, r9) @ vA<- r0 7884 GET_INST_OPCODE(ip) @ extract opcode from rINST 7885 GOTO_OPCODE(ip) @ jump to next instruction 7886 7887 /* 7888 * Trivial test succeeded, save and bail. 7889 * r9 holds A 7890 */ 7891.LOP_INSTANCE_OF_trivial: 7892 mov r0, #1 @ indicate success 7893 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7894 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7895 SET_VREG(r0, r9) @ vA<- r0 7896 GET_INST_OPCODE(ip) @ extract opcode from rINST 7897 GOTO_OPCODE(ip) @ jump to next instruction 7898 7899 /* 7900 * Resolution required. This is the least-likely path. 7901 * 7902 * r3 holds BBBB 7903 * r9 holds A 7904 */ 7905.LOP_INSTANCE_OF_resolve: 7906 EXPORT_PC() @ resolve() could throw 7907 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7908 mov r1, r3 @ r1<- BBBB 7909 mov r2, #1 @ r2<- true 7910 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7911 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7912 cmp r0, #0 @ got null? 7913 beq common_exceptionThrown @ yes, handle exception 7914 mov r1, r0 @ r1<- class resolved from BBB 7915 mov r3, rINST, lsr #12 @ r3<- B 7916 GET_VREG(r0, r3) @ r0<- vB (object) 7917 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7918 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7919 7920/* continuation for OP_NEW_INSTANCE */ 7921 7922 .balign 32 @ minimize cache lines 7923.LOP_NEW_INSTANCE_finish: @ r0=new object 7924 mov r3, rINST, lsr #8 @ r3<- AA 7925 cmp r0, #0 @ failed? 7926 beq common_exceptionThrown @ yes, handle the exception 7927 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7928 GET_INST_OPCODE(ip) @ extract opcode from rINST 7929 SET_VREG(r0, r3) @ vAA<- r0 7930 GOTO_OPCODE(ip) @ jump to next instruction 7931 7932 /* 7933 * Class initialization required. 7934 * 7935 * r0 holds class object 7936 */ 7937.LOP_NEW_INSTANCE_needinit: 7938 mov r9, r0 @ save r0 7939 bl dvmInitClass @ initialize class 7940 cmp r0, #0 @ check boolean result 7941 mov r0, r9 @ restore r0 7942 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7943 b common_exceptionThrown @ failed, deal with init exception 7944 7945 /* 7946 * Resolution required. This is the least-likely path. 7947 * 7948 * r1 holds BBBB 7949 */ 7950.LOP_NEW_INSTANCE_resolve: 7951 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7952 mov r2, #0 @ r2<- false 7953 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7954 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7955 cmp r0, #0 @ got null? 7956 bne .LOP_NEW_INSTANCE_resolved @ no, continue 7957 b common_exceptionThrown @ yes, handle exception 7958 7959.LstrInstantiationErrorPtr: 7960 .word .LstrInstantiationError 7961 7962/* continuation for OP_NEW_ARRAY */ 7963 7964 7965 /* 7966 * Resolve class. (This is an uncommon case.) 7967 * 7968 * r1 holds array length 7969 * r2 holds class ref CCCC 7970 */ 7971.LOP_NEW_ARRAY_resolve: 7972 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7973 mov r9, r1 @ r9<- length (save) 7974 mov r1, r2 @ r1<- CCCC 7975 mov r2, #0 @ r2<- false 7976 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7977 bl dvmResolveClass @ r0<- call(clazz, ref) 7978 cmp r0, #0 @ got null? 7979 mov r1, r9 @ r1<- length (restore) 7980 beq common_exceptionThrown @ yes, handle exception 7981 @ fall through to OP_NEW_ARRAY_finish 7982 7983 /* 7984 * Finish allocation. 7985 * 7986 * r0 holds class 7987 * r1 holds array length 7988 */ 7989.LOP_NEW_ARRAY_finish: 7990 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 7991 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 7992 cmp r0, #0 @ failed? 7993 mov r2, rINST, lsr #8 @ r2<- A+ 7994 beq common_exceptionThrown @ yes, handle the exception 7995 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7996 and r2, r2, #15 @ r2<- A 7997 GET_INST_OPCODE(ip) @ extract opcode from rINST 7998 SET_VREG(r0, r2) @ vA<- r0 7999 GOTO_OPCODE(ip) @ jump to next instruction 8000 8001/* continuation for OP_FILLED_NEW_ARRAY */ 8002 8003 /* 8004 * On entry: 8005 * r0 holds array class 8006 * r10 holds AA or BA 8007 */ 8008.LOP_FILLED_NEW_ARRAY_continue: 8009 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8010 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8011 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 8012 .if 0 8013 mov r1, r10 @ r1<- AA (length) 8014 .else 8015 mov r1, r10, lsr #4 @ r1<- B (length) 8016 .endif 8017 cmp rINST, #'I' @ array of ints? 8018 cmpne rINST, #'L' @ array of objects? 8019 cmpne rINST, #'[' @ array of arrays? 8020 mov r9, r1 @ save length in r9 8021 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 8022 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8023 cmp r0, #0 @ null return? 8024 beq common_exceptionThrown @ alloc failed, handle exception 8025 8026 FETCH(r1, 2) @ r1<- FEDC or CCCC 8027 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8028 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 8029 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8030 subs r9, r9, #1 @ length--, check for neg 8031 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8032 bmi 2f @ was zero, bail 8033 8034 @ copy values from registers into the array 8035 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8036 .if 0 8037 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 80381: ldr r3, [r2], #4 @ r3<- *r2++ 8039 subs r9, r9, #1 @ count-- 8040 str r3, [r0], #4 @ *contents++ = vX 8041 bpl 1b 8042 @ continue at 2 8043 .else 8044 cmp r9, #4 @ length was initially 5? 8045 and r2, r10, #15 @ r2<- A 8046 bne 1f @ <= 4 args, branch 8047 GET_VREG(r3, r2) @ r3<- vA 8048 sub r9, r9, #1 @ count-- 8049 str r3, [r0, #16] @ contents[4] = vA 80501: and r2, r1, #15 @ r2<- F/E/D/C 8051 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8052 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8053 subs r9, r9, #1 @ count-- 8054 str r3, [r0], #4 @ *contents++ = vX 8055 bpl 1b 8056 @ continue at 2 8057 .endif 8058 80592: 8060 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 8061 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 8062 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8063 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8064 cmp r1, #'I' @ Is int array? 8065 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 8066 GOTO_OPCODE(ip) @ execute it 8067 8068 /* 8069 * Throw an exception indicating that we have not implemented this 8070 * mode of filled-new-array. 8071 */ 8072.LOP_FILLED_NEW_ARRAY_notimpl: 8073 ldr r0, .L_strInternalError 8074 ldr r1, .L_strFilledNewArrayNotImpl 8075 bl dvmThrowException 8076 b common_exceptionThrown 8077 8078 .if (!0) @ define in one or the other, not both 8079.L_strFilledNewArrayNotImpl: 8080 .word .LstrFilledNewArrayNotImpl 8081.L_strInternalError: 8082 .word .LstrInternalError 8083 .endif 8084 8085/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 8086 8087 /* 8088 * On entry: 8089 * r0 holds array class 8090 * r10 holds AA or BA 8091 */ 8092.LOP_FILLED_NEW_ARRAY_RANGE_continue: 8093 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8094 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8095 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 8096 .if 1 8097 mov r1, r10 @ r1<- AA (length) 8098 .else 8099 mov r1, r10, lsr #4 @ r1<- B (length) 8100 .endif 8101 cmp rINST, #'I' @ array of ints? 8102 cmpne rINST, #'L' @ array of objects? 8103 cmpne rINST, #'[' @ array of arrays? 8104 mov r9, r1 @ save length in r9 8105 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 8106 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8107 cmp r0, #0 @ null return? 8108 beq common_exceptionThrown @ alloc failed, handle exception 8109 8110 FETCH(r1, 2) @ r1<- FEDC or CCCC 8111 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8112 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 8113 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8114 subs r9, r9, #1 @ length--, check for neg 8115 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8116 bmi 2f @ was zero, bail 8117 8118 @ copy values from registers into the array 8119 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8120 .if 1 8121 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 81221: ldr r3, [r2], #4 @ r3<- *r2++ 8123 subs r9, r9, #1 @ count-- 8124 str r3, [r0], #4 @ *contents++ = vX 8125 bpl 1b 8126 @ continue at 2 8127 .else 8128 cmp r9, #4 @ length was initially 5? 8129 and r2, r10, #15 @ r2<- A 8130 bne 1f @ <= 4 args, branch 8131 GET_VREG(r3, r2) @ r3<- vA 8132 sub r9, r9, #1 @ count-- 8133 str r3, [r0, #16] @ contents[4] = vA 81341: and r2, r1, #15 @ r2<- F/E/D/C 8135 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8136 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8137 subs r9, r9, #1 @ count-- 8138 str r3, [r0], #4 @ *contents++ = vX 8139 bpl 1b 8140 @ continue at 2 8141 .endif 8142 81432: 8144 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 8145 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 8146 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8147 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8148 cmp r1, #'I' @ Is int array? 8149 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 8150 GOTO_OPCODE(ip) @ execute it 8151 8152 /* 8153 * Throw an exception indicating that we have not implemented this 8154 * mode of filled-new-array. 8155 */ 8156.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8157 ldr r0, .L_strInternalError 8158 ldr r1, .L_strFilledNewArrayNotImpl 8159 bl dvmThrowException 8160 b common_exceptionThrown 8161 8162 .if (!1) @ define in one or the other, not both 8163.L_strFilledNewArrayNotImpl: 8164 .word .LstrFilledNewArrayNotImpl 8165.L_strInternalError: 8166 .word .LstrInternalError 8167 .endif 8168 8169/* continuation for OP_CMPL_FLOAT */ 8170.LOP_CMPL_FLOAT_finish: 8171 SET_VREG(r0, r9) @ vAA<- r0 8172 GOTO_OPCODE(ip) @ jump to next instruction 8173 8174/* continuation for OP_CMPG_FLOAT */ 8175.LOP_CMPG_FLOAT_finish: 8176 SET_VREG(r0, r9) @ vAA<- r0 8177 GOTO_OPCODE(ip) @ jump to next instruction 8178 8179/* continuation for OP_CMPL_DOUBLE */ 8180.LOP_CMPL_DOUBLE_finish: 8181 SET_VREG(r0, r9) @ vAA<- r0 8182 GOTO_OPCODE(ip) @ jump to next instruction 8183 8184/* continuation for OP_CMPG_DOUBLE */ 8185.LOP_CMPG_DOUBLE_finish: 8186 SET_VREG(r0, r9) @ vAA<- r0 8187 GOTO_OPCODE(ip) @ jump to next instruction 8188 8189/* continuation for OP_CMP_LONG */ 8190 8191.LOP_CMP_LONG_less: 8192 mvn r1, #0 @ r1<- -1 8193 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8194 @ instead, we just replicate the tail end. 8195 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8196 SET_VREG(r1, r9) @ vAA<- r1 8197 GET_INST_OPCODE(ip) @ extract opcode from rINST 8198 GOTO_OPCODE(ip) @ jump to next instruction 8199 8200.LOP_CMP_LONG_greater: 8201 mov r1, #1 @ r1<- 1 8202 @ fall through to _finish 8203 8204.LOP_CMP_LONG_finish: 8205 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8206 SET_VREG(r1, r9) @ vAA<- r1 8207 GET_INST_OPCODE(ip) @ extract opcode from rINST 8208 GOTO_OPCODE(ip) @ jump to next instruction 8209 8210/* continuation for OP_AGET_WIDE */ 8211 8212.LOP_AGET_WIDE_finish: 8213 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8214 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8215 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8216 GET_INST_OPCODE(ip) @ extract opcode from rINST 8217 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8218 GOTO_OPCODE(ip) @ jump to next instruction 8219 8220/* continuation for OP_APUT_WIDE */ 8221 8222.LOP_APUT_WIDE_finish: 8223 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8224 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8225 GET_INST_OPCODE(ip) @ extract opcode from rINST 8226 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8227 GOTO_OPCODE(ip) @ jump to next instruction 8228 8229/* continuation for OP_APUT_OBJECT */ 8230 /* 8231 * On entry: 8232 * rINST = vBB (arrayObj) 8233 * r9 = vAA (obj) 8234 * r10 = offset into array (vBB + vCC * width) 8235 */ 8236.LOP_APUT_OBJECT_finish: 8237 cmp r9, #0 @ storing null reference? 8238 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8239 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8240 ldr r1, [rINST, #offObject_clazz] @ r1<- arrayObj->clazz 8241 bl dvmCanPutArrayElement @ test object type vs. array type 8242 cmp r0, #0 @ okay? 8243 beq .LOP_APUT_OBJECT_throw @ no 8244 mov r1, rINST @ r1<- arrayObj 8245 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8246 ldr r2, [rGLUE, #offGlue_cardTable] @ get biased CT base 8247 add r10, #offArrayObject_contents @ r0<- pointer to slot 8248 GET_INST_OPCODE(ip) @ extract opcode from rINST 8249 str r9, [r10] @ vBB[vCC]<- vAA 8250 strb r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head 8251 GOTO_OPCODE(ip) @ jump to next instruction 8252.LOP_APUT_OBJECT_skip_check: 8253 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8254 GET_INST_OPCODE(ip) @ extract opcode from rINST 8255 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8256 GOTO_OPCODE(ip) @ jump to next instruction 8257.LOP_APUT_OBJECT_throw: 8258 @ The types don't match. We need to throw an ArrayStoreException. 8259 ldr r0, [r9, #offObject_clazz] 8260 ldr r1, [rINST, #offObject_clazz] 8261 EXPORT_PC() 8262 bl dvmThrowArrayStoreException 8263 b common_exceptionThrown 8264 8265/* continuation for OP_IGET */ 8266 8267 /* 8268 * Currently: 8269 * r0 holds resolved field 8270 * r9 holds object 8271 */ 8272.LOP_IGET_finish: 8273 @bl common_squeak0 8274 cmp r9, #0 @ check object for null 8275 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8276 beq common_errNullObject @ object was null 8277 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8278 @ no-op @ acquiring load 8279 mov r2, rINST, lsr #8 @ r2<- A+ 8280 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8281 and r2, r2, #15 @ r2<- A 8282 GET_INST_OPCODE(ip) @ extract opcode from rINST 8283 SET_VREG(r0, r2) @ fp[A]<- r0 8284 GOTO_OPCODE(ip) @ jump to next instruction 8285 8286/* continuation for OP_IGET_WIDE */ 8287 8288 /* 8289 * Currently: 8290 * r0 holds resolved field 8291 * r9 holds object 8292 */ 8293.LOP_IGET_WIDE_finish: 8294 cmp r9, #0 @ check object for null 8295 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8296 beq common_errNullObject @ object was null 8297 .if 0 8298 add r0, r9, r3 @ r0<- address of field 8299 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 8300 .else 8301 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8302 .endif 8303 mov r2, rINST, lsr #8 @ r2<- A+ 8304 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8305 and r2, r2, #15 @ r2<- A 8306 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8307 GET_INST_OPCODE(ip) @ extract opcode from rINST 8308 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8309 GOTO_OPCODE(ip) @ jump to next instruction 8310 8311/* continuation for OP_IGET_OBJECT */ 8312 8313 /* 8314 * Currently: 8315 * r0 holds resolved field 8316 * r9 holds object 8317 */ 8318.LOP_IGET_OBJECT_finish: 8319 @bl common_squeak0 8320 cmp r9, #0 @ check object for null 8321 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8322 beq common_errNullObject @ object was null 8323 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8324 @ no-op @ acquiring load 8325 mov r2, rINST, lsr #8 @ r2<- A+ 8326 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8327 and r2, r2, #15 @ r2<- A 8328 GET_INST_OPCODE(ip) @ extract opcode from rINST 8329 SET_VREG(r0, r2) @ fp[A]<- r0 8330 GOTO_OPCODE(ip) @ jump to next instruction 8331 8332/* continuation for OP_IGET_BOOLEAN */ 8333 8334 /* 8335 * Currently: 8336 * r0 holds resolved field 8337 * r9 holds object 8338 */ 8339.LOP_IGET_BOOLEAN_finish: 8340 @bl common_squeak1 8341 cmp r9, #0 @ check object for null 8342 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8343 beq common_errNullObject @ object was null 8344 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8345 @ no-op @ acquiring load 8346 mov r2, rINST, lsr #8 @ r2<- A+ 8347 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8348 and r2, r2, #15 @ r2<- A 8349 GET_INST_OPCODE(ip) @ extract opcode from rINST 8350 SET_VREG(r0, r2) @ fp[A]<- r0 8351 GOTO_OPCODE(ip) @ jump to next instruction 8352 8353/* continuation for OP_IGET_BYTE */ 8354 8355 /* 8356 * Currently: 8357 * r0 holds resolved field 8358 * r9 holds object 8359 */ 8360.LOP_IGET_BYTE_finish: 8361 @bl common_squeak2 8362 cmp r9, #0 @ check object for null 8363 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8364 beq common_errNullObject @ object was null 8365 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8366 @ no-op @ acquiring load 8367 mov r2, rINST, lsr #8 @ r2<- A+ 8368 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8369 and r2, r2, #15 @ r2<- A 8370 GET_INST_OPCODE(ip) @ extract opcode from rINST 8371 SET_VREG(r0, r2) @ fp[A]<- r0 8372 GOTO_OPCODE(ip) @ jump to next instruction 8373 8374/* continuation for OP_IGET_CHAR */ 8375 8376 /* 8377 * Currently: 8378 * r0 holds resolved field 8379 * r9 holds object 8380 */ 8381.LOP_IGET_CHAR_finish: 8382 @bl common_squeak3 8383 cmp r9, #0 @ check object for null 8384 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8385 beq common_errNullObject @ object was null 8386 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8387 @ no-op @ acquiring load 8388 mov r2, rINST, lsr #8 @ r2<- A+ 8389 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8390 and r2, r2, #15 @ r2<- A 8391 GET_INST_OPCODE(ip) @ extract opcode from rINST 8392 SET_VREG(r0, r2) @ fp[A]<- r0 8393 GOTO_OPCODE(ip) @ jump to next instruction 8394 8395/* continuation for OP_IGET_SHORT */ 8396 8397 /* 8398 * Currently: 8399 * r0 holds resolved field 8400 * r9 holds object 8401 */ 8402.LOP_IGET_SHORT_finish: 8403 @bl common_squeak4 8404 cmp r9, #0 @ check object for null 8405 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8406 beq common_errNullObject @ object was null 8407 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8408 @ no-op @ acquiring load 8409 mov r2, rINST, lsr #8 @ r2<- A+ 8410 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8411 and r2, r2, #15 @ r2<- A 8412 GET_INST_OPCODE(ip) @ extract opcode from rINST 8413 SET_VREG(r0, r2) @ fp[A]<- r0 8414 GOTO_OPCODE(ip) @ jump to next instruction 8415 8416/* continuation for OP_IPUT */ 8417 8418 /* 8419 * Currently: 8420 * r0 holds resolved field 8421 * r9 holds object 8422 */ 8423.LOP_IPUT_finish: 8424 @bl common_squeak0 8425 mov r1, rINST, lsr #8 @ r1<- A+ 8426 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8427 and r1, r1, #15 @ r1<- A 8428 cmp r9, #0 @ check object for null 8429 GET_VREG(r0, r1) @ r0<- fp[A] 8430 beq common_errNullObject @ object was null 8431 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8432 GET_INST_OPCODE(ip) @ extract opcode from rINST 8433 @ no-op @ releasing store 8434 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8435 GOTO_OPCODE(ip) @ jump to next instruction 8436 8437/* continuation for OP_IPUT_WIDE */ 8438 8439 /* 8440 * Currently: 8441 * r0 holds resolved field 8442 * r9 holds object 8443 */ 8444.LOP_IPUT_WIDE_finish: 8445 mov r2, rINST, lsr #8 @ r2<- A+ 8446 cmp r9, #0 @ check object for null 8447 and r2, r2, #15 @ r2<- A 8448 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8449 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8450 beq common_errNullObject @ object was null 8451 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8452 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8453 GET_INST_OPCODE(r10) @ extract opcode from rINST 8454 .if 0 8455 add r2, r9, r3 @ r2<- target address 8456 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 8457 .else 8458 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 8459 .endif 8460 GOTO_OPCODE(r10) @ jump to next instruction 8461 8462/* continuation for OP_IPUT_OBJECT */ 8463 8464 /* 8465 * Currently: 8466 * r0 holds resolved field 8467 * r9 holds object 8468 */ 8469.LOP_IPUT_OBJECT_finish: 8470 @bl common_squeak0 8471 mov r1, rINST, lsr #8 @ r1<- A+ 8472 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8473 and r1, r1, #15 @ r1<- A 8474 cmp r9, #0 @ check object for null 8475 GET_VREG(r0, r1) @ r0<- fp[A] 8476 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8477 beq common_errNullObject @ object was null 8478 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8479 GET_INST_OPCODE(ip) @ extract opcode from rINST 8480 @ no-op @ releasing store 8481 str r0, [r9, r3] @ obj.field (32 bits)<- r0 8482 cmp r0, #0 @ stored a null reference? 8483 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 8484 GOTO_OPCODE(ip) @ jump to next instruction 8485 8486/* continuation for OP_IPUT_BOOLEAN */ 8487 8488 /* 8489 * Currently: 8490 * r0 holds resolved field 8491 * r9 holds object 8492 */ 8493.LOP_IPUT_BOOLEAN_finish: 8494 @bl common_squeak1 8495 mov r1, rINST, lsr #8 @ r1<- A+ 8496 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8497 and r1, r1, #15 @ r1<- A 8498 cmp r9, #0 @ check object for null 8499 GET_VREG(r0, r1) @ r0<- fp[A] 8500 beq common_errNullObject @ object was null 8501 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8502 GET_INST_OPCODE(ip) @ extract opcode from rINST 8503 @ no-op @ releasing store 8504 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8505 GOTO_OPCODE(ip) @ jump to next instruction 8506 8507/* continuation for OP_IPUT_BYTE */ 8508 8509 /* 8510 * Currently: 8511 * r0 holds resolved field 8512 * r9 holds object 8513 */ 8514.LOP_IPUT_BYTE_finish: 8515 @bl common_squeak2 8516 mov r1, rINST, lsr #8 @ r1<- A+ 8517 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8518 and r1, r1, #15 @ r1<- A 8519 cmp r9, #0 @ check object for null 8520 GET_VREG(r0, r1) @ r0<- fp[A] 8521 beq common_errNullObject @ object was null 8522 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8523 GET_INST_OPCODE(ip) @ extract opcode from rINST 8524 @ no-op @ releasing store 8525 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8526 GOTO_OPCODE(ip) @ jump to next instruction 8527 8528/* continuation for OP_IPUT_CHAR */ 8529 8530 /* 8531 * Currently: 8532 * r0 holds resolved field 8533 * r9 holds object 8534 */ 8535.LOP_IPUT_CHAR_finish: 8536 @bl common_squeak3 8537 mov r1, rINST, lsr #8 @ r1<- A+ 8538 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8539 and r1, r1, #15 @ r1<- A 8540 cmp r9, #0 @ check object for null 8541 GET_VREG(r0, r1) @ r0<- fp[A] 8542 beq common_errNullObject @ object was null 8543 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8544 GET_INST_OPCODE(ip) @ extract opcode from rINST 8545 @ no-op @ releasing store 8546 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8547 GOTO_OPCODE(ip) @ jump to next instruction 8548 8549/* continuation for OP_IPUT_SHORT */ 8550 8551 /* 8552 * Currently: 8553 * r0 holds resolved field 8554 * r9 holds object 8555 */ 8556.LOP_IPUT_SHORT_finish: 8557 @bl common_squeak4 8558 mov r1, rINST, lsr #8 @ r1<- A+ 8559 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8560 and r1, r1, #15 @ r1<- A 8561 cmp r9, #0 @ check object for null 8562 GET_VREG(r0, r1) @ r0<- fp[A] 8563 beq common_errNullObject @ object was null 8564 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8565 GET_INST_OPCODE(ip) @ extract opcode from rINST 8566 @ no-op @ releasing store 8567 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8568 GOTO_OPCODE(ip) @ jump to next instruction 8569 8570/* continuation for OP_SGET */ 8571 8572 /* 8573 * Continuation if the field has not yet been resolved. 8574 * r1: BBBB field ref 8575 */ 8576.LOP_SGET_resolve: 8577 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8578 EXPORT_PC() @ resolve() could throw, so export now 8579 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8580 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8581 cmp r0, #0 @ success? 8582 bne .LOP_SGET_finish @ yes, finish 8583 b common_exceptionThrown @ no, handle exception 8584 8585/* continuation for OP_SGET_WIDE */ 8586 8587 /* 8588 * Continuation if the field has not yet been resolved. 8589 * r1: BBBB field ref 8590 * 8591 * Returns StaticField pointer in r0. 8592 */ 8593.LOP_SGET_WIDE_resolve: 8594 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8595 EXPORT_PC() @ resolve() could throw, so export now 8596 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8597 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8598 cmp r0, #0 @ success? 8599 bne .LOP_SGET_WIDE_finish @ yes, finish 8600 b common_exceptionThrown @ no, handle exception 8601 8602/* continuation for OP_SGET_OBJECT */ 8603 8604 /* 8605 * Continuation if the field has not yet been resolved. 8606 * r1: BBBB field ref 8607 */ 8608.LOP_SGET_OBJECT_resolve: 8609 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8610 EXPORT_PC() @ resolve() could throw, so export now 8611 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8612 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8613 cmp r0, #0 @ success? 8614 bne .LOP_SGET_OBJECT_finish @ yes, finish 8615 b common_exceptionThrown @ no, handle exception 8616 8617/* continuation for OP_SGET_BOOLEAN */ 8618 8619 /* 8620 * Continuation if the field has not yet been resolved. 8621 * r1: BBBB field ref 8622 */ 8623.LOP_SGET_BOOLEAN_resolve: 8624 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8625 EXPORT_PC() @ resolve() could throw, so export now 8626 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8627 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8628 cmp r0, #0 @ success? 8629 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8630 b common_exceptionThrown @ no, handle exception 8631 8632/* continuation for OP_SGET_BYTE */ 8633 8634 /* 8635 * Continuation if the field has not yet been resolved. 8636 * r1: BBBB field ref 8637 */ 8638.LOP_SGET_BYTE_resolve: 8639 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8640 EXPORT_PC() @ resolve() could throw, so export now 8641 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8642 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8643 cmp r0, #0 @ success? 8644 bne .LOP_SGET_BYTE_finish @ yes, finish 8645 b common_exceptionThrown @ no, handle exception 8646 8647/* continuation for OP_SGET_CHAR */ 8648 8649 /* 8650 * Continuation if the field has not yet been resolved. 8651 * r1: BBBB field ref 8652 */ 8653.LOP_SGET_CHAR_resolve: 8654 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8655 EXPORT_PC() @ resolve() could throw, so export now 8656 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8657 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8658 cmp r0, #0 @ success? 8659 bne .LOP_SGET_CHAR_finish @ yes, finish 8660 b common_exceptionThrown @ no, handle exception 8661 8662/* continuation for OP_SGET_SHORT */ 8663 8664 /* 8665 * Continuation if the field has not yet been resolved. 8666 * r1: BBBB field ref 8667 */ 8668.LOP_SGET_SHORT_resolve: 8669 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8670 EXPORT_PC() @ resolve() could throw, so export now 8671 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8672 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8673 cmp r0, #0 @ success? 8674 bne .LOP_SGET_SHORT_finish @ yes, finish 8675 b common_exceptionThrown @ no, handle exception 8676 8677/* continuation for OP_SPUT */ 8678 8679 /* 8680 * Continuation if the field has not yet been resolved. 8681 * r1: BBBB field ref 8682 */ 8683.LOP_SPUT_resolve: 8684 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8685 EXPORT_PC() @ resolve() could throw, so export now 8686 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8687 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8688 cmp r0, #0 @ success? 8689 bne .LOP_SPUT_finish @ yes, finish 8690 b common_exceptionThrown @ no, handle exception 8691 8692/* continuation for OP_SPUT_WIDE */ 8693 8694 /* 8695 * Continuation if the field has not yet been resolved. 8696 * r1: BBBB field ref 8697 * r9: &fp[AA] 8698 * 8699 * Returns StaticField pointer in r2. 8700 */ 8701.LOP_SPUT_WIDE_resolve: 8702 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8703 EXPORT_PC() @ resolve() could throw, so export now 8704 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8705 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8706 cmp r0, #0 @ success? 8707 mov r2, r0 @ copy to r2 8708 bne .LOP_SPUT_WIDE_finish @ yes, finish 8709 b common_exceptionThrown @ no, handle exception 8710 8711/* continuation for OP_SPUT_OBJECT */ 8712.LOP_SPUT_OBJECT_finish: @ field ptr in r0 8713 mov r2, rINST, lsr #8 @ r2<- AA 8714 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8715 GET_VREG(r1, r2) @ r1<- fp[AA] 8716 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8717 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz 8718 GET_INST_OPCODE(ip) @ extract opcode from rINST 8719 @ no-op @ releasing store 8720 str r1, [r0, #offStaticField_value] @ field<- vAA 8721 cmp r1, #0 @ stored a null object? 8722 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 8723 GOTO_OPCODE(ip) @ jump to next instruction 8724 8725/* continuation for OP_SPUT_BOOLEAN */ 8726 8727 /* 8728 * Continuation if the field has not yet been resolved. 8729 * r1: BBBB field ref 8730 */ 8731.LOP_SPUT_BOOLEAN_resolve: 8732 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8733 EXPORT_PC() @ resolve() could throw, so export now 8734 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8735 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8736 cmp r0, #0 @ success? 8737 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 8738 b common_exceptionThrown @ no, handle exception 8739 8740/* continuation for OP_SPUT_BYTE */ 8741 8742 /* 8743 * Continuation if the field has not yet been resolved. 8744 * r1: BBBB field ref 8745 */ 8746.LOP_SPUT_BYTE_resolve: 8747 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8748 EXPORT_PC() @ resolve() could throw, so export now 8749 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8750 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8751 cmp r0, #0 @ success? 8752 bne .LOP_SPUT_BYTE_finish @ yes, finish 8753 b common_exceptionThrown @ no, handle exception 8754 8755/* continuation for OP_SPUT_CHAR */ 8756 8757 /* 8758 * Continuation if the field has not yet been resolved. 8759 * r1: BBBB field ref 8760 */ 8761.LOP_SPUT_CHAR_resolve: 8762 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8763 EXPORT_PC() @ resolve() could throw, so export now 8764 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8765 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8766 cmp r0, #0 @ success? 8767 bne .LOP_SPUT_CHAR_finish @ yes, finish 8768 b common_exceptionThrown @ no, handle exception 8769 8770/* continuation for OP_SPUT_SHORT */ 8771 8772 /* 8773 * Continuation if the field has not yet been resolved. 8774 * r1: BBBB field ref 8775 */ 8776.LOP_SPUT_SHORT_resolve: 8777 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8778 EXPORT_PC() @ resolve() could throw, so export now 8779 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8780 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8781 cmp r0, #0 @ success? 8782 bne .LOP_SPUT_SHORT_finish @ yes, finish 8783 b common_exceptionThrown @ no, handle exception 8784 8785/* continuation for OP_INVOKE_VIRTUAL */ 8786 8787 /* 8788 * At this point: 8789 * r0 = resolved base method 8790 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8791 */ 8792.LOP_INVOKE_VIRTUAL_continue: 8793 GET_VREG(r1, r10) @ r1<- "this" ptr 8794 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8795 cmp r1, #0 @ is "this" null? 8796 beq common_errNullObject @ null "this", throw exception 8797 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8798 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8799 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8800 bl common_invokeMethodNoRange @ continue on 8801 8802/* continuation for OP_INVOKE_SUPER */ 8803 8804 /* 8805 * At this point: 8806 * r0 = resolved base method 8807 * r9 = method->clazz 8808 */ 8809.LOP_INVOKE_SUPER_continue: 8810 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8811 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8812 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8813 EXPORT_PC() @ must export for invoke 8814 cmp r2, r3 @ compare (methodIndex, vtableCount) 8815 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 8816 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8817 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8818 bl common_invokeMethodNoRange @ continue on 8819 8820.LOP_INVOKE_SUPER_resolve: 8821 mov r0, r9 @ r0<- method->clazz 8822 mov r2, #METHOD_VIRTUAL @ resolver method type 8823 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8824 cmp r0, #0 @ got null? 8825 bne .LOP_INVOKE_SUPER_continue @ no, continue 8826 b common_exceptionThrown @ yes, handle exception 8827 8828 /* 8829 * Throw a NoSuchMethodError with the method name as the message. 8830 * r0 = resolved base method 8831 */ 8832.LOP_INVOKE_SUPER_nsm: 8833 ldr r1, [r0, #offMethod_name] @ r1<- method name 8834 b common_errNoSuchMethod 8835 8836/* continuation for OP_INVOKE_DIRECT */ 8837 8838 /* 8839 * On entry: 8840 * r1 = reference (BBBB or CCCC) 8841 * r10 = "this" register 8842 */ 8843.LOP_INVOKE_DIRECT_resolve: 8844 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8845 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8846 mov r2, #METHOD_DIRECT @ resolver method type 8847 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8848 cmp r0, #0 @ got null? 8849 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8850 bne .LOP_INVOKE_DIRECT_finish @ no, continue 8851 b common_exceptionThrown @ yes, handle exception 8852 8853/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 8854 8855 /* 8856 * At this point: 8857 * r0 = resolved base method 8858 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8859 */ 8860.LOP_INVOKE_VIRTUAL_RANGE_continue: 8861 GET_VREG(r1, r10) @ r1<- "this" ptr 8862 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8863 cmp r1, #0 @ is "this" null? 8864 beq common_errNullObject @ null "this", throw exception 8865 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8866 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8867 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8868 bl common_invokeMethodRange @ continue on 8869 8870/* continuation for OP_INVOKE_SUPER_RANGE */ 8871 8872 /* 8873 * At this point: 8874 * r0 = resolved base method 8875 * r9 = method->clazz 8876 */ 8877.LOP_INVOKE_SUPER_RANGE_continue: 8878 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8879 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8880 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8881 EXPORT_PC() @ must export for invoke 8882 cmp r2, r3 @ compare (methodIndex, vtableCount) 8883 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 8884 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8885 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8886 bl common_invokeMethodRange @ continue on 8887 8888.LOP_INVOKE_SUPER_RANGE_resolve: 8889 mov r0, r9 @ r0<- method->clazz 8890 mov r2, #METHOD_VIRTUAL @ resolver method type 8891 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8892 cmp r0, #0 @ got null? 8893 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 8894 b common_exceptionThrown @ yes, handle exception 8895 8896 /* 8897 * Throw a NoSuchMethodError with the method name as the message. 8898 * r0 = resolved base method 8899 */ 8900.LOP_INVOKE_SUPER_RANGE_nsm: 8901 ldr r1, [r0, #offMethod_name] @ r1<- method name 8902 b common_errNoSuchMethod 8903 8904/* continuation for OP_INVOKE_DIRECT_RANGE */ 8905 8906 /* 8907 * On entry: 8908 * r1 = reference (BBBB or CCCC) 8909 * r10 = "this" register 8910 */ 8911.LOP_INVOKE_DIRECT_RANGE_resolve: 8912 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8913 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8914 mov r2, #METHOD_DIRECT @ resolver method type 8915 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8916 cmp r0, #0 @ got null? 8917 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8918 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 8919 b common_exceptionThrown @ yes, handle exception 8920 8921/* continuation for OP_FLOAT_TO_LONG */ 8922/* 8923 * Convert the float in r0 to a long in r0/r1. 8924 * 8925 * We have to clip values to long min/max per the specification. The 8926 * expected common case is a "reasonable" value that converts directly 8927 * to modest integer. The EABI convert function isn't doing this for us. 8928 */ 8929f2l_doconv: 8930 stmfd sp!, {r4, lr} 8931 mov r1, #0x5f000000 @ (float)maxlong 8932 mov r4, r0 8933 bl __aeabi_fcmpge @ is arg >= maxlong? 8934 cmp r0, #0 @ nonzero == yes 8935 mvnne r0, #0 @ return maxlong (7fffffff) 8936 mvnne r1, #0x80000000 8937 ldmnefd sp!, {r4, pc} 8938 8939 mov r0, r4 @ recover arg 8940 mov r1, #0xdf000000 @ (float)minlong 8941 bl __aeabi_fcmple @ is arg <= minlong? 8942 cmp r0, #0 @ nonzero == yes 8943 movne r0, #0 @ return minlong (80000000) 8944 movne r1, #0x80000000 8945 ldmnefd sp!, {r4, pc} 8946 8947 mov r0, r4 @ recover arg 8948 mov r1, r4 8949 bl __aeabi_fcmpeq @ is arg == self? 8950 cmp r0, #0 @ zero == no 8951 moveq r1, #0 @ return zero for NaN 8952 ldmeqfd sp!, {r4, pc} 8953 8954 mov r0, r4 @ recover arg 8955 bl __aeabi_f2lz @ convert float to long 8956 ldmfd sp!, {r4, pc} 8957 8958/* continuation for OP_DOUBLE_TO_LONG */ 8959/* 8960 * Convert the double in r0/r1 to a long in r0/r1. 8961 * 8962 * We have to clip values to long min/max per the specification. The 8963 * expected common case is a "reasonable" value that converts directly 8964 * to modest integer. The EABI convert function isn't doing this for us. 8965 */ 8966d2l_doconv: 8967 stmfd sp!, {r4, r5, lr} @ save regs 8968 mov r3, #0x43000000 @ maxlong, as a double (high word) 8969 add r3, #0x00e00000 @ 0x43e00000 8970 mov r2, #0 @ maxlong, as a double (low word) 8971 sub sp, sp, #4 @ align for EABI 8972 mov r4, r0 @ save a copy of r0 8973 mov r5, r1 @ and r1 8974 bl __aeabi_dcmpge @ is arg >= maxlong? 8975 cmp r0, #0 @ nonzero == yes 8976 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 8977 mvnne r1, #0x80000000 8978 bne 1f 8979 8980 mov r0, r4 @ recover arg 8981 mov r1, r5 8982 mov r3, #0xc3000000 @ minlong, as a double (high word) 8983 add r3, #0x00e00000 @ 0xc3e00000 8984 mov r2, #0 @ minlong, as a double (low word) 8985 bl __aeabi_dcmple @ is arg <= minlong? 8986 cmp r0, #0 @ nonzero == yes 8987 movne r0, #0 @ return minlong (8000000000000000) 8988 movne r1, #0x80000000 8989 bne 1f 8990 8991 mov r0, r4 @ recover arg 8992 mov r1, r5 8993 mov r2, r4 @ compare against self 8994 mov r3, r5 8995 bl __aeabi_dcmpeq @ is arg == self? 8996 cmp r0, #0 @ zero == no 8997 moveq r1, #0 @ return zero for NaN 8998 beq 1f 8999 9000 mov r0, r4 @ recover arg 9001 mov r1, r5 9002 bl __aeabi_d2lz @ convert double to long 9003 90041: 9005 add sp, sp, #4 9006 ldmfd sp!, {r4, r5, pc} 9007 9008/* continuation for OP_MUL_LONG */ 9009 9010.LOP_MUL_LONG_finish: 9011 GET_INST_OPCODE(ip) @ extract opcode from rINST 9012 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 9013 GOTO_OPCODE(ip) @ jump to next instruction 9014 9015/* continuation for OP_SHL_LONG */ 9016 9017.LOP_SHL_LONG_finish: 9018 mov r0, r0, asl r2 @ r0<- r0 << r2 9019 GET_INST_OPCODE(ip) @ extract opcode from rINST 9020 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9021 GOTO_OPCODE(ip) @ jump to next instruction 9022 9023/* continuation for OP_SHR_LONG */ 9024 9025.LOP_SHR_LONG_finish: 9026 mov r1, r1, asr r2 @ r1<- r1 >> r2 9027 GET_INST_OPCODE(ip) @ extract opcode from rINST 9028 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9029 GOTO_OPCODE(ip) @ jump to next instruction 9030 9031/* continuation for OP_USHR_LONG */ 9032 9033.LOP_USHR_LONG_finish: 9034 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 9035 GET_INST_OPCODE(ip) @ extract opcode from rINST 9036 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9037 GOTO_OPCODE(ip) @ jump to next instruction 9038 9039/* continuation for OP_SHL_LONG_2ADDR */ 9040 9041.LOP_SHL_LONG_2ADDR_finish: 9042 GET_INST_OPCODE(ip) @ extract opcode from rINST 9043 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9044 GOTO_OPCODE(ip) @ jump to next instruction 9045 9046/* continuation for OP_SHR_LONG_2ADDR */ 9047 9048.LOP_SHR_LONG_2ADDR_finish: 9049 GET_INST_OPCODE(ip) @ extract opcode from rINST 9050 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9051 GOTO_OPCODE(ip) @ jump to next instruction 9052 9053/* continuation for OP_USHR_LONG_2ADDR */ 9054 9055.LOP_USHR_LONG_2ADDR_finish: 9056 GET_INST_OPCODE(ip) @ extract opcode from rINST 9057 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9058 GOTO_OPCODE(ip) @ jump to next instruction 9059 9060/* continuation for OP_IGET_VOLATILE */ 9061 9062 /* 9063 * Currently: 9064 * r0 holds resolved field 9065 * r9 holds object 9066 */ 9067.LOP_IGET_VOLATILE_finish: 9068 @bl common_squeak0 9069 cmp r9, #0 @ check object for null 9070 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9071 beq common_errNullObject @ object was null 9072 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9073 SMP_DMB @ acquiring load 9074 mov r2, rINST, lsr #8 @ r2<- A+ 9075 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9076 and r2, r2, #15 @ r2<- A 9077 GET_INST_OPCODE(ip) @ extract opcode from rINST 9078 SET_VREG(r0, r2) @ fp[A]<- r0 9079 GOTO_OPCODE(ip) @ jump to next instruction 9080 9081/* continuation for OP_IPUT_VOLATILE */ 9082 9083 /* 9084 * Currently: 9085 * r0 holds resolved field 9086 * r9 holds object 9087 */ 9088.LOP_IPUT_VOLATILE_finish: 9089 @bl common_squeak0 9090 mov r1, rINST, lsr #8 @ r1<- A+ 9091 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9092 and r1, r1, #15 @ r1<- A 9093 cmp r9, #0 @ check object for null 9094 GET_VREG(r0, r1) @ r0<- fp[A] 9095 beq common_errNullObject @ object was null 9096 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9097 GET_INST_OPCODE(ip) @ extract opcode from rINST 9098 SMP_DMB @ releasing store 9099 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 9100 GOTO_OPCODE(ip) @ jump to next instruction 9101 9102/* continuation for OP_SGET_VOLATILE */ 9103 9104 /* 9105 * Continuation if the field has not yet been resolved. 9106 * r1: BBBB field ref 9107 */ 9108.LOP_SGET_VOLATILE_resolve: 9109 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9110 EXPORT_PC() @ resolve() could throw, so export now 9111 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9112 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9113 cmp r0, #0 @ success? 9114 bne .LOP_SGET_VOLATILE_finish @ yes, finish 9115 b common_exceptionThrown @ no, handle exception 9116 9117/* continuation for OP_SPUT_VOLATILE */ 9118 9119 /* 9120 * Continuation if the field has not yet been resolved. 9121 * r1: BBBB field ref 9122 */ 9123.LOP_SPUT_VOLATILE_resolve: 9124 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9125 EXPORT_PC() @ resolve() could throw, so export now 9126 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9127 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9128 cmp r0, #0 @ success? 9129 bne .LOP_SPUT_VOLATILE_finish @ yes, finish 9130 b common_exceptionThrown @ no, handle exception 9131 9132/* continuation for OP_IGET_OBJECT_VOLATILE */ 9133 9134 /* 9135 * Currently: 9136 * r0 holds resolved field 9137 * r9 holds object 9138 */ 9139.LOP_IGET_OBJECT_VOLATILE_finish: 9140 @bl common_squeak0 9141 cmp r9, #0 @ check object for null 9142 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9143 beq common_errNullObject @ object was null 9144 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9145 SMP_DMB @ acquiring load 9146 mov r2, rINST, lsr #8 @ r2<- A+ 9147 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9148 and r2, r2, #15 @ r2<- A 9149 GET_INST_OPCODE(ip) @ extract opcode from rINST 9150 SET_VREG(r0, r2) @ fp[A]<- r0 9151 GOTO_OPCODE(ip) @ jump to next instruction 9152 9153/* continuation for OP_IGET_WIDE_VOLATILE */ 9154 9155 /* 9156 * Currently: 9157 * r0 holds resolved field 9158 * r9 holds object 9159 */ 9160.LOP_IGET_WIDE_VOLATILE_finish: 9161 cmp r9, #0 @ check object for null 9162 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9163 beq common_errNullObject @ object was null 9164 .if 1 9165 add r0, r9, r3 @ r0<- address of field 9166 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 9167 .else 9168 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 9169 .endif 9170 mov r2, rINST, lsr #8 @ r2<- A+ 9171 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9172 and r2, r2, #15 @ r2<- A 9173 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 9174 GET_INST_OPCODE(ip) @ extract opcode from rINST 9175 stmia r3, {r0-r1} @ fp[A]<- r0/r1 9176 GOTO_OPCODE(ip) @ jump to next instruction 9177 9178/* continuation for OP_IPUT_WIDE_VOLATILE */ 9179 9180 /* 9181 * Currently: 9182 * r0 holds resolved field 9183 * r9 holds object 9184 */ 9185.LOP_IPUT_WIDE_VOLATILE_finish: 9186 mov r2, rINST, lsr #8 @ r2<- A+ 9187 cmp r9, #0 @ check object for null 9188 and r2, r2, #15 @ r2<- A 9189 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9190 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 9191 beq common_errNullObject @ object was null 9192 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9193 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 9194 GET_INST_OPCODE(r10) @ extract opcode from rINST 9195 .if 1 9196 add r2, r9, r3 @ r2<- target address 9197 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 9198 .else 9199 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 9200 .endif 9201 GOTO_OPCODE(r10) @ jump to next instruction 9202 9203/* continuation for OP_SGET_WIDE_VOLATILE */ 9204 9205 /* 9206 * Continuation if the field has not yet been resolved. 9207 * r1: BBBB field ref 9208 * 9209 * Returns StaticField pointer in r0. 9210 */ 9211.LOP_SGET_WIDE_VOLATILE_resolve: 9212 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9213 EXPORT_PC() @ resolve() could throw, so export now 9214 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9215 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9216 cmp r0, #0 @ success? 9217 bne .LOP_SGET_WIDE_VOLATILE_finish @ yes, finish 9218 b common_exceptionThrown @ no, handle exception 9219 9220/* continuation for OP_SPUT_WIDE_VOLATILE */ 9221 9222 /* 9223 * Continuation if the field has not yet been resolved. 9224 * r1: BBBB field ref 9225 * r9: &fp[AA] 9226 * 9227 * Returns StaticField pointer in r2. 9228 */ 9229.LOP_SPUT_WIDE_VOLATILE_resolve: 9230 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9231 EXPORT_PC() @ resolve() could throw, so export now 9232 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9233 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9234 cmp r0, #0 @ success? 9235 mov r2, r0 @ copy to r2 9236 bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish 9237 b common_exceptionThrown @ no, handle exception 9238 9239/* continuation for OP_EXECUTE_INLINE */ 9240 9241 /* 9242 * Extract args, call function. 9243 * r0 = #of args (0-4) 9244 * r10 = call index 9245 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9246 * 9247 * Other ideas: 9248 * - Use a jump table from the main piece to jump directly into the 9249 * AND/LDR pairs. Costs a data load, saves a branch. 9250 * - Have five separate pieces that do the loading, so we can work the 9251 * interleave a little better. Increases code size. 9252 */ 9253.LOP_EXECUTE_INLINE_continue: 9254 rsb r0, r0, #4 @ r0<- 4-r0 9255 FETCH(r9, 2) @ r9<- FEDC 9256 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9257 bl common_abort @ (skipped due to ARM prefetch) 92584: and ip, r9, #0xf000 @ isolate F 9259 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 92603: and ip, r9, #0x0f00 @ isolate E 9261 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 92622: and ip, r9, #0x00f0 @ isolate D 9263 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 92641: and ip, r9, #0x000f @ isolate C 9265 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 92660: 9267 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 9268 ldr pc, [r9, r10, lsl #4] @ sizeof=16, "func" is first entry 9269 @ (not reached) 9270 9271.LOP_EXECUTE_INLINE_table: 9272 .word gDvmInlineOpsTable 9273 9274/* continuation for OP_EXECUTE_INLINE_RANGE */ 9275 9276 /* 9277 * Extract args, call function. 9278 * r0 = #of args (0-4) 9279 * r10 = call index 9280 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9281 */ 9282.LOP_EXECUTE_INLINE_RANGE_continue: 9283 rsb r0, r0, #4 @ r0<- 4-r0 9284 FETCH(r9, 2) @ r9<- CCCC 9285 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9286 bl common_abort @ (skipped due to ARM prefetch) 92874: add ip, r9, #3 @ base+3 9288 GET_VREG(r3, ip) @ r3<- vBase[3] 92893: add ip, r9, #2 @ base+2 9290 GET_VREG(r2, ip) @ r2<- vBase[2] 92912: add ip, r9, #1 @ base+1 9292 GET_VREG(r1, ip) @ r1<- vBase[1] 92931: add ip, r9, #0 @ (nop) 9294 GET_VREG(r0, ip) @ r0<- vBase[0] 92950: 9296 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation 9297 ldr pc, [r9, r10, lsl #4] @ sizeof=16, "func" is first entry 9298 @ (not reached) 9299 9300.LOP_EXECUTE_INLINE_RANGE_table: 9301 .word gDvmInlineOpsTable 9302 9303/* continuation for OP_IPUT_OBJECT_VOLATILE */ 9304 9305 /* 9306 * Currently: 9307 * r0 holds resolved field 9308 * r9 holds object 9309 */ 9310.LOP_IPUT_OBJECT_VOLATILE_finish: 9311 @bl common_squeak0 9312 mov r1, rINST, lsr #8 @ r1<- A+ 9313 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9314 and r1, r1, #15 @ r1<- A 9315 cmp r9, #0 @ check object for null 9316 GET_VREG(r0, r1) @ r0<- fp[A] 9317 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 9318 beq common_errNullObject @ object was null 9319 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9320 GET_INST_OPCODE(ip) @ extract opcode from rINST 9321 SMP_DMB @ releasing store 9322 str r0, [r9, r3] @ obj.field (32 bits)<- r0 9323 cmp r0, #0 @ stored a null reference? 9324 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 9325 GOTO_OPCODE(ip) @ jump to next instruction 9326 9327/* continuation for OP_SGET_OBJECT_VOLATILE */ 9328 9329 /* 9330 * Continuation if the field has not yet been resolved. 9331 * r1: BBBB field ref 9332 */ 9333.LOP_SGET_OBJECT_VOLATILE_resolve: 9334 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9335 EXPORT_PC() @ resolve() could throw, so export now 9336 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9337 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9338 cmp r0, #0 @ success? 9339 bne .LOP_SGET_OBJECT_VOLATILE_finish @ yes, finish 9340 b common_exceptionThrown @ no, handle exception 9341 9342/* continuation for OP_SPUT_OBJECT_VOLATILE */ 9343.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0 9344 mov r2, rINST, lsr #8 @ r2<- AA 9345 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9346 GET_VREG(r1, r2) @ r1<- fp[AA] 9347 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 9348 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz 9349 GET_INST_OPCODE(ip) @ extract opcode from rINST 9350 SMP_DMB @ releasing store 9351 str r1, [r0, #offStaticField_value] @ field<- vAA 9352 cmp r1, #0 @ stored a null object? 9353 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 9354 GOTO_OPCODE(ip) @ jump to next instruction 9355 9356 .size dvmAsmSisterStart, .-dvmAsmSisterStart 9357 .global dvmAsmSisterEnd 9358dvmAsmSisterEnd: 9359 9360/* File: armv5te/footer.S */ 9361 9362/* 9363 * =========================================================================== 9364 * Common subroutines and data 9365 * =========================================================================== 9366 */ 9367 9368 9369 9370 .text 9371 .align 2 9372 9373#if defined(WITH_JIT) 9374#if defined(WITH_SELF_VERIFICATION) 9375 .global dvmJitToInterpPunt 9376dvmJitToInterpPunt: 9377 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9378 mov r2,#kSVSPunt @ r2<- interpreter entry point 9379 mov r3, #0 9380 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9381 b jitSVShadowRunEnd @ doesn't return 9382 9383 .global dvmJitToInterpSingleStep 9384dvmJitToInterpSingleStep: 9385 str lr,[rGLUE,#offGlue_jitResumeNPC] 9386 str r1,[rGLUE,#offGlue_jitResumeDPC] 9387 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 9388 b jitSVShadowRunEnd @ doesn't return 9389 9390 .global dvmJitToInterpNoChainNoProfile 9391dvmJitToInterpNoChainNoProfile: 9392 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9393 mov r0,rPC @ pass our target PC 9394 mov r2,#kSVSNoProfile @ r2<- interpreter entry point 9395 mov r3, #0 @ 0 means !inJitCodeCache 9396 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land 9397 b jitSVShadowRunEnd @ doesn't return 9398 9399 .global dvmJitToInterpTraceSelectNoChain 9400dvmJitToInterpTraceSelectNoChain: 9401 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9402 mov r0,rPC @ pass our target PC 9403 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9404 mov r3, #0 @ 0 means !inJitCodeCache 9405 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9406 b jitSVShadowRunEnd @ doesn't return 9407 9408 .global dvmJitToInterpTraceSelect 9409dvmJitToInterpTraceSelect: 9410 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9411 ldr r0,[lr, #-1] @ pass our target PC 9412 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9413 mov r3, #0 @ 0 means !inJitCodeCache 9414 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9415 b jitSVShadowRunEnd @ doesn't return 9416 9417 .global dvmJitToInterpBackwardBranch 9418dvmJitToInterpBackwardBranch: 9419 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9420 ldr r0,[lr, #-1] @ pass our target PC 9421 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 9422 mov r3, #0 @ 0 means !inJitCodeCache 9423 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9424 b jitSVShadowRunEnd @ doesn't return 9425 9426 .global dvmJitToInterpNormal 9427dvmJitToInterpNormal: 9428 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9429 ldr r0,[lr, #-1] @ pass our target PC 9430 mov r2,#kSVSNormal @ r2<- interpreter entry point 9431 mov r3, #0 @ 0 means !inJitCodeCache 9432 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9433 b jitSVShadowRunEnd @ doesn't return 9434 9435 .global dvmJitToInterpNoChain 9436dvmJitToInterpNoChain: 9437 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9438 mov r0,rPC @ pass our target PC 9439 mov r2,#kSVSNoChain @ r2<- interpreter entry point 9440 mov r3, #0 @ 0 means !inJitCodeCache 9441 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9442 b jitSVShadowRunEnd @ doesn't return 9443#else 9444/* 9445 * Return from the translation cache to the interpreter when the compiler is 9446 * having issues translating/executing a Dalvik instruction. We have to skip 9447 * the code cache lookup otherwise it is possible to indefinitely bouce 9448 * between the interpreter and the code cache if the instruction that fails 9449 * to be compiled happens to be at a trace start. 9450 */ 9451 .global dvmJitToInterpPunt 9452dvmJitToInterpPunt: 9453 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9454 mov rPC, r0 9455#if defined(WITH_JIT_TUNING) 9456 mov r0,lr 9457 bl dvmBumpPunt; 9458#endif 9459 EXPORT_PC() 9460 mov r0, #0 9461 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9462 adrl rIBASE, dvmAsmInstructionStart 9463 FETCH_INST() 9464 GET_INST_OPCODE(ip) 9465 GOTO_OPCODE(ip) 9466 9467/* 9468 * Return to the interpreter to handle a single instruction. 9469 * On entry: 9470 * r0 <= PC 9471 * r1 <= PC of resume instruction 9472 * lr <= resume point in translation 9473 */ 9474 .global dvmJitToInterpSingleStep 9475dvmJitToInterpSingleStep: 9476 str lr,[rGLUE,#offGlue_jitResumeNPC] 9477 str r1,[rGLUE,#offGlue_jitResumeDPC] 9478 mov r1,#kInterpEntryInstr 9479 @ enum is 4 byte in aapcs-EABI 9480 str r1, [rGLUE, #offGlue_entryPoint] 9481 mov rPC,r0 9482 EXPORT_PC() 9483 9484 adrl rIBASE, dvmAsmInstructionStart 9485 mov r2,#kJitSingleStep @ Ask for single step and then revert 9486 str r2,[rGLUE,#offGlue_jitState] 9487 mov r1,#1 @ set changeInterp to bail to debug interp 9488 b common_gotoBail 9489 9490/* 9491 * Return from the translation cache and immediately request 9492 * a translation for the exit target. Commonly used for callees. 9493 */ 9494 .global dvmJitToInterpTraceSelectNoChain 9495dvmJitToInterpTraceSelectNoChain: 9496#if defined(WITH_JIT_TUNING) 9497 bl dvmBumpNoChain 9498#endif 9499 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9500 mov r0,rPC 9501 bl dvmJitGetCodeAddr @ Is there a translation? 9502 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9503 mov r1, rPC @ arg1 of translation may need this 9504 mov lr, #0 @ in case target is HANDLER_INTERPRET 9505 cmp r0,#0 @ !0 means translation exists 9506 bxne r0 @ continue native execution if so 9507 b 2f @ branch over to use the interpreter 9508 9509/* 9510 * Return from the translation cache and immediately request 9511 * a translation for the exit target. Commonly used following 9512 * invokes. 9513 */ 9514 .global dvmJitToInterpTraceSelect 9515dvmJitToInterpTraceSelect: 9516 ldr rPC,[lr, #-1] @ get our target PC 9517 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9518 add rINST,lr,#-5 @ save start of chain branch 9519 add rINST, #-4 @ .. which is 9 bytes back 9520 mov r0,rPC 9521 bl dvmJitGetCodeAddr @ Is there a translation? 9522 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9523 cmp r0,#0 9524 beq 2f 9525 mov r1,rINST 9526 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9527 mov r1, rPC @ arg1 of translation may need this 9528 mov lr, #0 @ in case target is HANDLER_INTERPRET 9529 cmp r0,#0 @ successful chain? 9530 bxne r0 @ continue native execution 9531 b toInterpreter @ didn't chain - resume with interpreter 9532 9533/* No translation, so request one if profiling isn't disabled*/ 95342: 9535 adrl rIBASE, dvmAsmInstructionStart 9536 GET_JIT_PROF_TABLE(r0) 9537 FETCH_INST() 9538 cmp r0, #0 9539 movne r2,#kJitTSelectRequestHot @ ask for trace selection 9540 bne common_selectTrace 9541 GET_INST_OPCODE(ip) 9542 GOTO_OPCODE(ip) 9543 9544/* 9545 * Return from the translation cache to the interpreter. 9546 * The return was done with a BLX from thumb mode, and 9547 * the following 32-bit word contains the target rPC value. 9548 * Note that lr (r14) will have its low-order bit set to denote 9549 * its thumb-mode origin. 9550 * 9551 * We'll need to stash our lr origin away, recover the new 9552 * target and then check to see if there is a translation available 9553 * for our new target. If so, we do a translation chain and 9554 * go back to native execution. Otherwise, it's back to the 9555 * interpreter (after treating this entry as a potential 9556 * trace start). 9557 */ 9558 .global dvmJitToInterpNormal 9559dvmJitToInterpNormal: 9560 ldr rPC,[lr, #-1] @ get our target PC 9561 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9562 add rINST,lr,#-5 @ save start of chain branch 9563 add rINST,#-4 @ .. which is 9 bytes back 9564#if defined(WITH_JIT_TUNING) 9565 bl dvmBumpNormal 9566#endif 9567 mov r0,rPC 9568 bl dvmJitGetCodeAddr @ Is there a translation? 9569 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9570 cmp r0,#0 9571 beq toInterpreter @ go if not, otherwise do chain 9572 mov r1,rINST 9573 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9574 mov r1, rPC @ arg1 of translation may need this 9575 mov lr, #0 @ in case target is HANDLER_INTERPRET 9576 cmp r0,#0 @ successful chain? 9577 bxne r0 @ continue native execution 9578 b toInterpreter @ didn't chain - resume with interpreter 9579 9580/* 9581 * Return from the translation cache to the interpreter to do method invocation. 9582 * Check if translation exists for the callee, but don't chain to it. 9583 */ 9584 .global dvmJitToInterpNoChainNoProfile 9585dvmJitToInterpNoChainNoProfile: 9586#if defined(WITH_JIT_TUNING) 9587 bl dvmBumpNoChain 9588#endif 9589 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9590 mov r0,rPC 9591 bl dvmJitGetCodeAddr @ Is there a translation? 9592 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9593 mov r1, rPC @ arg1 of translation may need this 9594 mov lr, #0 @ in case target is HANDLER_INTERPRET 9595 cmp r0,#0 9596 bxne r0 @ continue native execution if so 9597 EXPORT_PC() 9598 adrl rIBASE, dvmAsmInstructionStart 9599 FETCH_INST() 9600 GET_INST_OPCODE(ip) @ extract opcode from rINST 9601 GOTO_OPCODE(ip) @ jump to next instruction 9602 9603/* 9604 * Return from the translation cache to the interpreter to do method invocation. 9605 * Check if translation exists for the callee, but don't chain to it. 9606 */ 9607 .global dvmJitToInterpNoChain 9608dvmJitToInterpNoChain: 9609#if defined(WITH_JIT_TUNING) 9610 bl dvmBumpNoChain 9611#endif 9612 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9613 mov r0,rPC 9614 bl dvmJitGetCodeAddr @ Is there a translation? 9615 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9616 mov r1, rPC @ arg1 of translation may need this 9617 mov lr, #0 @ in case target is HANDLER_INTERPRET 9618 cmp r0,#0 9619 bxne r0 @ continue native execution if so 9620#endif 9621 9622/* 9623 * No translation, restore interpreter regs and start interpreting. 9624 * rGLUE & rFP were preserved in the translated code, and rPC has 9625 * already been restored by the time we get here. We'll need to set 9626 * up rIBASE & rINST, and load the address of the JitTable into r0. 9627 */ 9628toInterpreter: 9629 EXPORT_PC() 9630 adrl rIBASE, dvmAsmInstructionStart 9631 FETCH_INST() 9632 GET_JIT_PROF_TABLE(r0) 9633 @ NOTE: intended fallthrough 9634 9635/* 9636 * Common code to update potential trace start counter, and initiate 9637 * a trace-build if appropriate. On entry, rPC should point to the 9638 * next instruction to execute, and rINST should be already loaded with 9639 * the next opcode word, and r0 holds a pointer to the jit profile 9640 * table (pJitProfTable). 9641 */ 9642common_testUpdateProfile: 9643 cmp r0,#0 9644 GET_INST_OPCODE(ip) 9645 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 9646 9647common_updateProfile: 9648 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 9649 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits 9650 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter 9651 GET_INST_OPCODE(ip) 9652 subs r1,r1,#1 @ decrement counter 9653 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it 9654 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 9655 9656/* 9657 * Here, we switch to the debug interpreter to request 9658 * trace selection. First, though, check to see if there 9659 * is already a native translation in place (and, if so, 9660 * jump to it now). 9661 */ 9662 GET_JIT_THRESHOLD(r1) 9663 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9664 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter 9665 EXPORT_PC() 9666 mov r0,rPC 9667 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC) 9668 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9669 mov r1, rPC @ arg1 of translation may need this 9670 mov lr, #0 @ in case target is HANDLER_INTERPRET 9671 cmp r0,#0 9672#if !defined(WITH_SELF_VERIFICATION) 9673 bxne r0 @ jump to the translation 9674 mov r2,#kJitTSelectRequest @ ask for trace selection 9675 @ fall-through to common_selectTrace 9676#else 9677 moveq r2,#kJitTSelectRequest @ ask for trace selection 9678 beq common_selectTrace 9679 /* 9680 * At this point, we have a target translation. However, if 9681 * that translation is actually the interpret-only pseudo-translation 9682 * we want to treat it the same as no translation. 9683 */ 9684 mov r10, r0 @ save target 9685 bl dvmCompilerGetInterpretTemplate 9686 cmp r0, r10 @ special case? 9687 bne jitSVShadowRunStart @ set up self verification shadow space 9688 @ Need to clear the inJitCodeCache flag 9689 ldr r10, [rGLUE, #offGlue_self] @ r10 <- glue->self 9690 mov r3, #0 @ 0 means not in the JIT code cache 9691 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land 9692 GET_INST_OPCODE(ip) 9693 GOTO_OPCODE(ip) 9694 /* no return */ 9695#endif 9696 9697/* 9698 * On entry: 9699 * r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot 9700 */ 9701common_selectTrace: 9702 str r2,[rGLUE,#offGlue_jitState] 9703 mov r2,#kInterpEntryInstr @ normal entry reason 9704 str r2,[rGLUE,#offGlue_entryPoint] 9705 mov r1,#1 @ set changeInterp 9706 b common_gotoBail 9707 9708#if defined(WITH_SELF_VERIFICATION) 9709/* 9710 * Save PC and registers to shadow memory for self verification mode 9711 * before jumping to native translation. 9712 * On entry: 9713 * rPC, rFP, rGLUE: the values that they should contain 9714 * r10: the address of the target translation. 9715 */ 9716jitSVShadowRunStart: 9717 mov r0,rPC @ r0<- program counter 9718 mov r1,rFP @ r1<- frame pointer 9719 mov r2,rGLUE @ r2<- InterpState pointer 9720 mov r3,r10 @ r3<- target translation 9721 bl dvmSelfVerificationSaveState @ save registers to shadow space 9722 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 9723 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 9724 bx r10 @ jump to the translation 9725 9726/* 9727 * Restore PC, registers, and interpState to original values 9728 * before jumping back to the interpreter. 9729 */ 9730jitSVShadowRunEnd: 9731 mov r1,rFP @ pass ending fp 9732 bl dvmSelfVerificationRestoreState @ restore pc and fp values 9733 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 9734 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 9735 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 9736 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 9737 cmp r1,#0 @ check for punt condition 9738 beq 1f 9739 mov r2,#kJitSelfVerification @ ask for self verification 9740 str r2,[rGLUE,#offGlue_jitState] 9741 mov r2,#kInterpEntryInstr @ normal entry reason 9742 str r2,[rGLUE,#offGlue_entryPoint] 9743 mov r1,#1 @ set changeInterp 9744 b common_gotoBail 9745 97461: @ exit to interpreter without check 9747 EXPORT_PC() 9748 adrl rIBASE, dvmAsmInstructionStart 9749 FETCH_INST() 9750 GET_INST_OPCODE(ip) 9751 GOTO_OPCODE(ip) 9752#endif 9753 9754#endif 9755 9756/* 9757 * Common code when a backward branch is taken. 9758 * 9759 * TODO: we could avoid a branch by just setting r0 and falling through 9760 * into the common_periodicChecks code, and having a test on r0 at the 9761 * end determine if we should return to the caller or update & branch to 9762 * the next instr. 9763 * 9764 * On entry: 9765 * r9 is PC adjustment *in bytes* 9766 */ 9767common_backwardBranch: 9768 mov r0, #kInterpEntryInstr 9769 bl common_periodicChecks 9770#if defined(WITH_JIT) 9771 GET_JIT_PROF_TABLE(r0) 9772 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9773 cmp r0,#0 9774 bne common_updateProfile 9775 GET_INST_OPCODE(ip) 9776 GOTO_OPCODE(ip) 9777#else 9778 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9779 GET_INST_OPCODE(ip) @ extract opcode from rINST 9780 GOTO_OPCODE(ip) @ jump to next instruction 9781#endif 9782 9783 9784/* 9785 * Need to see if the thread needs to be suspended or debugger/profiler 9786 * activity has begun. If so, we suspend the thread or side-exit to 9787 * the debug interpreter as appropriate. 9788 * 9789 * The common case is no activity on any of these, so we want to figure 9790 * that out quickly. If something is up, we can then sort out what. 9791 * 9792 * We want to be fast if the VM was built without debugger or profiler 9793 * support, but we also need to recognize that the system is usually 9794 * shipped with both of these enabled. 9795 * 9796 * TODO: reduce this so we're just checking a single location. 9797 * 9798 * On entry: 9799 * r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling) 9800 * r9 is trampoline PC adjustment *in bytes* 9801 */ 9802common_periodicChecks: 9803 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9804 9805 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9806 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9807 9808 ldr ip, [r3] @ ip<- suspendCount (int) 9809 9810 cmp r1, #0 @ debugger enabled? 9811#if defined(WORKAROUND_CORTEX_A9_745320) 9812 /* Don't use conditional loads if the HW defect exists */ 9813 beq 101f 9814 ldrb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9815101: 9816#else 9817 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9818#endif 9819 ldr r2, [r2] @ r2<- activeProfilers (int) 9820 orrnes ip, ip, r1 @ ip<- suspendCount | debuggerActive 9821 /* 9822 * Don't switch the interpreter in the libdvm_traceview build even if the 9823 * profiler is active. 9824 * The code here is opted for less intrusion instead of performance. 9825 * That is, *pActiveProfilers is still loaded into r2 even though it is not 9826 * used when WITH_INLINE_PROFILING is defined. 9827 */ 9828#if !defined(WITH_INLINE_PROFILING) 9829 orrs ip, ip, r2 @ ip<- suspend|debugger|profiler; set Z 9830#endif 9831 9832 9833 bxeq lr @ all zero, return 9834 9835 /* 9836 * One or more interesting events have happened. Figure out what. 9837 * 9838 * If debugging or profiling are compiled in, we need to disambiguate. 9839 * 9840 * r0 still holds the reentry type. 9841 */ 9842 ldr ip, [r3] @ ip<- suspendCount (int) 9843 cmp ip, #0 @ want suspend? 9844 beq 1f @ no, must be debugger/profiler 9845 9846 stmfd sp!, {r0, lr} @ preserve r0 and lr 9847#if defined(WITH_JIT) 9848 /* 9849 * Refresh the Jit's cached copy of profile table pointer. This pointer 9850 * doubles as the Jit's on/off switch. 9851 */ 9852 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable 9853 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9854 ldr r3, [r3] @ r3 <- pJitProfTable 9855 EXPORT_PC() @ need for precise GC 9856 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch 9857#else 9858 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9859 EXPORT_PC() @ need for precise GC 9860#endif 9861 bl dvmCheckSuspendPending @ do full check, suspend if necessary 9862 ldmfd sp!, {r0, lr} @ restore r0 and lr 9863 9864 /* 9865 * Reload the debugger/profiler enable flags. We're checking to see 9866 * if either of these got set while we were suspended. 9867 * 9868 * If WITH_INLINE_PROFILING is configured, don't check whether the profiler 9869 * is enabled or not as the profiling will be done inline. 9870 */ 9871 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9872 cmp r1, #0 @ debugger enabled? 9873#if defined(WORKAROUND_CORTEX_A9_745320) 9874 /* Don't use conditional loads if the HW defect exists */ 9875 beq 101f 9876 ldrb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9877101: 9878#else 9879 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9880#endif 9881 9882#if !defined(WITH_INLINE_PROFILING) 9883 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9884 ldr r2, [r2] @ r2<- activeProfilers (int) 9885 orrs r1, r1, r2 9886#else 9887 cmp r1, #0 @ only consult the debuggerActive flag 9888#endif 9889 9890 beq 2f 9891 98921: @ debugger/profiler enabled, bail out; glue->entryPoint was set above 9893 str r0, [rGLUE, #offGlue_entryPoint] @ store r0, need for debug/prof 9894 add rPC, rPC, r9 @ update rPC 9895 mov r1, #1 @ "want switch" = true 9896 b common_gotoBail @ side exit 9897 98982: 9899 bx lr @ nothing to do, return 9900 9901 9902/* 9903 * The equivalent of "goto bail", this calls through the "bail handler". 9904 * 9905 * State registers will be saved to the "glue" area before bailing. 9906 * 9907 * On entry: 9908 * r1 is "bool changeInterp", indicating if we want to switch to the 9909 * other interpreter or just bail all the way out 9910 */ 9911common_gotoBail: 9912 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9913 mov r0, rGLUE @ r0<- glue ptr 9914 b dvmMterpStdBail @ call(glue, changeInterp) 9915 9916 @add r1, r1, #1 @ using (boolean+1) 9917 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9918 @bl _longjmp @ does not return 9919 @bl common_abort 9920 9921 9922/* 9923 * Common code for method invocation with range. 9924 * 9925 * On entry: 9926 * r0 is "Method* methodToCall", the method we're trying to call 9927 */ 9928common_invokeMethodRange: 9929.LinvokeNewRange: 9930 @ prepare to copy args to "outs" area of current frame 9931 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9932 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9933 beq .LinvokeArgsDone @ if no args, skip the rest 9934 FETCH(r1, 2) @ r1<- CCCC 9935 9936 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9937 @ (very few methods have > 10 args; could unroll for common cases) 9938 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9939 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9940 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 99411: ldr r1, [r3], #4 @ val = *fp++ 9942 subs r2, r2, #1 @ count-- 9943 str r1, [r10], #4 @ *outs++ = val 9944 bne 1b @ ...while count != 0 9945 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9946 b .LinvokeArgsDone 9947 9948/* 9949 * Common code for method invocation without range. 9950 * 9951 * On entry: 9952 * r0 is "Method* methodToCall", the method we're trying to call 9953 */ 9954common_invokeMethodNoRange: 9955.LinvokeNewNoRange: 9956 @ prepare to copy args to "outs" area of current frame 9957 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9958 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9959 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9960 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9961 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9962 beq .LinvokeArgsDone 9963 9964 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9965.LinvokeNonRange: 9966 rsb r2, r2, #5 @ r2<- 5-r2 9967 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9968 bl common_abort @ (skipped due to ARM prefetch) 99695: and ip, rINST, #0x0f00 @ isolate A 9970 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 9971 mov r0, r0 @ nop 9972 str r2, [r10, #-4]! @ *--outs = vA 99734: and ip, r1, #0xf000 @ isolate G 9974 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 9975 mov r0, r0 @ nop 9976 str r2, [r10, #-4]! @ *--outs = vG 99773: and ip, r1, #0x0f00 @ isolate F 9978 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 9979 mov r0, r0 @ nop 9980 str r2, [r10, #-4]! @ *--outs = vF 99812: and ip, r1, #0x00f0 @ isolate E 9982 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 9983 mov r0, r0 @ nop 9984 str r2, [r10, #-4]! @ *--outs = vE 99851: and ip, r1, #0x000f @ isolate D 9986 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 9987 mov r0, r0 @ nop 9988 str r2, [r10, #-4]! @ *--outs = vD 99890: @ fall through to .LinvokeArgsDone 9990 9991.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 9992 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 9993 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 9994 @ find space for the new stack frame, check for overflow 9995 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 9996 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 9997 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 9998@ bl common_dumpRegs 9999 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 10000 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 10001 cmp r3, r9 @ bottom < interpStackEnd? 10002 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 10003 blo .LstackOverflow @ yes, this frame will overflow stack 10004 10005 @ set up newSaveArea 10006#ifdef EASY_GDB 10007 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 10008 str ip, [r10, #offStackSaveArea_prevSave] 10009#endif 10010 str rFP, [r10, #offStackSaveArea_prevFrame] 10011 str rPC, [r10, #offStackSaveArea_savedPc] 10012#if defined(WITH_JIT) 10013 mov r9, #0 10014 str r9, [r10, #offStackSaveArea_returnAddr] 10015#endif 10016#if defined(WITH_INLINE_PROFILING) 10017 stmfd sp!, {r0-r3} @ preserve r0-r3 10018 mov r1, r6 10019 @ r0=methodToCall, r1=rGlue 10020 bl dvmFastMethodTraceEnter 10021 ldmfd sp!, {r0-r3} @ restore r0-r3 10022#endif 10023 str r0, [r10, #offStackSaveArea_method] 10024 tst r3, #ACC_NATIVE 10025 bne .LinvokeNative 10026 10027 /* 10028 stmfd sp!, {r0-r3} 10029 bl common_printNewline 10030 mov r0, rFP 10031 mov r1, #0 10032 bl dvmDumpFp 10033 ldmfd sp!, {r0-r3} 10034 stmfd sp!, {r0-r3} 10035 mov r0, r1 10036 mov r1, r10 10037 bl dvmDumpFp 10038 bl common_printNewline 10039 ldmfd sp!, {r0-r3} 10040 */ 10041 10042 ldrh r9, [r2] @ r9 <- load INST from new PC 10043 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 10044 mov rPC, r2 @ publish new rPC 10045 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 10046 10047 @ Update "glue" values for the new method 10048 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 10049 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 10050 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 10051#if defined(WITH_JIT) 10052 GET_JIT_PROF_TABLE(r0) 10053 mov rFP, r1 @ fp = newFp 10054 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 10055 mov rINST, r9 @ publish new rINST 10056 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 10057 cmp r0,#0 10058 bne common_updateProfile 10059 GOTO_OPCODE(ip) @ jump to next instruction 10060#else 10061 mov rFP, r1 @ fp = newFp 10062 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 10063 mov rINST, r9 @ publish new rINST 10064 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 10065 GOTO_OPCODE(ip) @ jump to next instruction 10066#endif 10067 10068.LinvokeNative: 10069 @ Prep for the native call 10070 @ r0=methodToCall, r1=newFp, r10=newSaveArea 10071 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10072 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 10073 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 10074 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 10075 mov r9, r3 @ r9<- glue->self (preserve) 10076 10077 mov r2, r0 @ r2<- methodToCall 10078 mov r0, r1 @ r0<- newFp (points to args) 10079 add r1, rGLUE, #offGlue_retval @ r1<- &retval 10080 10081#ifdef ASSIST_DEBUGGER 10082 /* insert fake function header to help gdb find the stack frame */ 10083 b .Lskip 10084 .type dalvik_mterp, %function 10085dalvik_mterp: 10086 .fnstart 10087 MTERP_ENTRY1 10088 MTERP_ENTRY2 10089.Lskip: 10090#endif 10091 10092#if defined(WITH_INLINE_PROFILING) 10093 @ r2=JNIMethod, r6=rGLUE 10094 stmfd sp!, {r2,r6} 10095#endif 10096 10097 mov lr, pc @ set return addr 10098 ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 10099 10100#if defined(WITH_INLINE_PROFILING) 10101 @ r0=JNIMethod, r1=rGLUE 10102 ldmfd sp!, {r0-r1} 10103 bl dvmFastNativeMethodTraceExit 10104#endif 10105 10106#if defined(WITH_JIT) 10107 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status 10108#endif 10109 10110 @ native return; r9=self, r10=newSaveArea 10111 @ equivalent to dvmPopJniLocals 10112 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 10113 ldr r1, [r9, #offThread_exception] @ check for exception 10114#if defined(WITH_JIT) 10115 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable 10116#endif 10117 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 10118 cmp r1, #0 @ null? 10119 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 10120#if defined(WITH_JIT) 10121 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch 10122#endif 10123 bne common_exceptionThrown @ no, handle exception 10124 10125 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 10126 GET_INST_OPCODE(ip) @ extract opcode from rINST 10127 GOTO_OPCODE(ip) @ jump to next instruction 10128 10129.LstackOverflow: @ r0=methodToCall 10130 mov r1, r0 @ r1<- methodToCall 10131 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 10132 bl dvmHandleStackOverflow 10133 b common_exceptionThrown 10134#ifdef ASSIST_DEBUGGER 10135 .fnend 10136#endif 10137 10138 10139 /* 10140 * Common code for method invocation, calling through "glue code". 10141 * 10142 * TODO: now that we have range and non-range invoke handlers, this 10143 * needs to be split into two. Maybe just create entry points 10144 * that set r9 and jump here? 10145 * 10146 * On entry: 10147 * r0 is "Method* methodToCall", the method we're trying to call 10148 * r9 is "bool methodCallRange", indicating if this is a /range variant 10149 */ 10150 .if 0 10151.LinvokeOld: 10152 sub sp, sp, #8 @ space for args + pad 10153 FETCH(ip, 2) @ ip<- FEDC or CCCC 10154 mov r2, r0 @ A2<- methodToCall 10155 mov r0, rGLUE @ A0<- glue 10156 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 10157 mov r1, r9 @ A1<- methodCallRange 10158 mov r3, rINST, lsr #8 @ A3<- AA 10159 str ip, [sp, #0] @ A4<- ip 10160 bl dvmMterp_invokeMethod @ call the C invokeMethod 10161 add sp, sp, #8 @ remove arg area 10162 b common_resumeAfterGlueCall @ continue to next instruction 10163 .endif 10164 10165 10166 10167/* 10168 * Common code for handling a return instruction. 10169 * 10170 * This does not return. 10171 */ 10172common_returnFromMethod: 10173.LreturnNew: 10174 mov r0, #kInterpEntryReturn 10175 mov r9, #0 10176 bl common_periodicChecks 10177 10178#if defined(WITH_INLINE_PROFILING) 10179 stmfd sp!, {r0-r3} @ preserve r0-r3 10180 mov r0, r6 10181 @ r0=rGlue 10182 bl dvmFastJavaMethodTraceExit 10183 ldmfd sp!, {r0-r3} @ restore r0-r3 10184#endif 10185 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 10186 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 10187 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 10188 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 10189 @ r2<- method we're returning to 10190 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10191 cmp r2, #0 @ is this a break frame? 10192#if defined(WORKAROUND_CORTEX_A9_745320) 10193 /* Don't use conditional loads if the HW defect exists */ 10194 beq 101f 10195 ldr r10, [r2, #offMethod_clazz] @ r10<- method->clazz 10196101: 10197#else 10198 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 10199#endif 10200 mov r1, #0 @ "want switch" = false 10201 beq common_gotoBail @ break frame, bail out completely 10202 10203 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 10204 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 10205 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 10206 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 10207#if defined(WITH_JIT) 10208 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr 10209 mov rPC, r9 @ publish new rPC 10210 str r1, [rGLUE, #offGlue_methodClassDex] 10211 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land 10212 cmp r10, #0 @ caller is compiled code 10213 blxne r10 10214 GET_INST_OPCODE(ip) @ extract opcode from rINST 10215 GOTO_OPCODE(ip) @ jump to next instruction 10216#else 10217 GET_INST_OPCODE(ip) @ extract opcode from rINST 10218 mov rPC, r9 @ publish new rPC 10219 str r1, [rGLUE, #offGlue_methodClassDex] 10220 GOTO_OPCODE(ip) @ jump to next instruction 10221#endif 10222 10223 /* 10224 * Return handling, calls through "glue code". 10225 */ 10226 .if 0 10227.LreturnOld: 10228 SAVE_PC_FP_TO_GLUE() @ export state 10229 mov r0, rGLUE @ arg to function 10230 bl dvmMterp_returnFromMethod 10231 b common_resumeAfterGlueCall 10232 .endif 10233 10234 10235/* 10236 * Somebody has thrown an exception. Handle it. 10237 * 10238 * If the exception processing code returns to us (instead of falling 10239 * out of the interpreter), continue with whatever the next instruction 10240 * now happens to be. 10241 * 10242 * This does not return. 10243 */ 10244 .global dvmMterpCommonExceptionThrown 10245dvmMterpCommonExceptionThrown: 10246common_exceptionThrown: 10247.LexceptionNew: 10248 mov r0, #kInterpEntryThrow 10249 mov r9, #0 10250 bl common_periodicChecks 10251 10252 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 10253 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 10254 mov r1, r10 @ r1<- self 10255 mov r0, r9 @ r0<- exception 10256 bl dvmAddTrackedAlloc @ don't let the exception be GCed 10257 mov r3, #0 @ r3<- NULL 10258 str r3, [r10, #offThread_exception] @ self->exception = NULL 10259 10260 /* set up args and a local for "&fp" */ 10261 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 10262 str rFP, [sp, #-4]! @ *--sp = fp 10263 mov ip, sp @ ip<- &fp 10264 mov r3, #0 @ r3<- false 10265 str ip, [sp, #-4]! @ *--sp = &fp 10266 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 10267 mov r0, r10 @ r0<- self 10268 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 10269 mov r2, r9 @ r2<- exception 10270 sub r1, rPC, r1 @ r1<- pc - method->insns 10271 mov r1, r1, asr #1 @ r1<- offset in code units 10272 10273 /* call, r0 gets catchRelPc (a code-unit offset) */ 10274 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 10275 10276 /* fix earlier stack overflow if necessary; may trash rFP */ 10277 ldrb r1, [r10, #offThread_stackOverflowed] 10278 cmp r1, #0 @ did we overflow earlier? 10279 beq 1f @ no, skip ahead 10280 mov rFP, r0 @ save relPc result in rFP 10281 mov r0, r10 @ r0<- self 10282 mov r1, r9 @ r1<- exception 10283 bl dvmCleanupStackOverflow @ call(self) 10284 mov r0, rFP @ restore result 102851: 10286 10287 /* update frame pointer and check result from dvmFindCatchBlock */ 10288 ldr rFP, [sp, #4] @ retrieve the updated rFP 10289 cmp r0, #0 @ is catchRelPc < 0? 10290 add sp, sp, #8 @ restore stack 10291 bmi .LnotCaughtLocally 10292 10293 /* adjust locals to match self->curFrame and updated PC */ 10294 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 10295 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 10296 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 10297 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 10298 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 10299 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 10300 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 10301 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 10302 10303 /* release the tracked alloc on the exception */ 10304 mov r0, r9 @ r0<- exception 10305 mov r1, r10 @ r1<- self 10306 bl dvmReleaseTrackedAlloc @ release the exception 10307 10308 /* restore the exception if the handler wants it */ 10309 FETCH_INST() @ load rINST from rPC 10310 GET_INST_OPCODE(ip) @ extract opcode from rINST 10311 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 10312 streq r9, [r10, #offThread_exception] @ yes, restore the exception 10313 GOTO_OPCODE(ip) @ jump to next instruction 10314 10315.LnotCaughtLocally: @ r9=exception, r10=self 10316 /* fix stack overflow if necessary */ 10317 ldrb r1, [r10, #offThread_stackOverflowed] 10318 cmp r1, #0 @ did we overflow earlier? 10319 movne r0, r10 @ if yes: r0<- self 10320 movne r1, r9 @ if yes: r1<- exception 10321 blne dvmCleanupStackOverflow @ if yes: call(self) 10322 10323 @ may want to show "not caught locally" debug messages here 10324#if DVM_SHOW_EXCEPTION >= 2 10325 /* call __android_log_print(prio, tag, format, ...) */ 10326 /* "Exception %s from %s:%d not caught locally" */ 10327 @ dvmLineNumFromPC(method, pc - method->insns) 10328 ldr r0, [rGLUE, #offGlue_method] 10329 ldr r1, [r0, #offMethod_insns] 10330 sub r1, rPC, r1 10331 asr r1, r1, #1 10332 bl dvmLineNumFromPC 10333 str r0, [sp, #-4]! 10334 @ dvmGetMethodSourceFile(method) 10335 ldr r0, [rGLUE, #offGlue_method] 10336 bl dvmGetMethodSourceFile 10337 str r0, [sp, #-4]! 10338 @ exception->clazz->descriptor 10339 ldr r3, [r9, #offObject_clazz] 10340 ldr r3, [r3, #offClassObject_descriptor] 10341 @ 10342 ldr r2, strExceptionNotCaughtLocally 10343 ldr r1, strLogTag 10344 mov r0, #3 @ LOG_DEBUG 10345 bl __android_log_print 10346#endif 10347 str r9, [r10, #offThread_exception] @ restore exception 10348 mov r0, r9 @ r0<- exception 10349 mov r1, r10 @ r1<- self 10350 bl dvmReleaseTrackedAlloc @ release the exception 10351 mov r1, #0 @ "want switch" = false 10352 b common_gotoBail @ bail out 10353 10354 10355 /* 10356 * Exception handling, calls through "glue code". 10357 */ 10358 .if 0 10359.LexceptionOld: 10360 SAVE_PC_FP_TO_GLUE() @ export state 10361 mov r0, rGLUE @ arg to function 10362 bl dvmMterp_exceptionThrown 10363 b common_resumeAfterGlueCall 10364 .endif 10365 10366 10367/* 10368 * After returning from a "glued" function, pull out the updated 10369 * values and start executing at the next instruction. 10370 */ 10371common_resumeAfterGlueCall: 10372 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 10373 FETCH_INST() @ load rINST from rPC 10374 GET_INST_OPCODE(ip) @ extract opcode from rINST 10375 GOTO_OPCODE(ip) @ jump to next instruction 10376 10377/* 10378 * Invalid array index. Note that our calling convention is strange; we use r1 10379 * and r3 because those just happen to be the registers all our callers are 10380 * using. We shuffle them here before calling the C function. 10381 * r1: index 10382 * r3: size 10383 */ 10384common_errArrayIndex: 10385 EXPORT_PC() 10386 mov r0, r1 10387 mov r1, r3 10388 bl dvmThrowAIOOBE 10389 b common_exceptionThrown 10390 10391/* 10392 * Integer divide or mod by zero. 10393 */ 10394common_errDivideByZero: 10395 EXPORT_PC() 10396 ldr r0, strArithmeticException 10397 ldr r1, strDivideByZero 10398 bl dvmThrowException 10399 b common_exceptionThrown 10400 10401/* 10402 * Attempt to allocate an array with a negative size. 10403 */ 10404common_errNegativeArraySize: 10405 EXPORT_PC() 10406 ldr r0, strNegativeArraySizeException 10407 mov r1, #0 10408 bl dvmThrowException 10409 b common_exceptionThrown 10410 10411/* 10412 * Invocation of a non-existent method. 10413 */ 10414common_errNoSuchMethod: 10415 EXPORT_PC() 10416 ldr r0, strNoSuchMethodError 10417 mov r1, #0 10418 bl dvmThrowException 10419 b common_exceptionThrown 10420 10421/* 10422 * We encountered a null object when we weren't expecting one. We 10423 * export the PC, throw a NullPointerException, and goto the exception 10424 * processing code. 10425 */ 10426common_errNullObject: 10427 EXPORT_PC() 10428 ldr r0, strNullPointerException 10429 mov r1, #0 10430 bl dvmThrowException 10431 b common_exceptionThrown 10432 10433/* 10434 * For debugging, cause an immediate fault. The source address will 10435 * be in lr (use a bl instruction to jump here). 10436 */ 10437common_abort: 10438 ldr pc, .LdeadFood 10439.LdeadFood: 10440 .word 0xdeadf00d 10441 10442/* 10443 * Spit out a "we were here", preserving all registers. (The attempt 10444 * to save ip won't work, but we need to save an even number of 10445 * registers for EABI 64-bit stack alignment.) 10446 */ 10447 .macro SQUEAK num 10448common_squeak\num: 10449 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10450 ldr r0, strSqueak 10451 mov r1, #\num 10452 bl printf 10453 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10454 bx lr 10455 .endm 10456 10457 SQUEAK 0 10458 SQUEAK 1 10459 SQUEAK 2 10460 SQUEAK 3 10461 SQUEAK 4 10462 SQUEAK 5 10463 10464/* 10465 * Spit out the number in r0, preserving registers. 10466 */ 10467common_printNum: 10468 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10469 mov r1, r0 10470 ldr r0, strSqueak 10471 bl printf 10472 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10473 bx lr 10474 10475/* 10476 * Print a newline, preserving registers. 10477 */ 10478common_printNewline: 10479 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10480 ldr r0, strNewline 10481 bl printf 10482 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10483 bx lr 10484 10485 /* 10486 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 10487 */ 10488common_printHex: 10489 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10490 mov r1, r0 10491 ldr r0, strPrintHex 10492 bl printf 10493 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10494 bx lr 10495 10496/* 10497 * Print the 64-bit quantity in r0-r1, preserving registers. 10498 */ 10499common_printLong: 10500 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10501 mov r3, r1 10502 mov r2, r0 10503 ldr r0, strPrintLong 10504 bl printf 10505 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10506 bx lr 10507 10508/* 10509 * Print full method info. Pass the Method* in r0. Preserves regs. 10510 */ 10511common_printMethod: 10512 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10513 bl dvmMterpPrintMethod 10514 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10515 bx lr 10516 10517/* 10518 * Call a C helper function that dumps regs and possibly some 10519 * additional info. Requires the C function to be compiled in. 10520 */ 10521 .if 0 10522common_dumpRegs: 10523 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10524 bl dvmMterpDumpArmRegs 10525 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10526 bx lr 10527 .endif 10528 10529#if 0 10530/* 10531 * Experiment on VFP mode. 10532 * 10533 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 10534 * 10535 * Updates the bits specified by "mask", setting them to the values in "val". 10536 */ 10537setFPSCR: 10538 and r0, r0, r1 @ make sure no stray bits are set 10539 fmrx r2, fpscr @ get VFP reg 10540 mvn r1, r1 @ bit-invert mask 10541 and r2, r2, r1 @ clear masked bits 10542 orr r2, r2, r0 @ set specified bits 10543 fmxr fpscr, r2 @ set VFP reg 10544 mov r0, r2 @ return new value 10545 bx lr 10546 10547 .align 2 10548 .global dvmConfigureFP 10549 .type dvmConfigureFP, %function 10550dvmConfigureFP: 10551 stmfd sp!, {ip, lr} 10552 /* 0x03000000 sets DN/FZ */ 10553 /* 0x00009f00 clears the six exception enable flags */ 10554 bl common_squeak0 10555 mov r0, #0x03000000 @ r0<- 0x03000000 10556 add r1, r0, #0x9f00 @ r1<- 0x03009f00 10557 bl setFPSCR 10558 ldmfd sp!, {ip, pc} 10559#endif 10560 10561 10562/* 10563 * String references, must be close to the code that uses them. 10564 */ 10565 .align 2 10566strArithmeticException: 10567 .word .LstrArithmeticException 10568strDivideByZero: 10569 .word .LstrDivideByZero 10570strNegativeArraySizeException: 10571 .word .LstrNegativeArraySizeException 10572strNoSuchMethodError: 10573 .word .LstrNoSuchMethodError 10574strNullPointerException: 10575 .word .LstrNullPointerException 10576 10577strLogTag: 10578 .word .LstrLogTag 10579strExceptionNotCaughtLocally: 10580 .word .LstrExceptionNotCaughtLocally 10581 10582strNewline: 10583 .word .LstrNewline 10584strSqueak: 10585 .word .LstrSqueak 10586strPrintHex: 10587 .word .LstrPrintHex 10588strPrintLong: 10589 .word .LstrPrintLong 10590 10591/* 10592 * Zero-terminated ASCII string data. 10593 * 10594 * On ARM we have two choices: do like gcc does, and LDR from a .word 10595 * with the address, or use an ADR pseudo-op to get the address 10596 * directly. ADR saves 4 bytes and an indirection, but it's using a 10597 * PC-relative addressing mode and hence has a limited range, which 10598 * makes it not work well with mergeable string sections. 10599 */ 10600 .section .rodata.str1.4,"aMS",%progbits,1 10601 10602.LstrBadEntryPoint: 10603 .asciz "Bad entry point %d\n" 10604.LstrArithmeticException: 10605 .asciz "Ljava/lang/ArithmeticException;" 10606.LstrDivideByZero: 10607 .asciz "divide by zero" 10608.LstrFilledNewArrayNotImpl: 10609 .asciz "filled-new-array only implemented for objects and 'int'" 10610.LstrInternalError: 10611 .asciz "Ljava/lang/InternalError;" 10612.LstrInstantiationError: 10613 .asciz "Ljava/lang/InstantiationError;" 10614.LstrNegativeArraySizeException: 10615 .asciz "Ljava/lang/NegativeArraySizeException;" 10616.LstrNoSuchMethodError: 10617 .asciz "Ljava/lang/NoSuchMethodError;" 10618.LstrNullPointerException: 10619 .asciz "Ljava/lang/NullPointerException;" 10620 10621.LstrLogTag: 10622 .asciz "mterp" 10623.LstrExceptionNotCaughtLocally: 10624 .asciz "Exception %s from %s:%d not caught locally\n" 10625 10626.LstrNewline: 10627 .asciz "\n" 10628.LstrSqueak: 10629 .asciz "<%d>" 10630.LstrPrintHex: 10631 .asciz "<0x%x>" 10632.LstrPrintLong: 10633 .asciz "<%lld>" 10634 10635