InterpAsm-armv5te-vfp.S revision d88756df5b4dbc6fd450afd0019a5f64ebe4432d
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_UNUSED_FF: /* 0xff */ 7745/* File: armv5te/OP_UNUSED_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 class resolved from BBBB 7831 * r9 holds object 7832 */ 7833.LOP_CHECK_CAST_fullcheck: 7834 bl dvmInstanceofNonTrivial @ r0<- boolean result 7835 cmp r0, #0 @ failed? 7836 bne .LOP_CHECK_CAST_okay @ no, success 7837 7838 @ A cast has failed. We need to throw a ClassCastException with the 7839 @ class of the object that failed to be cast. 7840 EXPORT_PC() @ about to throw 7841 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 7842 ldr r0, .LstrClassCastExceptionPtr 7843 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 7844 bl dvmThrowExceptionWithClassMessage 7845 b common_exceptionThrown 7846 7847 /* 7848 * Resolution required. This is the least-likely path. 7849 * 7850 * r2 holds BBBB 7851 * r9 holds object 7852 */ 7853.LOP_CHECK_CAST_resolve: 7854 EXPORT_PC() @ resolve() could throw 7855 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7856 mov r1, r2 @ r1<- BBBB 7857 mov r2, #0 @ r2<- false 7858 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7859 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7860 cmp r0, #0 @ got null? 7861 beq common_exceptionThrown @ yes, handle exception 7862 mov r1, r0 @ r1<- class resolved from BBB 7863 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7864 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7865 7866.LstrClassCastExceptionPtr: 7867 .word .LstrClassCastException 7868 7869/* continuation for OP_INSTANCE_OF */ 7870 7871 /* 7872 * Trivial test failed, need to perform full check. This is common. 7873 * r0 holds obj->clazz 7874 * r1 holds class resolved from BBBB 7875 * r9 holds A 7876 */ 7877.LOP_INSTANCE_OF_fullcheck: 7878 bl dvmInstanceofNonTrivial @ r0<- boolean result 7879 @ fall through to OP_INSTANCE_OF_store 7880 7881 /* 7882 * r0 holds boolean result 7883 * r9 holds A 7884 */ 7885.LOP_INSTANCE_OF_store: 7886 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7887 SET_VREG(r0, r9) @ vA<- r0 7888 GET_INST_OPCODE(ip) @ extract opcode from rINST 7889 GOTO_OPCODE(ip) @ jump to next instruction 7890 7891 /* 7892 * Trivial test succeeded, save and bail. 7893 * r9 holds A 7894 */ 7895.LOP_INSTANCE_OF_trivial: 7896 mov r0, #1 @ indicate success 7897 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7898 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7899 SET_VREG(r0, r9) @ vA<- r0 7900 GET_INST_OPCODE(ip) @ extract opcode from rINST 7901 GOTO_OPCODE(ip) @ jump to next instruction 7902 7903 /* 7904 * Resolution required. This is the least-likely path. 7905 * 7906 * r3 holds BBBB 7907 * r9 holds A 7908 */ 7909.LOP_INSTANCE_OF_resolve: 7910 EXPORT_PC() @ resolve() could throw 7911 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7912 mov r1, r3 @ r1<- BBBB 7913 mov r2, #1 @ r2<- true 7914 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7915 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7916 cmp r0, #0 @ got null? 7917 beq common_exceptionThrown @ yes, handle exception 7918 mov r1, r0 @ r1<- class resolved from BBB 7919 mov r3, rINST, lsr #12 @ r3<- B 7920 GET_VREG(r0, r3) @ r0<- vB (object) 7921 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7922 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7923 7924/* continuation for OP_NEW_INSTANCE */ 7925 7926 .balign 32 @ minimize cache lines 7927.LOP_NEW_INSTANCE_finish: @ r0=new object 7928 mov r3, rINST, lsr #8 @ r3<- AA 7929 cmp r0, #0 @ failed? 7930 beq common_exceptionThrown @ yes, handle the exception 7931 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7932 GET_INST_OPCODE(ip) @ extract opcode from rINST 7933 SET_VREG(r0, r3) @ vAA<- r0 7934 GOTO_OPCODE(ip) @ jump to next instruction 7935 7936 /* 7937 * Class initialization required. 7938 * 7939 * r0 holds class object 7940 */ 7941.LOP_NEW_INSTANCE_needinit: 7942 mov r9, r0 @ save r0 7943 bl dvmInitClass @ initialize class 7944 cmp r0, #0 @ check boolean result 7945 mov r0, r9 @ restore r0 7946 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7947 b common_exceptionThrown @ failed, deal with init exception 7948 7949 /* 7950 * Resolution required. This is the least-likely path. 7951 * 7952 * r1 holds BBBB 7953 */ 7954.LOP_NEW_INSTANCE_resolve: 7955 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7956 mov r2, #0 @ r2<- false 7957 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7958 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7959 cmp r0, #0 @ got null? 7960 bne .LOP_NEW_INSTANCE_resolved @ no, continue 7961 b common_exceptionThrown @ yes, handle exception 7962 7963.LstrInstantiationErrorPtr: 7964 .word .LstrInstantiationError 7965 7966/* continuation for OP_NEW_ARRAY */ 7967 7968 7969 /* 7970 * Resolve class. (This is an uncommon case.) 7971 * 7972 * r1 holds array length 7973 * r2 holds class ref CCCC 7974 */ 7975.LOP_NEW_ARRAY_resolve: 7976 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7977 mov r9, r1 @ r9<- length (save) 7978 mov r1, r2 @ r1<- CCCC 7979 mov r2, #0 @ r2<- false 7980 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7981 bl dvmResolveClass @ r0<- call(clazz, ref) 7982 cmp r0, #0 @ got null? 7983 mov r1, r9 @ r1<- length (restore) 7984 beq common_exceptionThrown @ yes, handle exception 7985 @ fall through to OP_NEW_ARRAY_finish 7986 7987 /* 7988 * Finish allocation. 7989 * 7990 * r0 holds class 7991 * r1 holds array length 7992 */ 7993.LOP_NEW_ARRAY_finish: 7994 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 7995 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 7996 cmp r0, #0 @ failed? 7997 mov r2, rINST, lsr #8 @ r2<- A+ 7998 beq common_exceptionThrown @ yes, handle the exception 7999 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8000 and r2, r2, #15 @ r2<- A 8001 GET_INST_OPCODE(ip) @ extract opcode from rINST 8002 SET_VREG(r0, r2) @ vA<- r0 8003 GOTO_OPCODE(ip) @ jump to next instruction 8004 8005/* continuation for OP_FILLED_NEW_ARRAY */ 8006 8007 /* 8008 * On entry: 8009 * r0 holds array class 8010 * r10 holds AA or BA 8011 */ 8012.LOP_FILLED_NEW_ARRAY_continue: 8013 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8014 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8015 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 8016 .if 0 8017 mov r1, r10 @ r1<- AA (length) 8018 .else 8019 mov r1, r10, lsr #4 @ r1<- B (length) 8020 .endif 8021 cmp rINST, #'I' @ array of ints? 8022 cmpne rINST, #'L' @ array of objects? 8023 cmpne rINST, #'[' @ array of arrays? 8024 mov r9, r1 @ save length in r9 8025 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 8026 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8027 cmp r0, #0 @ null return? 8028 beq common_exceptionThrown @ alloc failed, handle exception 8029 8030 FETCH(r1, 2) @ r1<- FEDC or CCCC 8031 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8032 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 8033 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8034 subs r9, r9, #1 @ length--, check for neg 8035 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8036 bmi 2f @ was zero, bail 8037 8038 @ copy values from registers into the array 8039 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8040 .if 0 8041 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 80421: ldr r3, [r2], #4 @ r3<- *r2++ 8043 subs r9, r9, #1 @ count-- 8044 str r3, [r0], #4 @ *contents++ = vX 8045 bpl 1b 8046 @ continue at 2 8047 .else 8048 cmp r9, #4 @ length was initially 5? 8049 and r2, r10, #15 @ r2<- A 8050 bne 1f @ <= 4 args, branch 8051 GET_VREG(r3, r2) @ r3<- vA 8052 sub r9, r9, #1 @ count-- 8053 str r3, [r0, #16] @ contents[4] = vA 80541: and r2, r1, #15 @ r2<- F/E/D/C 8055 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8056 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8057 subs r9, r9, #1 @ count-- 8058 str r3, [r0], #4 @ *contents++ = vX 8059 bpl 1b 8060 @ continue at 2 8061 .endif 8062 80632: 8064 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 8065 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 8066 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8067 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8068 cmp r1, #'I' @ Is int array? 8069 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 8070 GOTO_OPCODE(ip) @ execute it 8071 8072 /* 8073 * Throw an exception indicating that we have not implemented this 8074 * mode of filled-new-array. 8075 */ 8076.LOP_FILLED_NEW_ARRAY_notimpl: 8077 ldr r0, .L_strInternalError 8078 ldr r1, .L_strFilledNewArrayNotImpl 8079 bl dvmThrowException 8080 b common_exceptionThrown 8081 8082 .if (!0) @ define in one or the other, not both 8083.L_strFilledNewArrayNotImpl: 8084 .word .LstrFilledNewArrayNotImpl 8085.L_strInternalError: 8086 .word .LstrInternalError 8087 .endif 8088 8089/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 8090 8091 /* 8092 * On entry: 8093 * r0 holds array class 8094 * r10 holds AA or BA 8095 */ 8096.LOP_FILLED_NEW_ARRAY_RANGE_continue: 8097 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8098 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8099 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 8100 .if 1 8101 mov r1, r10 @ r1<- AA (length) 8102 .else 8103 mov r1, r10, lsr #4 @ r1<- B (length) 8104 .endif 8105 cmp rINST, #'I' @ array of ints? 8106 cmpne rINST, #'L' @ array of objects? 8107 cmpne rINST, #'[' @ array of arrays? 8108 mov r9, r1 @ save length in r9 8109 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 8110 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8111 cmp r0, #0 @ null return? 8112 beq common_exceptionThrown @ alloc failed, handle exception 8113 8114 FETCH(r1, 2) @ r1<- FEDC or CCCC 8115 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8116 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 8117 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8118 subs r9, r9, #1 @ length--, check for neg 8119 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8120 bmi 2f @ was zero, bail 8121 8122 @ copy values from registers into the array 8123 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8124 .if 1 8125 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 81261: ldr r3, [r2], #4 @ r3<- *r2++ 8127 subs r9, r9, #1 @ count-- 8128 str r3, [r0], #4 @ *contents++ = vX 8129 bpl 1b 8130 @ continue at 2 8131 .else 8132 cmp r9, #4 @ length was initially 5? 8133 and r2, r10, #15 @ r2<- A 8134 bne 1f @ <= 4 args, branch 8135 GET_VREG(r3, r2) @ r3<- vA 8136 sub r9, r9, #1 @ count-- 8137 str r3, [r0, #16] @ contents[4] = vA 81381: and r2, r1, #15 @ r2<- F/E/D/C 8139 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8140 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8141 subs r9, r9, #1 @ count-- 8142 str r3, [r0], #4 @ *contents++ = vX 8143 bpl 1b 8144 @ continue at 2 8145 .endif 8146 81472: 8148 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 8149 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 8150 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8151 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8152 cmp r1, #'I' @ Is int array? 8153 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 8154 GOTO_OPCODE(ip) @ execute it 8155 8156 /* 8157 * Throw an exception indicating that we have not implemented this 8158 * mode of filled-new-array. 8159 */ 8160.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8161 ldr r0, .L_strInternalError 8162 ldr r1, .L_strFilledNewArrayNotImpl 8163 bl dvmThrowException 8164 b common_exceptionThrown 8165 8166 .if (!1) @ define in one or the other, not both 8167.L_strFilledNewArrayNotImpl: 8168 .word .LstrFilledNewArrayNotImpl 8169.L_strInternalError: 8170 .word .LstrInternalError 8171 .endif 8172 8173/* continuation for OP_CMPL_FLOAT */ 8174.LOP_CMPL_FLOAT_finish: 8175 SET_VREG(r0, r9) @ vAA<- r0 8176 GOTO_OPCODE(ip) @ jump to next instruction 8177 8178/* continuation for OP_CMPG_FLOAT */ 8179.LOP_CMPG_FLOAT_finish: 8180 SET_VREG(r0, r9) @ vAA<- r0 8181 GOTO_OPCODE(ip) @ jump to next instruction 8182 8183/* continuation for OP_CMPL_DOUBLE */ 8184.LOP_CMPL_DOUBLE_finish: 8185 SET_VREG(r0, r9) @ vAA<- r0 8186 GOTO_OPCODE(ip) @ jump to next instruction 8187 8188/* continuation for OP_CMPG_DOUBLE */ 8189.LOP_CMPG_DOUBLE_finish: 8190 SET_VREG(r0, r9) @ vAA<- r0 8191 GOTO_OPCODE(ip) @ jump to next instruction 8192 8193/* continuation for OP_CMP_LONG */ 8194 8195.LOP_CMP_LONG_less: 8196 mvn r1, #0 @ r1<- -1 8197 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8198 @ instead, we just replicate the tail end. 8199 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8200 SET_VREG(r1, r9) @ vAA<- r1 8201 GET_INST_OPCODE(ip) @ extract opcode from rINST 8202 GOTO_OPCODE(ip) @ jump to next instruction 8203 8204.LOP_CMP_LONG_greater: 8205 mov r1, #1 @ r1<- 1 8206 @ fall through to _finish 8207 8208.LOP_CMP_LONG_finish: 8209 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8210 SET_VREG(r1, r9) @ vAA<- r1 8211 GET_INST_OPCODE(ip) @ extract opcode from rINST 8212 GOTO_OPCODE(ip) @ jump to next instruction 8213 8214/* continuation for OP_AGET_WIDE */ 8215 8216.LOP_AGET_WIDE_finish: 8217 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8218 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8219 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8220 GET_INST_OPCODE(ip) @ extract opcode from rINST 8221 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8222 GOTO_OPCODE(ip) @ jump to next instruction 8223 8224/* continuation for OP_APUT_WIDE */ 8225 8226.LOP_APUT_WIDE_finish: 8227 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8228 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8229 GET_INST_OPCODE(ip) @ extract opcode from rINST 8230 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8231 GOTO_OPCODE(ip) @ jump to next instruction 8232 8233/* continuation for OP_APUT_OBJECT */ 8234 /* 8235 * On entry: 8236 * rINST = vBB (arrayObj) 8237 * r9 = vAA (obj) 8238 * r10 = offset into array (vBB + vCC * width) 8239 */ 8240.LOP_APUT_OBJECT_finish: 8241 cmp r9, #0 @ storing null reference? 8242 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8243 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8244 ldr r1, [rINST, #offObject_clazz] @ r1<- arrayObj->clazz 8245 bl dvmCanPutArrayElement @ test object type vs. array type 8246 cmp r0, #0 @ okay? 8247 beq common_errArrayStore @ no 8248 mov r1, rINST @ r1<- arrayObj 8249 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8250 ldr r2, [rGLUE, #offGlue_cardTable] @ get biased CT base 8251 add r10, #offArrayObject_contents @ r0<- pointer to slot 8252 GET_INST_OPCODE(ip) @ extract opcode from rINST 8253 str r9, [r10] @ vBB[vCC]<- vAA 8254 strb r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head 8255 GOTO_OPCODE(ip) @ jump to next instruction 8256.LOP_APUT_OBJECT_skip_check: 8257 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8258 GET_INST_OPCODE(ip) @ extract opcode from rINST 8259 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8260 GOTO_OPCODE(ip) @ jump to next instruction 8261 8262/* continuation for OP_IGET */ 8263 8264 /* 8265 * Currently: 8266 * r0 holds resolved field 8267 * r9 holds object 8268 */ 8269.LOP_IGET_finish: 8270 @bl common_squeak0 8271 cmp r9, #0 @ check object for null 8272 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8273 beq common_errNullObject @ object was null 8274 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8275 @ no-op @ acquiring load 8276 mov r2, rINST, lsr #8 @ r2<- A+ 8277 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8278 and r2, r2, #15 @ r2<- A 8279 GET_INST_OPCODE(ip) @ extract opcode from rINST 8280 SET_VREG(r0, r2) @ fp[A]<- r0 8281 GOTO_OPCODE(ip) @ jump to next instruction 8282 8283/* continuation for OP_IGET_WIDE */ 8284 8285 /* 8286 * Currently: 8287 * r0 holds resolved field 8288 * r9 holds object 8289 */ 8290.LOP_IGET_WIDE_finish: 8291 cmp r9, #0 @ check object for null 8292 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8293 beq common_errNullObject @ object was null 8294 .if 0 8295 add r0, r9, r3 @ r0<- address of field 8296 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 8297 .else 8298 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8299 .endif 8300 mov r2, rINST, lsr #8 @ r2<- A+ 8301 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8302 and r2, r2, #15 @ r2<- A 8303 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8304 GET_INST_OPCODE(ip) @ extract opcode from rINST 8305 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8306 GOTO_OPCODE(ip) @ jump to next instruction 8307 8308/* continuation for OP_IGET_OBJECT */ 8309 8310 /* 8311 * Currently: 8312 * r0 holds resolved field 8313 * r9 holds object 8314 */ 8315.LOP_IGET_OBJECT_finish: 8316 @bl common_squeak0 8317 cmp r9, #0 @ check object for null 8318 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8319 beq common_errNullObject @ object was null 8320 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8321 @ no-op @ acquiring load 8322 mov r2, rINST, lsr #8 @ r2<- A+ 8323 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8324 and r2, r2, #15 @ r2<- A 8325 GET_INST_OPCODE(ip) @ extract opcode from rINST 8326 SET_VREG(r0, r2) @ fp[A]<- r0 8327 GOTO_OPCODE(ip) @ jump to next instruction 8328 8329/* continuation for OP_IGET_BOOLEAN */ 8330 8331 /* 8332 * Currently: 8333 * r0 holds resolved field 8334 * r9 holds object 8335 */ 8336.LOP_IGET_BOOLEAN_finish: 8337 @bl common_squeak1 8338 cmp r9, #0 @ check object for null 8339 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8340 beq common_errNullObject @ object was null 8341 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8342 @ no-op @ acquiring load 8343 mov r2, rINST, lsr #8 @ r2<- A+ 8344 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8345 and r2, r2, #15 @ r2<- A 8346 GET_INST_OPCODE(ip) @ extract opcode from rINST 8347 SET_VREG(r0, r2) @ fp[A]<- r0 8348 GOTO_OPCODE(ip) @ jump to next instruction 8349 8350/* continuation for OP_IGET_BYTE */ 8351 8352 /* 8353 * Currently: 8354 * r0 holds resolved field 8355 * r9 holds object 8356 */ 8357.LOP_IGET_BYTE_finish: 8358 @bl common_squeak2 8359 cmp r9, #0 @ check object for null 8360 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8361 beq common_errNullObject @ object was null 8362 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8363 @ no-op @ acquiring load 8364 mov r2, rINST, lsr #8 @ r2<- A+ 8365 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8366 and r2, r2, #15 @ r2<- A 8367 GET_INST_OPCODE(ip) @ extract opcode from rINST 8368 SET_VREG(r0, r2) @ fp[A]<- r0 8369 GOTO_OPCODE(ip) @ jump to next instruction 8370 8371/* continuation for OP_IGET_CHAR */ 8372 8373 /* 8374 * Currently: 8375 * r0 holds resolved field 8376 * r9 holds object 8377 */ 8378.LOP_IGET_CHAR_finish: 8379 @bl common_squeak3 8380 cmp r9, #0 @ check object for null 8381 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8382 beq common_errNullObject @ object was null 8383 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8384 @ no-op @ acquiring load 8385 mov r2, rINST, lsr #8 @ r2<- A+ 8386 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8387 and r2, r2, #15 @ r2<- A 8388 GET_INST_OPCODE(ip) @ extract opcode from rINST 8389 SET_VREG(r0, r2) @ fp[A]<- r0 8390 GOTO_OPCODE(ip) @ jump to next instruction 8391 8392/* continuation for OP_IGET_SHORT */ 8393 8394 /* 8395 * Currently: 8396 * r0 holds resolved field 8397 * r9 holds object 8398 */ 8399.LOP_IGET_SHORT_finish: 8400 @bl common_squeak4 8401 cmp r9, #0 @ check object for null 8402 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8403 beq common_errNullObject @ object was null 8404 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8405 @ no-op @ acquiring load 8406 mov r2, rINST, lsr #8 @ r2<- A+ 8407 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8408 and r2, r2, #15 @ r2<- A 8409 GET_INST_OPCODE(ip) @ extract opcode from rINST 8410 SET_VREG(r0, r2) @ fp[A]<- r0 8411 GOTO_OPCODE(ip) @ jump to next instruction 8412 8413/* continuation for OP_IPUT */ 8414 8415 /* 8416 * Currently: 8417 * r0 holds resolved field 8418 * r9 holds object 8419 */ 8420.LOP_IPUT_finish: 8421 @bl common_squeak0 8422 mov r1, rINST, lsr #8 @ r1<- A+ 8423 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8424 and r1, r1, #15 @ r1<- A 8425 cmp r9, #0 @ check object for null 8426 GET_VREG(r0, r1) @ r0<- fp[A] 8427 beq common_errNullObject @ object was null 8428 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8429 GET_INST_OPCODE(ip) @ extract opcode from rINST 8430 @ no-op @ releasing store 8431 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8432 GOTO_OPCODE(ip) @ jump to next instruction 8433 8434/* continuation for OP_IPUT_WIDE */ 8435 8436 /* 8437 * Currently: 8438 * r0 holds resolved field 8439 * r9 holds object 8440 */ 8441.LOP_IPUT_WIDE_finish: 8442 mov r2, rINST, lsr #8 @ r2<- A+ 8443 cmp r9, #0 @ check object for null 8444 and r2, r2, #15 @ r2<- A 8445 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8446 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8447 beq common_errNullObject @ object was null 8448 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8449 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8450 GET_INST_OPCODE(r10) @ extract opcode from rINST 8451 .if 0 8452 add r2, r9, r3 @ r2<- target address 8453 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 8454 .else 8455 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 8456 .endif 8457 GOTO_OPCODE(r10) @ jump to next instruction 8458 8459/* continuation for OP_IPUT_OBJECT */ 8460 8461 /* 8462 * Currently: 8463 * r0 holds resolved field 8464 * r9 holds object 8465 */ 8466.LOP_IPUT_OBJECT_finish: 8467 @bl common_squeak0 8468 mov r1, rINST, lsr #8 @ r1<- A+ 8469 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8470 and r1, r1, #15 @ r1<- A 8471 cmp r9, #0 @ check object for null 8472 GET_VREG(r0, r1) @ r0<- fp[A] 8473 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8474 beq common_errNullObject @ object was null 8475 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8476 GET_INST_OPCODE(ip) @ extract opcode from rINST 8477 @ no-op @ releasing store 8478 str r0, [r9, r3] @ obj.field (32 bits)<- r0 8479 cmp r0, #0 @ stored a null reference? 8480 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 8481 GOTO_OPCODE(ip) @ jump to next instruction 8482 8483/* continuation for OP_IPUT_BOOLEAN */ 8484 8485 /* 8486 * Currently: 8487 * r0 holds resolved field 8488 * r9 holds object 8489 */ 8490.LOP_IPUT_BOOLEAN_finish: 8491 @bl common_squeak1 8492 mov r1, rINST, lsr #8 @ r1<- A+ 8493 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8494 and r1, r1, #15 @ r1<- A 8495 cmp r9, #0 @ check object for null 8496 GET_VREG(r0, r1) @ r0<- fp[A] 8497 beq common_errNullObject @ object was null 8498 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8499 GET_INST_OPCODE(ip) @ extract opcode from rINST 8500 @ no-op @ releasing store 8501 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8502 GOTO_OPCODE(ip) @ jump to next instruction 8503 8504/* continuation for OP_IPUT_BYTE */ 8505 8506 /* 8507 * Currently: 8508 * r0 holds resolved field 8509 * r9 holds object 8510 */ 8511.LOP_IPUT_BYTE_finish: 8512 @bl common_squeak2 8513 mov r1, rINST, lsr #8 @ r1<- A+ 8514 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8515 and r1, r1, #15 @ r1<- A 8516 cmp r9, #0 @ check object for null 8517 GET_VREG(r0, r1) @ r0<- fp[A] 8518 beq common_errNullObject @ object was null 8519 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8520 GET_INST_OPCODE(ip) @ extract opcode from rINST 8521 @ no-op @ releasing store 8522 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8523 GOTO_OPCODE(ip) @ jump to next instruction 8524 8525/* continuation for OP_IPUT_CHAR */ 8526 8527 /* 8528 * Currently: 8529 * r0 holds resolved field 8530 * r9 holds object 8531 */ 8532.LOP_IPUT_CHAR_finish: 8533 @bl common_squeak3 8534 mov r1, rINST, lsr #8 @ r1<- A+ 8535 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8536 and r1, r1, #15 @ r1<- A 8537 cmp r9, #0 @ check object for null 8538 GET_VREG(r0, r1) @ r0<- fp[A] 8539 beq common_errNullObject @ object was null 8540 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8541 GET_INST_OPCODE(ip) @ extract opcode from rINST 8542 @ no-op @ releasing store 8543 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8544 GOTO_OPCODE(ip) @ jump to next instruction 8545 8546/* continuation for OP_IPUT_SHORT */ 8547 8548 /* 8549 * Currently: 8550 * r0 holds resolved field 8551 * r9 holds object 8552 */ 8553.LOP_IPUT_SHORT_finish: 8554 @bl common_squeak4 8555 mov r1, rINST, lsr #8 @ r1<- A+ 8556 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8557 and r1, r1, #15 @ r1<- A 8558 cmp r9, #0 @ check object for null 8559 GET_VREG(r0, r1) @ r0<- fp[A] 8560 beq common_errNullObject @ object was null 8561 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8562 GET_INST_OPCODE(ip) @ extract opcode from rINST 8563 @ no-op @ releasing store 8564 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8565 GOTO_OPCODE(ip) @ jump to next instruction 8566 8567/* continuation for OP_SGET */ 8568 8569 /* 8570 * Continuation if the field has not yet been resolved. 8571 * r1: BBBB field ref 8572 */ 8573.LOP_SGET_resolve: 8574 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8575 EXPORT_PC() @ resolve() could throw, so export now 8576 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8577 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8578 cmp r0, #0 @ success? 8579 bne .LOP_SGET_finish @ yes, finish 8580 b common_exceptionThrown @ no, handle exception 8581 8582/* continuation for OP_SGET_WIDE */ 8583 8584 /* 8585 * Continuation if the field has not yet been resolved. 8586 * r1: BBBB field ref 8587 * 8588 * Returns StaticField pointer in r0. 8589 */ 8590.LOP_SGET_WIDE_resolve: 8591 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8592 EXPORT_PC() @ resolve() could throw, so export now 8593 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8594 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8595 cmp r0, #0 @ success? 8596 bne .LOP_SGET_WIDE_finish @ yes, finish 8597 b common_exceptionThrown @ no, handle exception 8598 8599/* continuation for OP_SGET_OBJECT */ 8600 8601 /* 8602 * Continuation if the field has not yet been resolved. 8603 * r1: BBBB field ref 8604 */ 8605.LOP_SGET_OBJECT_resolve: 8606 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8607 EXPORT_PC() @ resolve() could throw, so export now 8608 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8609 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8610 cmp r0, #0 @ success? 8611 bne .LOP_SGET_OBJECT_finish @ yes, finish 8612 b common_exceptionThrown @ no, handle exception 8613 8614/* continuation for OP_SGET_BOOLEAN */ 8615 8616 /* 8617 * Continuation if the field has not yet been resolved. 8618 * r1: BBBB field ref 8619 */ 8620.LOP_SGET_BOOLEAN_resolve: 8621 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8622 EXPORT_PC() @ resolve() could throw, so export now 8623 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8624 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8625 cmp r0, #0 @ success? 8626 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8627 b common_exceptionThrown @ no, handle exception 8628 8629/* continuation for OP_SGET_BYTE */ 8630 8631 /* 8632 * Continuation if the field has not yet been resolved. 8633 * r1: BBBB field ref 8634 */ 8635.LOP_SGET_BYTE_resolve: 8636 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8637 EXPORT_PC() @ resolve() could throw, so export now 8638 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8639 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8640 cmp r0, #0 @ success? 8641 bne .LOP_SGET_BYTE_finish @ yes, finish 8642 b common_exceptionThrown @ no, handle exception 8643 8644/* continuation for OP_SGET_CHAR */ 8645 8646 /* 8647 * Continuation if the field has not yet been resolved. 8648 * r1: BBBB field ref 8649 */ 8650.LOP_SGET_CHAR_resolve: 8651 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8652 EXPORT_PC() @ resolve() could throw, so export now 8653 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8654 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8655 cmp r0, #0 @ success? 8656 bne .LOP_SGET_CHAR_finish @ yes, finish 8657 b common_exceptionThrown @ no, handle exception 8658 8659/* continuation for OP_SGET_SHORT */ 8660 8661 /* 8662 * Continuation if the field has not yet been resolved. 8663 * r1: BBBB field ref 8664 */ 8665.LOP_SGET_SHORT_resolve: 8666 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8667 EXPORT_PC() @ resolve() could throw, so export now 8668 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8669 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8670 cmp r0, #0 @ success? 8671 bne .LOP_SGET_SHORT_finish @ yes, finish 8672 b common_exceptionThrown @ no, handle exception 8673 8674/* continuation for OP_SPUT */ 8675 8676 /* 8677 * Continuation if the field has not yet been resolved. 8678 * r1: BBBB field ref 8679 */ 8680.LOP_SPUT_resolve: 8681 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8682 EXPORT_PC() @ resolve() could throw, so export now 8683 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8684 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8685 cmp r0, #0 @ success? 8686 bne .LOP_SPUT_finish @ yes, finish 8687 b common_exceptionThrown @ no, handle exception 8688 8689/* continuation for OP_SPUT_WIDE */ 8690 8691 /* 8692 * Continuation if the field has not yet been resolved. 8693 * r1: BBBB field ref 8694 * r9: &fp[AA] 8695 * 8696 * Returns StaticField pointer in r2. 8697 */ 8698.LOP_SPUT_WIDE_resolve: 8699 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8700 EXPORT_PC() @ resolve() could throw, so export now 8701 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8702 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8703 cmp r0, #0 @ success? 8704 mov r2, r0 @ copy to r2 8705 bne .LOP_SPUT_WIDE_finish @ yes, finish 8706 b common_exceptionThrown @ no, handle exception 8707 8708/* continuation for OP_SPUT_OBJECT */ 8709.LOP_SPUT_OBJECT_finish: @ field ptr in r0 8710 mov r2, rINST, lsr #8 @ r2<- AA 8711 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8712 GET_VREG(r1, r2) @ r1<- fp[AA] 8713 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8714 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz 8715 GET_INST_OPCODE(ip) @ extract opcode from rINST 8716 @ no-op @ releasing store 8717 str r1, [r0, #offStaticField_value] @ field<- vAA 8718 cmp r1, #0 @ stored a null object? 8719 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 8720 GOTO_OPCODE(ip) @ jump to next instruction 8721 8722/* continuation for OP_SPUT_BOOLEAN */ 8723 8724 /* 8725 * Continuation if the field has not yet been resolved. 8726 * r1: BBBB field ref 8727 */ 8728.LOP_SPUT_BOOLEAN_resolve: 8729 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8730 EXPORT_PC() @ resolve() could throw, so export now 8731 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8732 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8733 cmp r0, #0 @ success? 8734 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 8735 b common_exceptionThrown @ no, handle exception 8736 8737/* continuation for OP_SPUT_BYTE */ 8738 8739 /* 8740 * Continuation if the field has not yet been resolved. 8741 * r1: BBBB field ref 8742 */ 8743.LOP_SPUT_BYTE_resolve: 8744 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8745 EXPORT_PC() @ resolve() could throw, so export now 8746 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8747 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8748 cmp r0, #0 @ success? 8749 bne .LOP_SPUT_BYTE_finish @ yes, finish 8750 b common_exceptionThrown @ no, handle exception 8751 8752/* continuation for OP_SPUT_CHAR */ 8753 8754 /* 8755 * Continuation if the field has not yet been resolved. 8756 * r1: BBBB field ref 8757 */ 8758.LOP_SPUT_CHAR_resolve: 8759 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8760 EXPORT_PC() @ resolve() could throw, so export now 8761 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8762 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8763 cmp r0, #0 @ success? 8764 bne .LOP_SPUT_CHAR_finish @ yes, finish 8765 b common_exceptionThrown @ no, handle exception 8766 8767/* continuation for OP_SPUT_SHORT */ 8768 8769 /* 8770 * Continuation if the field has not yet been resolved. 8771 * r1: BBBB field ref 8772 */ 8773.LOP_SPUT_SHORT_resolve: 8774 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8775 EXPORT_PC() @ resolve() could throw, so export now 8776 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8777 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8778 cmp r0, #0 @ success? 8779 bne .LOP_SPUT_SHORT_finish @ yes, finish 8780 b common_exceptionThrown @ no, handle exception 8781 8782/* continuation for OP_INVOKE_VIRTUAL */ 8783 8784 /* 8785 * At this point: 8786 * r0 = resolved base method 8787 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8788 */ 8789.LOP_INVOKE_VIRTUAL_continue: 8790 GET_VREG(r1, r10) @ r1<- "this" ptr 8791 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8792 cmp r1, #0 @ is "this" null? 8793 beq common_errNullObject @ null "this", throw exception 8794 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8795 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8796 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8797 bl common_invokeMethodNoRange @ continue on 8798 8799/* continuation for OP_INVOKE_SUPER */ 8800 8801 /* 8802 * At this point: 8803 * r0 = resolved base method 8804 * r9 = method->clazz 8805 */ 8806.LOP_INVOKE_SUPER_continue: 8807 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8808 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8809 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8810 EXPORT_PC() @ must export for invoke 8811 cmp r2, r3 @ compare (methodIndex, vtableCount) 8812 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 8813 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8814 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8815 bl common_invokeMethodNoRange @ continue on 8816 8817.LOP_INVOKE_SUPER_resolve: 8818 mov r0, r9 @ r0<- method->clazz 8819 mov r2, #METHOD_VIRTUAL @ resolver method type 8820 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8821 cmp r0, #0 @ got null? 8822 bne .LOP_INVOKE_SUPER_continue @ no, continue 8823 b common_exceptionThrown @ yes, handle exception 8824 8825 /* 8826 * Throw a NoSuchMethodError with the method name as the message. 8827 * r0 = resolved base method 8828 */ 8829.LOP_INVOKE_SUPER_nsm: 8830 ldr r1, [r0, #offMethod_name] @ r1<- method name 8831 b common_errNoSuchMethod 8832 8833/* continuation for OP_INVOKE_DIRECT */ 8834 8835 /* 8836 * On entry: 8837 * r1 = reference (BBBB or CCCC) 8838 * r10 = "this" register 8839 */ 8840.LOP_INVOKE_DIRECT_resolve: 8841 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8842 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8843 mov r2, #METHOD_DIRECT @ resolver method type 8844 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8845 cmp r0, #0 @ got null? 8846 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8847 bne .LOP_INVOKE_DIRECT_finish @ no, continue 8848 b common_exceptionThrown @ yes, handle exception 8849 8850/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 8851 8852 /* 8853 * At this point: 8854 * r0 = resolved base method 8855 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8856 */ 8857.LOP_INVOKE_VIRTUAL_RANGE_continue: 8858 GET_VREG(r1, r10) @ r1<- "this" ptr 8859 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8860 cmp r1, #0 @ is "this" null? 8861 beq common_errNullObject @ null "this", throw exception 8862 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8863 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8864 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8865 bl common_invokeMethodRange @ continue on 8866 8867/* continuation for OP_INVOKE_SUPER_RANGE */ 8868 8869 /* 8870 * At this point: 8871 * r0 = resolved base method 8872 * r9 = method->clazz 8873 */ 8874.LOP_INVOKE_SUPER_RANGE_continue: 8875 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8876 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8877 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8878 EXPORT_PC() @ must export for invoke 8879 cmp r2, r3 @ compare (methodIndex, vtableCount) 8880 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 8881 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8882 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8883 bl common_invokeMethodRange @ continue on 8884 8885.LOP_INVOKE_SUPER_RANGE_resolve: 8886 mov r0, r9 @ r0<- method->clazz 8887 mov r2, #METHOD_VIRTUAL @ resolver method type 8888 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8889 cmp r0, #0 @ got null? 8890 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 8891 b common_exceptionThrown @ yes, handle exception 8892 8893 /* 8894 * Throw a NoSuchMethodError with the method name as the message. 8895 * r0 = resolved base method 8896 */ 8897.LOP_INVOKE_SUPER_RANGE_nsm: 8898 ldr r1, [r0, #offMethod_name] @ r1<- method name 8899 b common_errNoSuchMethod 8900 8901/* continuation for OP_INVOKE_DIRECT_RANGE */ 8902 8903 /* 8904 * On entry: 8905 * r1 = reference (BBBB or CCCC) 8906 * r10 = "this" register 8907 */ 8908.LOP_INVOKE_DIRECT_RANGE_resolve: 8909 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8910 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8911 mov r2, #METHOD_DIRECT @ resolver method type 8912 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8913 cmp r0, #0 @ got null? 8914 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8915 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 8916 b common_exceptionThrown @ yes, handle exception 8917 8918/* continuation for OP_FLOAT_TO_LONG */ 8919/* 8920 * Convert the float in r0 to a long in r0/r1. 8921 * 8922 * We have to clip values to long min/max per the specification. The 8923 * expected common case is a "reasonable" value that converts directly 8924 * to modest integer. The EABI convert function isn't doing this for us. 8925 */ 8926f2l_doconv: 8927 stmfd sp!, {r4, lr} 8928 mov r1, #0x5f000000 @ (float)maxlong 8929 mov r4, r0 8930 bl __aeabi_fcmpge @ is arg >= maxlong? 8931 cmp r0, #0 @ nonzero == yes 8932 mvnne r0, #0 @ return maxlong (7fffffff) 8933 mvnne r1, #0x80000000 8934 ldmnefd sp!, {r4, pc} 8935 8936 mov r0, r4 @ recover arg 8937 mov r1, #0xdf000000 @ (float)minlong 8938 bl __aeabi_fcmple @ is arg <= minlong? 8939 cmp r0, #0 @ nonzero == yes 8940 movne r0, #0 @ return minlong (80000000) 8941 movne r1, #0x80000000 8942 ldmnefd sp!, {r4, pc} 8943 8944 mov r0, r4 @ recover arg 8945 mov r1, r4 8946 bl __aeabi_fcmpeq @ is arg == self? 8947 cmp r0, #0 @ zero == no 8948 moveq r1, #0 @ return zero for NaN 8949 ldmeqfd sp!, {r4, pc} 8950 8951 mov r0, r4 @ recover arg 8952 bl __aeabi_f2lz @ convert float to long 8953 ldmfd sp!, {r4, pc} 8954 8955/* continuation for OP_DOUBLE_TO_LONG */ 8956/* 8957 * Convert the double in r0/r1 to a long in r0/r1. 8958 * 8959 * We have to clip values to long min/max per the specification. The 8960 * expected common case is a "reasonable" value that converts directly 8961 * to modest integer. The EABI convert function isn't doing this for us. 8962 */ 8963d2l_doconv: 8964 stmfd sp!, {r4, r5, lr} @ save regs 8965 mov r3, #0x43000000 @ maxlong, as a double (high word) 8966 add r3, #0x00e00000 @ 0x43e00000 8967 mov r2, #0 @ maxlong, as a double (low word) 8968 sub sp, sp, #4 @ align for EABI 8969 mov r4, r0 @ save a copy of r0 8970 mov r5, r1 @ and r1 8971 bl __aeabi_dcmpge @ is arg >= maxlong? 8972 cmp r0, #0 @ nonzero == yes 8973 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 8974 mvnne r1, #0x80000000 8975 bne 1f 8976 8977 mov r0, r4 @ recover arg 8978 mov r1, r5 8979 mov r3, #0xc3000000 @ minlong, as a double (high word) 8980 add r3, #0x00e00000 @ 0xc3e00000 8981 mov r2, #0 @ minlong, as a double (low word) 8982 bl __aeabi_dcmple @ is arg <= minlong? 8983 cmp r0, #0 @ nonzero == yes 8984 movne r0, #0 @ return minlong (8000000000000000) 8985 movne r1, #0x80000000 8986 bne 1f 8987 8988 mov r0, r4 @ recover arg 8989 mov r1, r5 8990 mov r2, r4 @ compare against self 8991 mov r3, r5 8992 bl __aeabi_dcmpeq @ is arg == self? 8993 cmp r0, #0 @ zero == no 8994 moveq r1, #0 @ return zero for NaN 8995 beq 1f 8996 8997 mov r0, r4 @ recover arg 8998 mov r1, r5 8999 bl __aeabi_d2lz @ convert double to long 9000 90011: 9002 add sp, sp, #4 9003 ldmfd sp!, {r4, r5, pc} 9004 9005/* continuation for OP_MUL_LONG */ 9006 9007.LOP_MUL_LONG_finish: 9008 GET_INST_OPCODE(ip) @ extract opcode from rINST 9009 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 9010 GOTO_OPCODE(ip) @ jump to next instruction 9011 9012/* continuation for OP_SHL_LONG */ 9013 9014.LOP_SHL_LONG_finish: 9015 mov r0, r0, asl r2 @ r0<- r0 << r2 9016 GET_INST_OPCODE(ip) @ extract opcode from rINST 9017 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9018 GOTO_OPCODE(ip) @ jump to next instruction 9019 9020/* continuation for OP_SHR_LONG */ 9021 9022.LOP_SHR_LONG_finish: 9023 mov r1, r1, asr r2 @ r1<- r1 >> r2 9024 GET_INST_OPCODE(ip) @ extract opcode from rINST 9025 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9026 GOTO_OPCODE(ip) @ jump to next instruction 9027 9028/* continuation for OP_USHR_LONG */ 9029 9030.LOP_USHR_LONG_finish: 9031 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 9032 GET_INST_OPCODE(ip) @ extract opcode from rINST 9033 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9034 GOTO_OPCODE(ip) @ jump to next instruction 9035 9036/* continuation for OP_SHL_LONG_2ADDR */ 9037 9038.LOP_SHL_LONG_2ADDR_finish: 9039 GET_INST_OPCODE(ip) @ extract opcode from rINST 9040 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9041 GOTO_OPCODE(ip) @ jump to next instruction 9042 9043/* continuation for OP_SHR_LONG_2ADDR */ 9044 9045.LOP_SHR_LONG_2ADDR_finish: 9046 GET_INST_OPCODE(ip) @ extract opcode from rINST 9047 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9048 GOTO_OPCODE(ip) @ jump to next instruction 9049 9050/* continuation for OP_USHR_LONG_2ADDR */ 9051 9052.LOP_USHR_LONG_2ADDR_finish: 9053 GET_INST_OPCODE(ip) @ extract opcode from rINST 9054 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9055 GOTO_OPCODE(ip) @ jump to next instruction 9056 9057/* continuation for OP_IGET_VOLATILE */ 9058 9059 /* 9060 * Currently: 9061 * r0 holds resolved field 9062 * r9 holds object 9063 */ 9064.LOP_IGET_VOLATILE_finish: 9065 @bl common_squeak0 9066 cmp r9, #0 @ check object for null 9067 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9068 beq common_errNullObject @ object was null 9069 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9070 SMP_DMB @ acquiring load 9071 mov r2, rINST, lsr #8 @ r2<- A+ 9072 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9073 and r2, r2, #15 @ r2<- A 9074 GET_INST_OPCODE(ip) @ extract opcode from rINST 9075 SET_VREG(r0, r2) @ fp[A]<- r0 9076 GOTO_OPCODE(ip) @ jump to next instruction 9077 9078/* continuation for OP_IPUT_VOLATILE */ 9079 9080 /* 9081 * Currently: 9082 * r0 holds resolved field 9083 * r9 holds object 9084 */ 9085.LOP_IPUT_VOLATILE_finish: 9086 @bl common_squeak0 9087 mov r1, rINST, lsr #8 @ r1<- A+ 9088 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9089 and r1, r1, #15 @ r1<- A 9090 cmp r9, #0 @ check object for null 9091 GET_VREG(r0, r1) @ r0<- fp[A] 9092 beq common_errNullObject @ object was null 9093 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9094 GET_INST_OPCODE(ip) @ extract opcode from rINST 9095 SMP_DMB @ releasing store 9096 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 9097 GOTO_OPCODE(ip) @ jump to next instruction 9098 9099/* continuation for OP_SGET_VOLATILE */ 9100 9101 /* 9102 * Continuation if the field has not yet been resolved. 9103 * r1: BBBB field ref 9104 */ 9105.LOP_SGET_VOLATILE_resolve: 9106 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9107 EXPORT_PC() @ resolve() could throw, so export now 9108 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9109 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9110 cmp r0, #0 @ success? 9111 bne .LOP_SGET_VOLATILE_finish @ yes, finish 9112 b common_exceptionThrown @ no, handle exception 9113 9114/* continuation for OP_SPUT_VOLATILE */ 9115 9116 /* 9117 * Continuation if the field has not yet been resolved. 9118 * r1: BBBB field ref 9119 */ 9120.LOP_SPUT_VOLATILE_resolve: 9121 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9122 EXPORT_PC() @ resolve() could throw, so export now 9123 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9124 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9125 cmp r0, #0 @ success? 9126 bne .LOP_SPUT_VOLATILE_finish @ yes, finish 9127 b common_exceptionThrown @ no, handle exception 9128 9129/* continuation for OP_IGET_OBJECT_VOLATILE */ 9130 9131 /* 9132 * Currently: 9133 * r0 holds resolved field 9134 * r9 holds object 9135 */ 9136.LOP_IGET_OBJECT_VOLATILE_finish: 9137 @bl common_squeak0 9138 cmp r9, #0 @ check object for null 9139 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9140 beq common_errNullObject @ object was null 9141 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9142 SMP_DMB @ acquiring load 9143 mov r2, rINST, lsr #8 @ r2<- A+ 9144 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9145 and r2, r2, #15 @ r2<- A 9146 GET_INST_OPCODE(ip) @ extract opcode from rINST 9147 SET_VREG(r0, r2) @ fp[A]<- r0 9148 GOTO_OPCODE(ip) @ jump to next instruction 9149 9150/* continuation for OP_IGET_WIDE_VOLATILE */ 9151 9152 /* 9153 * Currently: 9154 * r0 holds resolved field 9155 * r9 holds object 9156 */ 9157.LOP_IGET_WIDE_VOLATILE_finish: 9158 cmp r9, #0 @ check object for null 9159 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9160 beq common_errNullObject @ object was null 9161 .if 1 9162 add r0, r9, r3 @ r0<- address of field 9163 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 9164 .else 9165 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 9166 .endif 9167 mov r2, rINST, lsr #8 @ r2<- A+ 9168 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9169 and r2, r2, #15 @ r2<- A 9170 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 9171 GET_INST_OPCODE(ip) @ extract opcode from rINST 9172 stmia r3, {r0-r1} @ fp[A]<- r0/r1 9173 GOTO_OPCODE(ip) @ jump to next instruction 9174 9175/* continuation for OP_IPUT_WIDE_VOLATILE */ 9176 9177 /* 9178 * Currently: 9179 * r0 holds resolved field 9180 * r9 holds object 9181 */ 9182.LOP_IPUT_WIDE_VOLATILE_finish: 9183 mov r2, rINST, lsr #8 @ r2<- A+ 9184 cmp r9, #0 @ check object for null 9185 and r2, r2, #15 @ r2<- A 9186 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9187 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 9188 beq common_errNullObject @ object was null 9189 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9190 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 9191 GET_INST_OPCODE(r10) @ extract opcode from rINST 9192 .if 1 9193 add r2, r9, r3 @ r2<- target address 9194 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 9195 .else 9196 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 9197 .endif 9198 GOTO_OPCODE(r10) @ jump to next instruction 9199 9200/* continuation for OP_SGET_WIDE_VOLATILE */ 9201 9202 /* 9203 * Continuation if the field has not yet been resolved. 9204 * r1: BBBB field ref 9205 * 9206 * Returns StaticField pointer in r0. 9207 */ 9208.LOP_SGET_WIDE_VOLATILE_resolve: 9209 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9210 EXPORT_PC() @ resolve() could throw, so export now 9211 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9212 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9213 cmp r0, #0 @ success? 9214 bne .LOP_SGET_WIDE_VOLATILE_finish @ yes, finish 9215 b common_exceptionThrown @ no, handle exception 9216 9217/* continuation for OP_SPUT_WIDE_VOLATILE */ 9218 9219 /* 9220 * Continuation if the field has not yet been resolved. 9221 * r1: BBBB field ref 9222 * r9: &fp[AA] 9223 * 9224 * Returns StaticField pointer in r2. 9225 */ 9226.LOP_SPUT_WIDE_VOLATILE_resolve: 9227 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9228 EXPORT_PC() @ resolve() could throw, so export now 9229 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9230 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9231 cmp r0, #0 @ success? 9232 mov r2, r0 @ copy to r2 9233 bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish 9234 b common_exceptionThrown @ no, handle exception 9235 9236/* continuation for OP_EXECUTE_INLINE */ 9237 9238 /* 9239 * Extract args, call function. 9240 * r0 = #of args (0-4) 9241 * r10 = call index 9242 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9243 * 9244 * Other ideas: 9245 * - Use a jump table from the main piece to jump directly into the 9246 * AND/LDR pairs. Costs a data load, saves a branch. 9247 * - Have five separate pieces that do the loading, so we can work the 9248 * interleave a little better. Increases code size. 9249 */ 9250.LOP_EXECUTE_INLINE_continue: 9251 rsb r0, r0, #4 @ r0<- 4-r0 9252 FETCH(r9, 2) @ r9<- FEDC 9253 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9254 bl common_abort @ (skipped due to ARM prefetch) 92554: and ip, r9, #0xf000 @ isolate F 9256 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 92573: and ip, r9, #0x0f00 @ isolate E 9258 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 92592: and ip, r9, #0x00f0 @ isolate D 9260 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 92611: and ip, r9, #0x000f @ isolate C 9262 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 92630: 9264 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 9265 ldr pc, [r9, r10, lsl #4] @ sizeof=16, "func" is first entry 9266 @ (not reached) 9267 9268.LOP_EXECUTE_INLINE_table: 9269 .word gDvmInlineOpsTable 9270 9271/* continuation for OP_EXECUTE_INLINE_RANGE */ 9272 9273 /* 9274 * Extract args, call function. 9275 * r0 = #of args (0-4) 9276 * r10 = call index 9277 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9278 */ 9279.LOP_EXECUTE_INLINE_RANGE_continue: 9280 rsb r0, r0, #4 @ r0<- 4-r0 9281 FETCH(r9, 2) @ r9<- CCCC 9282 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9283 bl common_abort @ (skipped due to ARM prefetch) 92844: add ip, r9, #3 @ base+3 9285 GET_VREG(r3, ip) @ r3<- vBase[3] 92863: add ip, r9, #2 @ base+2 9287 GET_VREG(r2, ip) @ r2<- vBase[2] 92882: add ip, r9, #1 @ base+1 9289 GET_VREG(r1, ip) @ r1<- vBase[1] 92901: add ip, r9, #0 @ (nop) 9291 GET_VREG(r0, ip) @ r0<- vBase[0] 92920: 9293 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation 9294 ldr pc, [r9, r10, lsl #4] @ sizeof=16, "func" is first entry 9295 @ (not reached) 9296 9297.LOP_EXECUTE_INLINE_RANGE_table: 9298 .word gDvmInlineOpsTable 9299 9300/* continuation for OP_IPUT_OBJECT_VOLATILE */ 9301 9302 /* 9303 * Currently: 9304 * r0 holds resolved field 9305 * r9 holds object 9306 */ 9307.LOP_IPUT_OBJECT_VOLATILE_finish: 9308 @bl common_squeak0 9309 mov r1, rINST, lsr #8 @ r1<- A+ 9310 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9311 and r1, r1, #15 @ r1<- A 9312 cmp r9, #0 @ check object for null 9313 GET_VREG(r0, r1) @ r0<- fp[A] 9314 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 9315 beq common_errNullObject @ object was null 9316 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9317 GET_INST_OPCODE(ip) @ extract opcode from rINST 9318 SMP_DMB @ releasing store 9319 str r0, [r9, r3] @ obj.field (32 bits)<- r0 9320 cmp r0, #0 @ stored a null reference? 9321 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 9322 GOTO_OPCODE(ip) @ jump to next instruction 9323 9324/* continuation for OP_SGET_OBJECT_VOLATILE */ 9325 9326 /* 9327 * Continuation if the field has not yet been resolved. 9328 * r1: BBBB field ref 9329 */ 9330.LOP_SGET_OBJECT_VOLATILE_resolve: 9331 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9332 EXPORT_PC() @ resolve() could throw, so export now 9333 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9334 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9335 cmp r0, #0 @ success? 9336 bne .LOP_SGET_OBJECT_VOLATILE_finish @ yes, finish 9337 b common_exceptionThrown @ no, handle exception 9338 9339/* continuation for OP_SPUT_OBJECT_VOLATILE */ 9340.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0 9341 mov r2, rINST, lsr #8 @ r2<- AA 9342 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9343 GET_VREG(r1, r2) @ r1<- fp[AA] 9344 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 9345 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz 9346 GET_INST_OPCODE(ip) @ extract opcode from rINST 9347 SMP_DMB @ releasing store 9348 str r1, [r0, #offStaticField_value] @ field<- vAA 9349 cmp r1, #0 @ stored a null object? 9350 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 9351 GOTO_OPCODE(ip) @ jump to next instruction 9352 9353 .size dvmAsmSisterStart, .-dvmAsmSisterStart 9354 .global dvmAsmSisterEnd 9355dvmAsmSisterEnd: 9356 9357/* File: armv5te/footer.S */ 9358 9359/* 9360 * =========================================================================== 9361 * Common subroutines and data 9362 * =========================================================================== 9363 */ 9364 9365 9366 9367 .text 9368 .align 2 9369 9370#if defined(WITH_JIT) 9371#if defined(WITH_SELF_VERIFICATION) 9372 .global dvmJitToInterpPunt 9373dvmJitToInterpPunt: 9374 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9375 mov r2,#kSVSPunt @ r2<- interpreter entry point 9376 mov r3, #0 9377 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9378 b jitSVShadowRunEnd @ doesn't return 9379 9380 .global dvmJitToInterpSingleStep 9381dvmJitToInterpSingleStep: 9382 str lr,[rGLUE,#offGlue_jitResumeNPC] 9383 str r1,[rGLUE,#offGlue_jitResumeDPC] 9384 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 9385 b jitSVShadowRunEnd @ doesn't return 9386 9387 .global dvmJitToInterpNoChainNoProfile 9388dvmJitToInterpNoChainNoProfile: 9389 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9390 mov r0,rPC @ pass our target PC 9391 mov r2,#kSVSNoProfile @ r2<- interpreter entry point 9392 mov r3, #0 @ 0 means !inJitCodeCache 9393 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land 9394 b jitSVShadowRunEnd @ doesn't return 9395 9396 .global dvmJitToInterpTraceSelectNoChain 9397dvmJitToInterpTraceSelectNoChain: 9398 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9399 mov r0,rPC @ pass our target PC 9400 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9401 mov r3, #0 @ 0 means !inJitCodeCache 9402 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9403 b jitSVShadowRunEnd @ doesn't return 9404 9405 .global dvmJitToInterpTraceSelect 9406dvmJitToInterpTraceSelect: 9407 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9408 ldr r0,[lr, #-1] @ pass our target PC 9409 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9410 mov r3, #0 @ 0 means !inJitCodeCache 9411 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9412 b jitSVShadowRunEnd @ doesn't return 9413 9414 .global dvmJitToInterpBackwardBranch 9415dvmJitToInterpBackwardBranch: 9416 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9417 ldr r0,[lr, #-1] @ pass our target PC 9418 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 9419 mov r3, #0 @ 0 means !inJitCodeCache 9420 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9421 b jitSVShadowRunEnd @ doesn't return 9422 9423 .global dvmJitToInterpNormal 9424dvmJitToInterpNormal: 9425 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9426 ldr r0,[lr, #-1] @ pass our target PC 9427 mov r2,#kSVSNormal @ r2<- interpreter entry point 9428 mov r3, #0 @ 0 means !inJitCodeCache 9429 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9430 b jitSVShadowRunEnd @ doesn't return 9431 9432 .global dvmJitToInterpNoChain 9433dvmJitToInterpNoChain: 9434 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9435 mov r0,rPC @ pass our target PC 9436 mov r2,#kSVSNoChain @ r2<- interpreter entry point 9437 mov r3, #0 @ 0 means !inJitCodeCache 9438 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9439 b jitSVShadowRunEnd @ doesn't return 9440#else 9441/* 9442 * Return from the translation cache to the interpreter when the compiler is 9443 * having issues translating/executing a Dalvik instruction. We have to skip 9444 * the code cache lookup otherwise it is possible to indefinitely bouce 9445 * between the interpreter and the code cache if the instruction that fails 9446 * to be compiled happens to be at a trace start. 9447 */ 9448 .global dvmJitToInterpPunt 9449dvmJitToInterpPunt: 9450 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9451 mov rPC, r0 9452#if defined(WITH_JIT_TUNING) 9453 mov r0,lr 9454 bl dvmBumpPunt; 9455#endif 9456 EXPORT_PC() 9457 mov r0, #0 9458 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9459 adrl rIBASE, dvmAsmInstructionStart 9460 FETCH_INST() 9461 GET_INST_OPCODE(ip) 9462 GOTO_OPCODE(ip) 9463 9464/* 9465 * Return to the interpreter to handle a single instruction. 9466 * On entry: 9467 * r0 <= PC 9468 * r1 <= PC of resume instruction 9469 * lr <= resume point in translation 9470 */ 9471 .global dvmJitToInterpSingleStep 9472dvmJitToInterpSingleStep: 9473 str lr,[rGLUE,#offGlue_jitResumeNPC] 9474 str r1,[rGLUE,#offGlue_jitResumeDPC] 9475 mov r1,#kInterpEntryInstr 9476 @ enum is 4 byte in aapcs-EABI 9477 str r1, [rGLUE, #offGlue_entryPoint] 9478 mov rPC,r0 9479 EXPORT_PC() 9480 9481 adrl rIBASE, dvmAsmInstructionStart 9482 mov r2,#kJitSingleStep @ Ask for single step and then revert 9483 str r2,[rGLUE,#offGlue_jitState] 9484 mov r1,#1 @ set changeInterp to bail to debug interp 9485 b common_gotoBail 9486 9487/* 9488 * Return from the translation cache and immediately request 9489 * a translation for the exit target. Commonly used for callees. 9490 */ 9491 .global dvmJitToInterpTraceSelectNoChain 9492dvmJitToInterpTraceSelectNoChain: 9493#if defined(WITH_JIT_TUNING) 9494 bl dvmBumpNoChain 9495#endif 9496 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9497 mov r0,rPC 9498 bl dvmJitGetCodeAddr @ Is there a translation? 9499 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9500 mov r1, rPC @ arg1 of translation may need this 9501 mov lr, #0 @ in case target is HANDLER_INTERPRET 9502 cmp r0,#0 @ !0 means translation exists 9503 bxne r0 @ continue native execution if so 9504 b 2f @ branch over to use the interpreter 9505 9506/* 9507 * Return from the translation cache and immediately request 9508 * a translation for the exit target. Commonly used following 9509 * invokes. 9510 */ 9511 .global dvmJitToInterpTraceSelect 9512dvmJitToInterpTraceSelect: 9513 ldr rPC,[lr, #-1] @ get our target PC 9514 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9515 add rINST,lr,#-5 @ save start of chain branch 9516 add rINST, #-4 @ .. which is 9 bytes back 9517 mov r0,rPC 9518 bl dvmJitGetCodeAddr @ Is there a translation? 9519 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9520 cmp r0,#0 9521 beq 2f 9522 mov r1,rINST 9523 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9524 mov r1, rPC @ arg1 of translation may need this 9525 mov lr, #0 @ in case target is HANDLER_INTERPRET 9526 cmp r0,#0 @ successful chain? 9527 bxne r0 @ continue native execution 9528 b toInterpreter @ didn't chain - resume with interpreter 9529 9530/* No translation, so request one if profiling isn't disabled*/ 95312: 9532 adrl rIBASE, dvmAsmInstructionStart 9533 GET_JIT_PROF_TABLE(r0) 9534 FETCH_INST() 9535 cmp r0, #0 9536 movne r2,#kJitTSelectRequestHot @ ask for trace selection 9537 bne common_selectTrace 9538 GET_INST_OPCODE(ip) 9539 GOTO_OPCODE(ip) 9540 9541/* 9542 * Return from the translation cache to the interpreter. 9543 * The return was done with a BLX from thumb mode, and 9544 * the following 32-bit word contains the target rPC value. 9545 * Note that lr (r14) will have its low-order bit set to denote 9546 * its thumb-mode origin. 9547 * 9548 * We'll need to stash our lr origin away, recover the new 9549 * target and then check to see if there is a translation available 9550 * for our new target. If so, we do a translation chain and 9551 * go back to native execution. Otherwise, it's back to the 9552 * interpreter (after treating this entry as a potential 9553 * trace start). 9554 */ 9555 .global dvmJitToInterpNormal 9556dvmJitToInterpNormal: 9557 ldr rPC,[lr, #-1] @ get our target PC 9558 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9559 add rINST,lr,#-5 @ save start of chain branch 9560 add rINST,#-4 @ .. which is 9 bytes back 9561#if defined(WITH_JIT_TUNING) 9562 bl dvmBumpNormal 9563#endif 9564 mov r0,rPC 9565 bl dvmJitGetCodeAddr @ Is there a translation? 9566 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9567 cmp r0,#0 9568 beq toInterpreter @ go if not, otherwise do chain 9569 mov r1,rINST 9570 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9571 mov r1, rPC @ arg1 of translation may need this 9572 mov lr, #0 @ in case target is HANDLER_INTERPRET 9573 cmp r0,#0 @ successful chain? 9574 bxne r0 @ continue native execution 9575 b toInterpreter @ didn't chain - resume with interpreter 9576 9577/* 9578 * Return from the translation cache to the interpreter to do method invocation. 9579 * Check if translation exists for the callee, but don't chain to it. 9580 */ 9581 .global dvmJitToInterpNoChainNoProfile 9582dvmJitToInterpNoChainNoProfile: 9583#if defined(WITH_JIT_TUNING) 9584 bl dvmBumpNoChain 9585#endif 9586 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9587 mov r0,rPC 9588 bl dvmJitGetCodeAddr @ Is there a translation? 9589 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9590 mov r1, rPC @ arg1 of translation may need this 9591 mov lr, #0 @ in case target is HANDLER_INTERPRET 9592 cmp r0,#0 9593 bxne r0 @ continue native execution if so 9594 EXPORT_PC() 9595 adrl rIBASE, dvmAsmInstructionStart 9596 FETCH_INST() 9597 GET_INST_OPCODE(ip) @ extract opcode from rINST 9598 GOTO_OPCODE(ip) @ jump to next instruction 9599 9600/* 9601 * Return from the translation cache to the interpreter to do method invocation. 9602 * Check if translation exists for the callee, but don't chain to it. 9603 */ 9604 .global dvmJitToInterpNoChain 9605dvmJitToInterpNoChain: 9606#if defined(WITH_JIT_TUNING) 9607 bl dvmBumpNoChain 9608#endif 9609 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9610 mov r0,rPC 9611 bl dvmJitGetCodeAddr @ Is there a translation? 9612 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9613 mov r1, rPC @ arg1 of translation may need this 9614 mov lr, #0 @ in case target is HANDLER_INTERPRET 9615 cmp r0,#0 9616 bxne r0 @ continue native execution if so 9617#endif 9618 9619/* 9620 * No translation, restore interpreter regs and start interpreting. 9621 * rGLUE & rFP were preserved in the translated code, and rPC has 9622 * already been restored by the time we get here. We'll need to set 9623 * up rIBASE & rINST, and load the address of the JitTable into r0. 9624 */ 9625toInterpreter: 9626 EXPORT_PC() 9627 adrl rIBASE, dvmAsmInstructionStart 9628 FETCH_INST() 9629 GET_JIT_PROF_TABLE(r0) 9630 @ NOTE: intended fallthrough 9631 9632/* 9633 * Common code to update potential trace start counter, and initiate 9634 * a trace-build if appropriate. On entry, rPC should point to the 9635 * next instruction to execute, and rINST should be already loaded with 9636 * the next opcode word, and r0 holds a pointer to the jit profile 9637 * table (pJitProfTable). 9638 */ 9639common_testUpdateProfile: 9640 cmp r0,#0 9641 GET_INST_OPCODE(ip) 9642 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 9643 9644common_updateProfile: 9645 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 9646 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits 9647 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter 9648 GET_INST_OPCODE(ip) 9649 subs r1,r1,#1 @ decrement counter 9650 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it 9651 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 9652 9653/* 9654 * Here, we switch to the debug interpreter to request 9655 * trace selection. First, though, check to see if there 9656 * is already a native translation in place (and, if so, 9657 * jump to it now). 9658 */ 9659 GET_JIT_THRESHOLD(r1) 9660 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9661 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter 9662 EXPORT_PC() 9663 mov r0,rPC 9664 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC) 9665 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9666 mov r1, rPC @ arg1 of translation may need this 9667 mov lr, #0 @ in case target is HANDLER_INTERPRET 9668 cmp r0,#0 9669#if !defined(WITH_SELF_VERIFICATION) 9670 bxne r0 @ jump to the translation 9671 mov r2,#kJitTSelectRequest @ ask for trace selection 9672 @ fall-through to common_selectTrace 9673#else 9674 moveq r2,#kJitTSelectRequest @ ask for trace selection 9675 beq common_selectTrace 9676 /* 9677 * At this point, we have a target translation. However, if 9678 * that translation is actually the interpret-only pseudo-translation 9679 * we want to treat it the same as no translation. 9680 */ 9681 mov r10, r0 @ save target 9682 bl dvmCompilerGetInterpretTemplate 9683 cmp r0, r10 @ special case? 9684 bne jitSVShadowRunStart @ set up self verification shadow space 9685 @ Need to clear the inJitCodeCache flag 9686 ldr r10, [rGLUE, #offGlue_self] @ r10 <- glue->self 9687 mov r3, #0 @ 0 means not in the JIT code cache 9688 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land 9689 GET_INST_OPCODE(ip) 9690 GOTO_OPCODE(ip) 9691 /* no return */ 9692#endif 9693 9694/* 9695 * On entry: 9696 * r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot 9697 */ 9698common_selectTrace: 9699 str r2,[rGLUE,#offGlue_jitState] 9700 mov r2,#kInterpEntryInstr @ normal entry reason 9701 str r2,[rGLUE,#offGlue_entryPoint] 9702 mov r1,#1 @ set changeInterp 9703 b common_gotoBail 9704 9705#if defined(WITH_SELF_VERIFICATION) 9706/* 9707 * Save PC and registers to shadow memory for self verification mode 9708 * before jumping to native translation. 9709 * On entry: 9710 * rPC, rFP, rGLUE: the values that they should contain 9711 * r10: the address of the target translation. 9712 */ 9713jitSVShadowRunStart: 9714 mov r0,rPC @ r0<- program counter 9715 mov r1,rFP @ r1<- frame pointer 9716 mov r2,rGLUE @ r2<- InterpState pointer 9717 mov r3,r10 @ r3<- target translation 9718 bl dvmSelfVerificationSaveState @ save registers to shadow space 9719 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 9720 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 9721 bx r10 @ jump to the translation 9722 9723/* 9724 * Restore PC, registers, and interpState to original values 9725 * before jumping back to the interpreter. 9726 */ 9727jitSVShadowRunEnd: 9728 mov r1,rFP @ pass ending fp 9729 bl dvmSelfVerificationRestoreState @ restore pc and fp values 9730 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 9731 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 9732 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 9733 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 9734 cmp r1,#0 @ check for punt condition 9735 beq 1f 9736 mov r2,#kJitSelfVerification @ ask for self verification 9737 str r2,[rGLUE,#offGlue_jitState] 9738 mov r2,#kInterpEntryInstr @ normal entry reason 9739 str r2,[rGLUE,#offGlue_entryPoint] 9740 mov r1,#1 @ set changeInterp 9741 b common_gotoBail 9742 97431: @ exit to interpreter without check 9744 EXPORT_PC() 9745 adrl rIBASE, dvmAsmInstructionStart 9746 FETCH_INST() 9747 GET_INST_OPCODE(ip) 9748 GOTO_OPCODE(ip) 9749#endif 9750 9751#endif 9752 9753/* 9754 * Common code when a backward branch is taken. 9755 * 9756 * TODO: we could avoid a branch by just setting r0 and falling through 9757 * into the common_periodicChecks code, and having a test on r0 at the 9758 * end determine if we should return to the caller or update & branch to 9759 * the next instr. 9760 * 9761 * On entry: 9762 * r9 is PC adjustment *in bytes* 9763 */ 9764common_backwardBranch: 9765 mov r0, #kInterpEntryInstr 9766 bl common_periodicChecks 9767#if defined(WITH_JIT) 9768 GET_JIT_PROF_TABLE(r0) 9769 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9770 cmp r0,#0 9771 bne common_updateProfile 9772 GET_INST_OPCODE(ip) 9773 GOTO_OPCODE(ip) 9774#else 9775 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9776 GET_INST_OPCODE(ip) @ extract opcode from rINST 9777 GOTO_OPCODE(ip) @ jump to next instruction 9778#endif 9779 9780 9781/* 9782 * Need to see if the thread needs to be suspended or debugger/profiler 9783 * activity has begun. If so, we suspend the thread or side-exit to 9784 * the debug interpreter as appropriate. 9785 * 9786 * The common case is no activity on any of these, so we want to figure 9787 * that out quickly. If something is up, we can then sort out what. 9788 * 9789 * We want to be fast if the VM was built without debugger or profiler 9790 * support, but we also need to recognize that the system is usually 9791 * shipped with both of these enabled. 9792 * 9793 * TODO: reduce this so we're just checking a single location. 9794 * 9795 * On entry: 9796 * r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling) 9797 * r9 is trampoline PC adjustment *in bytes* 9798 */ 9799common_periodicChecks: 9800 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9801 9802 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9803 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9804 9805 ldr ip, [r3] @ ip<- suspendCount (int) 9806 9807 cmp r1, #0 @ debugger enabled? 9808 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9809 ldr r2, [r2] @ r2<- activeProfilers (int) 9810 orrnes ip, ip, r1 @ ip<- suspendCount | debuggerActive 9811 /* 9812 * Don't switch the interpreter in the libdvm_traceview build even if the 9813 * profiler is active. 9814 * The code here is opted for less intrusion instead of performance. 9815 * That is, *pActiveProfilers is still loaded into r2 even though it is not 9816 * used when WITH_INLINE_PROFILING is defined. 9817 */ 9818#if !defined(WITH_INLINE_PROFILING) 9819 orrs ip, ip, r2 @ ip<- suspend|debugger|profiler; set Z 9820#endif 9821 9822 9823 bxeq lr @ all zero, return 9824 9825 /* 9826 * One or more interesting events have happened. Figure out what. 9827 * 9828 * If debugging or profiling are compiled in, we need to disambiguate. 9829 * 9830 * r0 still holds the reentry type. 9831 */ 9832 ldr ip, [r3] @ ip<- suspendCount (int) 9833 cmp ip, #0 @ want suspend? 9834 beq 1f @ no, must be debugger/profiler 9835 9836 stmfd sp!, {r0, lr} @ preserve r0 and lr 9837#if defined(WITH_JIT) 9838 /* 9839 * Refresh the Jit's cached copy of profile table pointer. This pointer 9840 * doubles as the Jit's on/off switch. 9841 */ 9842 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable 9843 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9844 ldr r3, [r3] @ r3 <- pJitProfTable 9845 EXPORT_PC() @ need for precise GC 9846 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch 9847#else 9848 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9849 EXPORT_PC() @ need for precise GC 9850#endif 9851 bl dvmCheckSuspendPending @ do full check, suspend if necessary 9852 ldmfd sp!, {r0, lr} @ restore r0 and lr 9853 9854 /* 9855 * Reload the debugger/profiler enable flags. We're checking to see 9856 * if either of these got set while we were suspended. 9857 * 9858 * If WITH_INLINE_PROFILING is configured, don't check whether the profiler 9859 * is enabled or not as the profiling will be done inline. 9860 */ 9861 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9862 cmp r1, #0 @ debugger enabled? 9863 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9864 9865#if !defined(WITH_INLINE_PROFILING) 9866 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9867 ldr r2, [r2] @ r2<- activeProfilers (int) 9868 orrs r1, r1, r2 9869#else 9870 cmp r1, #0 @ only consult the debuggerActive flag 9871#endif 9872 9873 beq 2f 9874 98751: @ debugger/profiler enabled, bail out; glue->entryPoint was set above 9876 str r0, [rGLUE, #offGlue_entryPoint] @ store r0, need for debug/prof 9877 add rPC, rPC, r9 @ update rPC 9878 mov r1, #1 @ "want switch" = true 9879 b common_gotoBail @ side exit 9880 98812: 9882 bx lr @ nothing to do, return 9883 9884 9885/* 9886 * The equivalent of "goto bail", this calls through the "bail handler". 9887 * 9888 * State registers will be saved to the "glue" area before bailing. 9889 * 9890 * On entry: 9891 * r1 is "bool changeInterp", indicating if we want to switch to the 9892 * other interpreter or just bail all the way out 9893 */ 9894common_gotoBail: 9895 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9896 mov r0, rGLUE @ r0<- glue ptr 9897 b dvmMterpStdBail @ call(glue, changeInterp) 9898 9899 @add r1, r1, #1 @ using (boolean+1) 9900 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9901 @bl _longjmp @ does not return 9902 @bl common_abort 9903 9904 9905/* 9906 * Common code for method invocation with range. 9907 * 9908 * On entry: 9909 * r0 is "Method* methodToCall", the method we're trying to call 9910 */ 9911common_invokeMethodRange: 9912.LinvokeNewRange: 9913 @ prepare to copy args to "outs" area of current frame 9914 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9915 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9916 beq .LinvokeArgsDone @ if no args, skip the rest 9917 FETCH(r1, 2) @ r1<- CCCC 9918 9919 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9920 @ (very few methods have > 10 args; could unroll for common cases) 9921 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9922 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9923 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 99241: ldr r1, [r3], #4 @ val = *fp++ 9925 subs r2, r2, #1 @ count-- 9926 str r1, [r10], #4 @ *outs++ = val 9927 bne 1b @ ...while count != 0 9928 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9929 b .LinvokeArgsDone 9930 9931/* 9932 * Common code for method invocation without range. 9933 * 9934 * On entry: 9935 * r0 is "Method* methodToCall", the method we're trying to call 9936 */ 9937common_invokeMethodNoRange: 9938.LinvokeNewNoRange: 9939 @ prepare to copy args to "outs" area of current frame 9940 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9941 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9942 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9943 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9944 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9945 beq .LinvokeArgsDone 9946 9947 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9948.LinvokeNonRange: 9949 rsb r2, r2, #5 @ r2<- 5-r2 9950 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9951 bl common_abort @ (skipped due to ARM prefetch) 99525: and ip, rINST, #0x0f00 @ isolate A 9953 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 9954 mov r0, r0 @ nop 9955 str r2, [r10, #-4]! @ *--outs = vA 99564: and ip, r1, #0xf000 @ isolate G 9957 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 9958 mov r0, r0 @ nop 9959 str r2, [r10, #-4]! @ *--outs = vG 99603: and ip, r1, #0x0f00 @ isolate F 9961 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 9962 mov r0, r0 @ nop 9963 str r2, [r10, #-4]! @ *--outs = vF 99642: and ip, r1, #0x00f0 @ isolate E 9965 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 9966 mov r0, r0 @ nop 9967 str r2, [r10, #-4]! @ *--outs = vE 99681: and ip, r1, #0x000f @ isolate D 9969 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 9970 mov r0, r0 @ nop 9971 str r2, [r10, #-4]! @ *--outs = vD 99720: @ fall through to .LinvokeArgsDone 9973 9974.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 9975 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 9976 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 9977 @ find space for the new stack frame, check for overflow 9978 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 9979 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 9980 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 9981@ bl common_dumpRegs 9982 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 9983 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 9984 cmp r3, r9 @ bottom < interpStackEnd? 9985 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 9986 blo .LstackOverflow @ yes, this frame will overflow stack 9987 9988 @ set up newSaveArea 9989#ifdef EASY_GDB 9990 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 9991 str ip, [r10, #offStackSaveArea_prevSave] 9992#endif 9993 str rFP, [r10, #offStackSaveArea_prevFrame] 9994 str rPC, [r10, #offStackSaveArea_savedPc] 9995#if defined(WITH_JIT) 9996 mov r9, #0 9997 str r9, [r10, #offStackSaveArea_returnAddr] 9998#endif 9999#if defined(WITH_INLINE_PROFILING) 10000 stmfd sp!, {r0-r3} @ preserve r0-r3 10001 mov r1, r6 10002 @ r0=methodToCall, r1=rGlue 10003 bl dvmFastMethodTraceEnter 10004 ldmfd sp!, {r0-r3} @ restore r0-r3 10005#endif 10006 str r0, [r10, #offStackSaveArea_method] 10007 tst r3, #ACC_NATIVE 10008 bne .LinvokeNative 10009 10010 /* 10011 stmfd sp!, {r0-r3} 10012 bl common_printNewline 10013 mov r0, rFP 10014 mov r1, #0 10015 bl dvmDumpFp 10016 ldmfd sp!, {r0-r3} 10017 stmfd sp!, {r0-r3} 10018 mov r0, r1 10019 mov r1, r10 10020 bl dvmDumpFp 10021 bl common_printNewline 10022 ldmfd sp!, {r0-r3} 10023 */ 10024 10025 ldrh r9, [r2] @ r9 <- load INST from new PC 10026 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 10027 mov rPC, r2 @ publish new rPC 10028 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 10029 10030 @ Update "glue" values for the new method 10031 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 10032 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 10033 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 10034#if defined(WITH_JIT) 10035 GET_JIT_PROF_TABLE(r0) 10036 mov rFP, r1 @ fp = newFp 10037 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 10038 mov rINST, r9 @ publish new rINST 10039 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 10040 cmp r0,#0 10041 bne common_updateProfile 10042 GOTO_OPCODE(ip) @ jump to next instruction 10043#else 10044 mov rFP, r1 @ fp = newFp 10045 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 10046 mov rINST, r9 @ publish new rINST 10047 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 10048 GOTO_OPCODE(ip) @ jump to next instruction 10049#endif 10050 10051.LinvokeNative: 10052 @ Prep for the native call 10053 @ r0=methodToCall, r1=newFp, r10=newSaveArea 10054 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10055 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 10056 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 10057 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 10058 mov r9, r3 @ r9<- glue->self (preserve) 10059 10060 mov r2, r0 @ r2<- methodToCall 10061 mov r0, r1 @ r0<- newFp (points to args) 10062 add r1, rGLUE, #offGlue_retval @ r1<- &retval 10063 10064#ifdef ASSIST_DEBUGGER 10065 /* insert fake function header to help gdb find the stack frame */ 10066 b .Lskip 10067 .type dalvik_mterp, %function 10068dalvik_mterp: 10069 .fnstart 10070 MTERP_ENTRY1 10071 MTERP_ENTRY2 10072.Lskip: 10073#endif 10074 10075#if defined(WITH_INLINE_PROFILING) 10076 @ r2=JNIMethod, r6=rGLUE 10077 stmfd sp!, {r2,r6} 10078#endif 10079 10080 mov lr, pc @ set return addr 10081 ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 10082 10083#if defined(WITH_INLINE_PROFILING) 10084 @ r0=JNIMethod, r1=rGLUE 10085 ldmfd sp!, {r0-r1} 10086 bl dvmFastNativeMethodTraceExit 10087#endif 10088 10089#if defined(WITH_JIT) 10090 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status 10091#endif 10092 10093 @ native return; r9=self, r10=newSaveArea 10094 @ equivalent to dvmPopJniLocals 10095 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 10096 ldr r1, [r9, #offThread_exception] @ check for exception 10097#if defined(WITH_JIT) 10098 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable 10099#endif 10100 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 10101 cmp r1, #0 @ null? 10102 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 10103#if defined(WITH_JIT) 10104 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch 10105#endif 10106 bne common_exceptionThrown @ no, handle exception 10107 10108 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 10109 GET_INST_OPCODE(ip) @ extract opcode from rINST 10110 GOTO_OPCODE(ip) @ jump to next instruction 10111 10112.LstackOverflow: @ r0=methodToCall 10113 mov r1, r0 @ r1<- methodToCall 10114 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 10115 bl dvmHandleStackOverflow 10116 b common_exceptionThrown 10117#ifdef ASSIST_DEBUGGER 10118 .fnend 10119#endif 10120 10121 10122 /* 10123 * Common code for method invocation, calling through "glue code". 10124 * 10125 * TODO: now that we have range and non-range invoke handlers, this 10126 * needs to be split into two. Maybe just create entry points 10127 * that set r9 and jump here? 10128 * 10129 * On entry: 10130 * r0 is "Method* methodToCall", the method we're trying to call 10131 * r9 is "bool methodCallRange", indicating if this is a /range variant 10132 */ 10133 .if 0 10134.LinvokeOld: 10135 sub sp, sp, #8 @ space for args + pad 10136 FETCH(ip, 2) @ ip<- FEDC or CCCC 10137 mov r2, r0 @ A2<- methodToCall 10138 mov r0, rGLUE @ A0<- glue 10139 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 10140 mov r1, r9 @ A1<- methodCallRange 10141 mov r3, rINST, lsr #8 @ A3<- AA 10142 str ip, [sp, #0] @ A4<- ip 10143 bl dvmMterp_invokeMethod @ call the C invokeMethod 10144 add sp, sp, #8 @ remove arg area 10145 b common_resumeAfterGlueCall @ continue to next instruction 10146 .endif 10147 10148 10149 10150/* 10151 * Common code for handling a return instruction. 10152 * 10153 * This does not return. 10154 */ 10155common_returnFromMethod: 10156.LreturnNew: 10157 mov r0, #kInterpEntryReturn 10158 mov r9, #0 10159 bl common_periodicChecks 10160 10161#if defined(WITH_INLINE_PROFILING) 10162 stmfd sp!, {r0-r3} @ preserve r0-r3 10163 mov r0, r6 10164 @ r0=rGlue 10165 bl dvmFastJavaMethodTraceExit 10166 ldmfd sp!, {r0-r3} @ restore r0-r3 10167#endif 10168 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 10169 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 10170 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 10171 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 10172 @ r2<- method we're returning to 10173 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10174 cmp r2, #0 @ is this a break frame? 10175 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 10176 mov r1, #0 @ "want switch" = false 10177 beq common_gotoBail @ break frame, bail out completely 10178 10179 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 10180 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 10181 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 10182 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 10183#if defined(WITH_JIT) 10184 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr 10185 mov rPC, r9 @ publish new rPC 10186 str r1, [rGLUE, #offGlue_methodClassDex] 10187 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land 10188 cmp r10, #0 @ caller is compiled code 10189 blxne r10 10190 GET_INST_OPCODE(ip) @ extract opcode from rINST 10191 GOTO_OPCODE(ip) @ jump to next instruction 10192#else 10193 GET_INST_OPCODE(ip) @ extract opcode from rINST 10194 mov rPC, r9 @ publish new rPC 10195 str r1, [rGLUE, #offGlue_methodClassDex] 10196 GOTO_OPCODE(ip) @ jump to next instruction 10197#endif 10198 10199 /* 10200 * Return handling, calls through "glue code". 10201 */ 10202 .if 0 10203.LreturnOld: 10204 SAVE_PC_FP_TO_GLUE() @ export state 10205 mov r0, rGLUE @ arg to function 10206 bl dvmMterp_returnFromMethod 10207 b common_resumeAfterGlueCall 10208 .endif 10209 10210 10211/* 10212 * Somebody has thrown an exception. Handle it. 10213 * 10214 * If the exception processing code returns to us (instead of falling 10215 * out of the interpreter), continue with whatever the next instruction 10216 * now happens to be. 10217 * 10218 * This does not return. 10219 */ 10220 .global dvmMterpCommonExceptionThrown 10221dvmMterpCommonExceptionThrown: 10222common_exceptionThrown: 10223.LexceptionNew: 10224 mov r0, #kInterpEntryThrow 10225 mov r9, #0 10226 bl common_periodicChecks 10227 10228 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 10229 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 10230 mov r1, r10 @ r1<- self 10231 mov r0, r9 @ r0<- exception 10232 bl dvmAddTrackedAlloc @ don't let the exception be GCed 10233 mov r3, #0 @ r3<- NULL 10234 str r3, [r10, #offThread_exception] @ self->exception = NULL 10235 10236 /* set up args and a local for "&fp" */ 10237 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 10238 str rFP, [sp, #-4]! @ *--sp = fp 10239 mov ip, sp @ ip<- &fp 10240 mov r3, #0 @ r3<- false 10241 str ip, [sp, #-4]! @ *--sp = &fp 10242 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 10243 mov r0, r10 @ r0<- self 10244 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 10245 mov r2, r9 @ r2<- exception 10246 sub r1, rPC, r1 @ r1<- pc - method->insns 10247 mov r1, r1, asr #1 @ r1<- offset in code units 10248 10249 /* call, r0 gets catchRelPc (a code-unit offset) */ 10250 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 10251 10252 /* fix earlier stack overflow if necessary; may trash rFP */ 10253 ldrb r1, [r10, #offThread_stackOverflowed] 10254 cmp r1, #0 @ did we overflow earlier? 10255 beq 1f @ no, skip ahead 10256 mov rFP, r0 @ save relPc result in rFP 10257 mov r0, r10 @ r0<- self 10258 mov r1, r9 @ r1<- exception 10259 bl dvmCleanupStackOverflow @ call(self) 10260 mov r0, rFP @ restore result 102611: 10262 10263 /* update frame pointer and check result from dvmFindCatchBlock */ 10264 ldr rFP, [sp, #4] @ retrieve the updated rFP 10265 cmp r0, #0 @ is catchRelPc < 0? 10266 add sp, sp, #8 @ restore stack 10267 bmi .LnotCaughtLocally 10268 10269 /* adjust locals to match self->curFrame and updated PC */ 10270 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 10271 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 10272 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 10273 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 10274 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 10275 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 10276 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 10277 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 10278 10279 /* release the tracked alloc on the exception */ 10280 mov r0, r9 @ r0<- exception 10281 mov r1, r10 @ r1<- self 10282 bl dvmReleaseTrackedAlloc @ release the exception 10283 10284 /* restore the exception if the handler wants it */ 10285 FETCH_INST() @ load rINST from rPC 10286 GET_INST_OPCODE(ip) @ extract opcode from rINST 10287 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 10288 streq r9, [r10, #offThread_exception] @ yes, restore the exception 10289 GOTO_OPCODE(ip) @ jump to next instruction 10290 10291.LnotCaughtLocally: @ r9=exception, r10=self 10292 /* fix stack overflow if necessary */ 10293 ldrb r1, [r10, #offThread_stackOverflowed] 10294 cmp r1, #0 @ did we overflow earlier? 10295 movne r0, r10 @ if yes: r0<- self 10296 movne r1, r9 @ if yes: r1<- exception 10297 blne dvmCleanupStackOverflow @ if yes: call(self) 10298 10299 @ may want to show "not caught locally" debug messages here 10300#if DVM_SHOW_EXCEPTION >= 2 10301 /* call __android_log_print(prio, tag, format, ...) */ 10302 /* "Exception %s from %s:%d not caught locally" */ 10303 @ dvmLineNumFromPC(method, pc - method->insns) 10304 ldr r0, [rGLUE, #offGlue_method] 10305 ldr r1, [r0, #offMethod_insns] 10306 sub r1, rPC, r1 10307 asr r1, r1, #1 10308 bl dvmLineNumFromPC 10309 str r0, [sp, #-4]! 10310 @ dvmGetMethodSourceFile(method) 10311 ldr r0, [rGLUE, #offGlue_method] 10312 bl dvmGetMethodSourceFile 10313 str r0, [sp, #-4]! 10314 @ exception->clazz->descriptor 10315 ldr r3, [r9, #offObject_clazz] 10316 ldr r3, [r3, #offClassObject_descriptor] 10317 @ 10318 ldr r2, strExceptionNotCaughtLocally 10319 ldr r1, strLogTag 10320 mov r0, #3 @ LOG_DEBUG 10321 bl __android_log_print 10322#endif 10323 str r9, [r10, #offThread_exception] @ restore exception 10324 mov r0, r9 @ r0<- exception 10325 mov r1, r10 @ r1<- self 10326 bl dvmReleaseTrackedAlloc @ release the exception 10327 mov r1, #0 @ "want switch" = false 10328 b common_gotoBail @ bail out 10329 10330 10331 /* 10332 * Exception handling, calls through "glue code". 10333 */ 10334 .if 0 10335.LexceptionOld: 10336 SAVE_PC_FP_TO_GLUE() @ export state 10337 mov r0, rGLUE @ arg to function 10338 bl dvmMterp_exceptionThrown 10339 b common_resumeAfterGlueCall 10340 .endif 10341 10342 10343/* 10344 * After returning from a "glued" function, pull out the updated 10345 * values and start executing at the next instruction. 10346 */ 10347common_resumeAfterGlueCall: 10348 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 10349 FETCH_INST() @ load rINST from rPC 10350 GET_INST_OPCODE(ip) @ extract opcode from rINST 10351 GOTO_OPCODE(ip) @ jump to next instruction 10352 10353/* 10354 * Invalid array index. Note that our calling convention is strange; we use r1 10355 * and r3 because those just happen to be the registers all our callers are 10356 * using. We shuffle them here before calling the C function. 10357 * r1: index 10358 * r3: size 10359 */ 10360common_errArrayIndex: 10361 EXPORT_PC() 10362 mov r0, r1 10363 mov r1, r3 10364 bl dvmThrowAIOOBE 10365 b common_exceptionThrown 10366 10367/* 10368 * Invalid array value. 10369 */ 10370common_errArrayStore: 10371 EXPORT_PC() 10372 ldr r0, strArrayStoreException 10373 mov r1, #0 10374 bl dvmThrowException 10375 b common_exceptionThrown 10376 10377/* 10378 * Integer divide or mod by zero. 10379 */ 10380common_errDivideByZero: 10381 EXPORT_PC() 10382 ldr r0, strArithmeticException 10383 ldr r1, strDivideByZero 10384 bl dvmThrowException 10385 b common_exceptionThrown 10386 10387/* 10388 * Attempt to allocate an array with a negative size. 10389 */ 10390common_errNegativeArraySize: 10391 EXPORT_PC() 10392 ldr r0, strNegativeArraySizeException 10393 mov r1, #0 10394 bl dvmThrowException 10395 b common_exceptionThrown 10396 10397/* 10398 * Invocation of a non-existent method. 10399 */ 10400common_errNoSuchMethod: 10401 EXPORT_PC() 10402 ldr r0, strNoSuchMethodError 10403 mov r1, #0 10404 bl dvmThrowException 10405 b common_exceptionThrown 10406 10407/* 10408 * We encountered a null object when we weren't expecting one. We 10409 * export the PC, throw a NullPointerException, and goto the exception 10410 * processing code. 10411 */ 10412common_errNullObject: 10413 EXPORT_PC() 10414 ldr r0, strNullPointerException 10415 mov r1, #0 10416 bl dvmThrowException 10417 b common_exceptionThrown 10418 10419/* 10420 * For debugging, cause an immediate fault. The source address will 10421 * be in lr (use a bl instruction to jump here). 10422 */ 10423common_abort: 10424 ldr pc, .LdeadFood 10425.LdeadFood: 10426 .word 0xdeadf00d 10427 10428/* 10429 * Spit out a "we were here", preserving all registers. (The attempt 10430 * to save ip won't work, but we need to save an even number of 10431 * registers for EABI 64-bit stack alignment.) 10432 */ 10433 .macro SQUEAK num 10434common_squeak\num: 10435 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10436 ldr r0, strSqueak 10437 mov r1, #\num 10438 bl printf 10439 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10440 bx lr 10441 .endm 10442 10443 SQUEAK 0 10444 SQUEAK 1 10445 SQUEAK 2 10446 SQUEAK 3 10447 SQUEAK 4 10448 SQUEAK 5 10449 10450/* 10451 * Spit out the number in r0, preserving registers. 10452 */ 10453common_printNum: 10454 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10455 mov r1, r0 10456 ldr r0, strSqueak 10457 bl printf 10458 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10459 bx lr 10460 10461/* 10462 * Print a newline, preserving registers. 10463 */ 10464common_printNewline: 10465 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10466 ldr r0, strNewline 10467 bl printf 10468 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10469 bx lr 10470 10471 /* 10472 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 10473 */ 10474common_printHex: 10475 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10476 mov r1, r0 10477 ldr r0, strPrintHex 10478 bl printf 10479 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10480 bx lr 10481 10482/* 10483 * Print the 64-bit quantity in r0-r1, preserving registers. 10484 */ 10485common_printLong: 10486 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10487 mov r3, r1 10488 mov r2, r0 10489 ldr r0, strPrintLong 10490 bl printf 10491 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10492 bx lr 10493 10494/* 10495 * Print full method info. Pass the Method* in r0. Preserves regs. 10496 */ 10497common_printMethod: 10498 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10499 bl dvmMterpPrintMethod 10500 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10501 bx lr 10502 10503/* 10504 * Call a C helper function that dumps regs and possibly some 10505 * additional info. Requires the C function to be compiled in. 10506 */ 10507 .if 0 10508common_dumpRegs: 10509 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10510 bl dvmMterpDumpArmRegs 10511 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10512 bx lr 10513 .endif 10514 10515#if 0 10516/* 10517 * Experiment on VFP mode. 10518 * 10519 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 10520 * 10521 * Updates the bits specified by "mask", setting them to the values in "val". 10522 */ 10523setFPSCR: 10524 and r0, r0, r1 @ make sure no stray bits are set 10525 fmrx r2, fpscr @ get VFP reg 10526 mvn r1, r1 @ bit-invert mask 10527 and r2, r2, r1 @ clear masked bits 10528 orr r2, r2, r0 @ set specified bits 10529 fmxr fpscr, r2 @ set VFP reg 10530 mov r0, r2 @ return new value 10531 bx lr 10532 10533 .align 2 10534 .global dvmConfigureFP 10535 .type dvmConfigureFP, %function 10536dvmConfigureFP: 10537 stmfd sp!, {ip, lr} 10538 /* 0x03000000 sets DN/FZ */ 10539 /* 0x00009f00 clears the six exception enable flags */ 10540 bl common_squeak0 10541 mov r0, #0x03000000 @ r0<- 0x03000000 10542 add r1, r0, #0x9f00 @ r1<- 0x03009f00 10543 bl setFPSCR 10544 ldmfd sp!, {ip, pc} 10545#endif 10546 10547 10548/* 10549 * String references, must be close to the code that uses them. 10550 */ 10551 .align 2 10552strArithmeticException: 10553 .word .LstrArithmeticException 10554strArrayStoreException: 10555 .word .LstrArrayStoreException 10556strDivideByZero: 10557 .word .LstrDivideByZero 10558strNegativeArraySizeException: 10559 .word .LstrNegativeArraySizeException 10560strNoSuchMethodError: 10561 .word .LstrNoSuchMethodError 10562strNullPointerException: 10563 .word .LstrNullPointerException 10564 10565strLogTag: 10566 .word .LstrLogTag 10567strExceptionNotCaughtLocally: 10568 .word .LstrExceptionNotCaughtLocally 10569 10570strNewline: 10571 .word .LstrNewline 10572strSqueak: 10573 .word .LstrSqueak 10574strPrintHex: 10575 .word .LstrPrintHex 10576strPrintLong: 10577 .word .LstrPrintLong 10578 10579/* 10580 * Zero-terminated ASCII string data. 10581 * 10582 * On ARM we have two choices: do like gcc does, and LDR from a .word 10583 * with the address, or use an ADR pseudo-op to get the address 10584 * directly. ADR saves 4 bytes and an indirection, but it's using a 10585 * PC-relative addressing mode and hence has a limited range, which 10586 * makes it not work well with mergeable string sections. 10587 */ 10588 .section .rodata.str1.4,"aMS",%progbits,1 10589 10590.LstrBadEntryPoint: 10591 .asciz "Bad entry point %d\n" 10592.LstrArithmeticException: 10593 .asciz "Ljava/lang/ArithmeticException;" 10594.LstrArrayStoreException: 10595 .asciz "Ljava/lang/ArrayStoreException;" 10596.LstrClassCastException: 10597 .asciz "Ljava/lang/ClassCastException;" 10598.LstrDivideByZero: 10599 .asciz "divide by zero" 10600.LstrFilledNewArrayNotImpl: 10601 .asciz "filled-new-array only implemented for objects and 'int'" 10602.LstrInternalError: 10603 .asciz "Ljava/lang/InternalError;" 10604.LstrInstantiationError: 10605 .asciz "Ljava/lang/InstantiationError;" 10606.LstrNegativeArraySizeException: 10607 .asciz "Ljava/lang/NegativeArraySizeException;" 10608.LstrNoSuchMethodError: 10609 .asciz "Ljava/lang/NoSuchMethodError;" 10610.LstrNullPointerException: 10611 .asciz "Ljava/lang/NullPointerException;" 10612 10613.LstrLogTag: 10614 .asciz "mterp" 10615.LstrExceptionNotCaughtLocally: 10616 .asciz "Exception %s from %s:%d not caught locally\n" 10617 10618.LstrNewline: 10619 .asciz "\n" 10620.LstrSqueak: 10621 .asciz "<%d>" 10622.LstrPrintHex: 10623 .asciz "<0x%x>" 10624.LstrPrintLong: 10625 .asciz "<%lld>" 10626 10627