InterpAsm-armv7-a-neon.S revision d3b0a4bf6b2e38e6e9e80e203ca753e941084103
1/* 2 * This file was generated automatically by gen-mterp.py for 'armv7-a-neon'. 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: armv7-a/platform.S */ 210/* 211 * =========================================================================== 212 * CPU-version-specific defines 213 * =========================================================================== 214 */ 215 216/* 217 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5. Essentially a 218 * one-way branch. 219 * 220 * May modify IP. Does not modify LR. 221 */ 222.macro LDR_PC source 223 ldr pc, \source 224.endm 225 226/* 227 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5. 228 * Jump to subroutine. 229 * 230 * May modify IP and LR. 231 */ 232.macro LDR_PC_LR source 233 mov lr, pc 234 ldr pc, \source 235.endm 236 237/* 238 * Macro for "LDMFD SP!, {...regs...,PC}". 239 * 240 * May modify IP and LR. 241 */ 242.macro LDMFD_PC regs 243 ldmfd sp!, {\regs,pc} 244.endm 245 246#if !defined(ANDROID_SMP) 247# error "Must define ANDROID_SMP" 248#endif 249 250/* 251 * Macro for data memory barrier. 252 */ 253.macro SMP_DMB 254#if ANDROID_SMP != 0 255 dmb 256#else 257 /* not SMP */ 258#endif 259.endm 260 261/* 262 * Macro for data memory barrier (store/store variant). 263 */ 264.macro SMP_DMB_ST 265#if ANDROID_SMP != 0 266 dmb @ TODO: want "dmb st" here 267#else 268 /* not SMP */ 269#endif 270.endm 271 272/* File: armv5te/entry.S */ 273/* 274 * Copyright (C) 2008 The Android Open Source Project 275 * 276 * Licensed under the Apache License, Version 2.0 (the "License"); 277 * you may not use this file except in compliance with the License. 278 * You may obtain a copy of the License at 279 * 280 * http://www.apache.org/licenses/LICENSE-2.0 281 * 282 * Unless required by applicable law or agreed to in writing, software 283 * distributed under the License is distributed on an "AS IS" BASIS, 284 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 285 * See the License for the specific language governing permissions and 286 * limitations under the License. 287 */ 288/* 289 * Interpreter entry point. 290 */ 291 292/* 293 * We don't have formal stack frames, so gdb scans upward in the code 294 * to find the start of the function (a label with the %function type), 295 * and then looks at the next few instructions to figure out what 296 * got pushed onto the stack. From this it figures out how to restore 297 * the registers, including PC, for the previous stack frame. If gdb 298 * sees a non-function label, it stops scanning, so either we need to 299 * have nothing but assembler-local labels between the entry point and 300 * the break, or we need to fake it out. 301 * 302 * When this is defined, we add some stuff to make gdb less confused. 303 */ 304#define ASSIST_DEBUGGER 1 305 306 .text 307 .align 2 308 .global dvmMterpStdRun 309 .type dvmMterpStdRun, %function 310 311/* 312 * On entry: 313 * r0 MterpGlue* glue 314 * 315 * This function returns a boolean "changeInterp" value. The return comes 316 * via a call to dvmMterpStdBail(). 317 */ 318dvmMterpStdRun: 319#define MTERP_ENTRY1 \ 320 .save {r4-r10,fp,lr}; \ 321 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs 322#define MTERP_ENTRY2 \ 323 .pad #4; \ 324 sub sp, sp, #4 @ align 64 325 326 .fnstart 327 MTERP_ENTRY1 328 MTERP_ENTRY2 329 330 /* save stack pointer, add magic word for debuggerd */ 331 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return 332 333 /* set up "named" registers, figure out entry point */ 334 mov rGLUE, r0 @ set rGLUE 335 ldr r1, [r0, #offGlue_entryPoint] @ enum is 4 bytes in aapcs-EABI 336 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue" 337 adr rIBASE, dvmAsmInstructionStart @ set rIBASE 338 cmp r1, #kInterpEntryInstr @ usual case? 339 bne .Lnot_instr @ no, handle it 340 341#if defined(WITH_JIT) 342.LentryInstr: 343 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 344 /* Entry is always a possible trace start */ 345 GET_JIT_PROF_TABLE(r0) 346 FETCH_INST() 347 mov r1, #0 @ prepare the value for the new state 348 str r1, [r10, #offThread_inJitCodeCache] @ back to the interp land 349 cmp r0,#0 @ is profiling disabled? 350#if !defined(WITH_SELF_VERIFICATION) 351 bne common_updateProfile @ profiling is enabled 352#else 353 ldr r2, [r10, #offThread_shadowSpace] @ to find out the jit exit state 354 beq 1f @ profiling is disabled 355 ldr r3, [r2, #offShadowSpace_jitExitState] @ jit exit state 356 cmp r3, #kSVSTraceSelect @ hot trace following? 357 moveq r2,#kJitTSelectRequestHot @ ask for trace selection 358 beq common_selectTrace @ go build the trace 359 cmp r3, #kSVSNoProfile @ don't profile the next instruction? 360 beq 1f @ intrepret the next instruction 361 b common_updateProfile @ collect profiles 362#endif 3631: 364 GET_INST_OPCODE(ip) 365 GOTO_OPCODE(ip) 366#else 367 /* start executing the instruction at rPC */ 368 FETCH_INST() @ load rINST from rPC 369 GET_INST_OPCODE(ip) @ extract opcode from rINST 370 GOTO_OPCODE(ip) @ jump to next instruction 371#endif 372 373.Lnot_instr: 374 cmp r1, #kInterpEntryReturn @ were we returning from a method? 375 beq common_returnFromMethod 376 377.Lnot_return: 378 cmp r1, #kInterpEntryThrow @ were we throwing an exception? 379 beq common_exceptionThrown 380 381#if defined(WITH_JIT) 382.Lnot_throw: 383 ldr r10,[rGLUE, #offGlue_jitResumeNPC] 384 ldr r2,[rGLUE, #offGlue_jitResumeDPC] 385 cmp r1, #kInterpEntryResume @ resuming after Jit single-step? 386 bne .Lbad_arg 387 cmp rPC,r2 388 bne .LentryInstr @ must have branched, don't resume 389#if defined(WITH_SELF_VERIFICATION) 390 @ glue->entryPoint will be set in dvmSelfVerificationSaveState 391 b jitSVShadowRunStart @ re-enter the translation after the 392 @ single-stepped instruction 393 @noreturn 394#endif 395 mov r1, #kInterpEntryInstr 396 str r1, [rGLUE, #offGlue_entryPoint] 397 bx r10 @ re-enter the translation 398#endif 399 400.Lbad_arg: 401 ldr r0, strBadEntryPoint 402 @ r1 holds value of entryPoint 403 bl printf 404 bl dvmAbort 405 .fnend 406 407 408 .global dvmMterpStdBail 409 .type dvmMterpStdBail, %function 410 411/* 412 * Restore the stack pointer and PC from the save point established on entry. 413 * This is essentially the same as a longjmp, but should be cheaper. The 414 * last instruction causes us to return to whoever called dvmMterpStdRun. 415 * 416 * We pushed some registers on the stack in dvmMterpStdRun, then saved 417 * SP and LR. Here we restore SP, restore the registers, and then restore 418 * LR to PC. 419 * 420 * On entry: 421 * r0 MterpGlue* glue 422 * r1 bool changeInterp 423 */ 424dvmMterpStdBail: 425 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 426 mov r0, r1 @ return the changeInterp value 427 add sp, sp, #4 @ un-align 64 428 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return 429 430 431/* 432 * String references. 433 */ 434strBadEntryPoint: 435 .word .LstrBadEntryPoint 436 437 438 .global dvmAsmInstructionStart 439 .type dvmAsmInstructionStart, %function 440dvmAsmInstructionStart = .L_OP_NOP 441 .text 442 443/* ------------------------------ */ 444 .balign 64 445.L_OP_NOP: /* 0x00 */ 446/* File: armv5te/OP_NOP.S */ 447 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST 448 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 449 GOTO_OPCODE(ip) @ execute it 450 451#ifdef ASSIST_DEBUGGER 452 /* insert fake function header to help gdb find the stack frame */ 453 .type dalvik_inst, %function 454dalvik_inst: 455 .fnstart 456 MTERP_ENTRY1 457 MTERP_ENTRY2 458 .fnend 459#endif 460 461/* ------------------------------ */ 462 .balign 64 463.L_OP_MOVE: /* 0x01 */ 464/* File: armv6t2/OP_MOVE.S */ 465 /* for move, move-object, long-to-int */ 466 /* op vA, vB */ 467 mov r1, rINST, lsr #12 @ r1<- B from 15:12 468 ubfx r0, rINST, #8, #4 @ r0<- A from 11:8 469 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 470 GET_VREG(r2, r1) @ r2<- fp[B] 471 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 472 SET_VREG(r2, r0) @ fp[A]<- r2 473 GOTO_OPCODE(ip) @ execute next instruction 474 475/* ------------------------------ */ 476 .balign 64 477.L_OP_MOVE_FROM16: /* 0x02 */ 478/* File: armv5te/OP_MOVE_FROM16.S */ 479 /* for: move/from16, move-object/from16 */ 480 /* op vAA, vBBBB */ 481 FETCH(r1, 1) @ r1<- BBBB 482 mov r0, rINST, lsr #8 @ r0<- AA 483 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 484 GET_VREG(r2, r1) @ r2<- fp[BBBB] 485 GET_INST_OPCODE(ip) @ extract opcode from rINST 486 SET_VREG(r2, r0) @ fp[AA]<- r2 487 GOTO_OPCODE(ip) @ jump to next instruction 488 489/* ------------------------------ */ 490 .balign 64 491.L_OP_MOVE_16: /* 0x03 */ 492/* File: armv5te/OP_MOVE_16.S */ 493 /* for: move/16, move-object/16 */ 494 /* op vAAAA, vBBBB */ 495 FETCH(r1, 2) @ r1<- BBBB 496 FETCH(r0, 1) @ r0<- AAAA 497 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 498 GET_VREG(r2, r1) @ r2<- fp[BBBB] 499 GET_INST_OPCODE(ip) @ extract opcode from rINST 500 SET_VREG(r2, r0) @ fp[AAAA]<- r2 501 GOTO_OPCODE(ip) @ jump to next instruction 502 503/* ------------------------------ */ 504 .balign 64 505.L_OP_MOVE_WIDE: /* 0x04 */ 506/* File: armv6t2/OP_MOVE_WIDE.S */ 507 /* move-wide vA, vB */ 508 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 509 mov r3, rINST, lsr #12 @ r3<- B 510 ubfx r2, rINST, #8, #4 @ r2<- A 511 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 512 add r2, rFP, r2, lsl #2 @ r2<- &fp[A] 513 ldmia r3, {r0-r1} @ r0/r1<- fp[B] 514 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 515 GET_INST_OPCODE(ip) @ extract opcode from rINST 516 stmia r2, {r0-r1} @ fp[A]<- r0/r1 517 GOTO_OPCODE(ip) @ jump to next instruction 518 519/* ------------------------------ */ 520 .balign 64 521.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 522/* File: armv5te/OP_MOVE_WIDE_FROM16.S */ 523 /* move-wide/from16 vAA, vBBBB */ 524 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 525 FETCH(r3, 1) @ r3<- BBBB 526 mov r2, rINST, lsr #8 @ r2<- AA 527 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 528 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 529 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 530 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 531 GET_INST_OPCODE(ip) @ extract opcode from rINST 532 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 533 GOTO_OPCODE(ip) @ jump to next instruction 534 535/* ------------------------------ */ 536 .balign 64 537.L_OP_MOVE_WIDE_16: /* 0x06 */ 538/* File: armv5te/OP_MOVE_WIDE_16.S */ 539 /* move-wide/16 vAAAA, vBBBB */ 540 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 541 FETCH(r3, 2) @ r3<- BBBB 542 FETCH(r2, 1) @ r2<- AAAA 543 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 544 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA] 545 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 546 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 547 GET_INST_OPCODE(ip) @ extract opcode from rINST 548 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1 549 GOTO_OPCODE(ip) @ jump to next instruction 550 551/* ------------------------------ */ 552 .balign 64 553.L_OP_MOVE_OBJECT: /* 0x07 */ 554/* File: armv5te/OP_MOVE_OBJECT.S */ 555/* File: armv5te/OP_MOVE.S */ 556 /* for move, move-object, long-to-int */ 557 /* op vA, vB */ 558 mov r1, rINST, lsr #12 @ r1<- B from 15:12 559 mov r0, rINST, lsr #8 @ r0<- A from 11:8 560 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 561 GET_VREG(r2, r1) @ r2<- fp[B] 562 and r0, r0, #15 563 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 564 SET_VREG(r2, r0) @ fp[A]<- r2 565 GOTO_OPCODE(ip) @ execute next instruction 566 567 568/* ------------------------------ */ 569 .balign 64 570.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 571/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */ 572/* File: armv5te/OP_MOVE_FROM16.S */ 573 /* for: move/from16, move-object/from16 */ 574 /* op vAA, vBBBB */ 575 FETCH(r1, 1) @ r1<- BBBB 576 mov r0, rINST, lsr #8 @ r0<- AA 577 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 578 GET_VREG(r2, r1) @ r2<- fp[BBBB] 579 GET_INST_OPCODE(ip) @ extract opcode from rINST 580 SET_VREG(r2, r0) @ fp[AA]<- r2 581 GOTO_OPCODE(ip) @ jump to next instruction 582 583 584/* ------------------------------ */ 585 .balign 64 586.L_OP_MOVE_OBJECT_16: /* 0x09 */ 587/* File: armv5te/OP_MOVE_OBJECT_16.S */ 588/* File: armv5te/OP_MOVE_16.S */ 589 /* for: move/16, move-object/16 */ 590 /* op vAAAA, vBBBB */ 591 FETCH(r1, 2) @ r1<- BBBB 592 FETCH(r0, 1) @ r0<- AAAA 593 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 594 GET_VREG(r2, r1) @ r2<- fp[BBBB] 595 GET_INST_OPCODE(ip) @ extract opcode from rINST 596 SET_VREG(r2, r0) @ fp[AAAA]<- r2 597 GOTO_OPCODE(ip) @ jump to next instruction 598 599 600/* ------------------------------ */ 601 .balign 64 602.L_OP_MOVE_RESULT: /* 0x0a */ 603/* File: armv5te/OP_MOVE_RESULT.S */ 604 /* for: move-result, move-result-object */ 605 /* op vAA */ 606 mov r2, rINST, lsr #8 @ r2<- AA 607 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 608 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 609 GET_INST_OPCODE(ip) @ extract opcode from rINST 610 SET_VREG(r0, r2) @ fp[AA]<- r0 611 GOTO_OPCODE(ip) @ jump to next instruction 612 613/* ------------------------------ */ 614 .balign 64 615.L_OP_MOVE_RESULT_WIDE: /* 0x0b */ 616/* File: armv5te/OP_MOVE_RESULT_WIDE.S */ 617 /* move-result-wide vAA */ 618 mov r2, rINST, lsr #8 @ r2<- AA 619 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 620 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 621 ldmia r3, {r0-r1} @ r0/r1<- retval.j 622 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 623 GET_INST_OPCODE(ip) @ extract opcode from rINST 624 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 625 GOTO_OPCODE(ip) @ jump to next instruction 626 627/* ------------------------------ */ 628 .balign 64 629.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 630/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */ 631/* File: armv5te/OP_MOVE_RESULT.S */ 632 /* for: move-result, move-result-object */ 633 /* op vAA */ 634 mov r2, rINST, lsr #8 @ r2<- AA 635 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 636 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 637 GET_INST_OPCODE(ip) @ extract opcode from rINST 638 SET_VREG(r0, r2) @ fp[AA]<- r0 639 GOTO_OPCODE(ip) @ jump to next instruction 640 641 642/* ------------------------------ */ 643 .balign 64 644.L_OP_MOVE_EXCEPTION: /* 0x0d */ 645/* File: armv5te/OP_MOVE_EXCEPTION.S */ 646 /* move-exception vAA */ 647 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 648 mov r2, rINST, lsr #8 @ r2<- AA 649 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass 650 mov r1, #0 @ r1<- 0 651 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 652 SET_VREG(r3, r2) @ fp[AA]<- exception obj 653 GET_INST_OPCODE(ip) @ extract opcode from rINST 654 str r1, [r0, #offThread_exception] @ dvmClearException bypass 655 GOTO_OPCODE(ip) @ jump to next instruction 656 657/* ------------------------------ */ 658 .balign 64 659.L_OP_RETURN_VOID: /* 0x0e */ 660/* File: armv5te/OP_RETURN_VOID.S */ 661 b common_returnFromMethod 662 663/* ------------------------------ */ 664 .balign 64 665.L_OP_RETURN: /* 0x0f */ 666/* File: armv5te/OP_RETURN.S */ 667 /* 668 * Return a 32-bit value. Copies the return value into the "glue" 669 * structure, then jumps to the return handler. 670 * 671 * for: return, return-object 672 */ 673 /* op vAA */ 674 mov r2, rINST, lsr #8 @ r2<- AA 675 GET_VREG(r0, r2) @ r0<- vAA 676 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 677 b common_returnFromMethod 678 679/* ------------------------------ */ 680 .balign 64 681.L_OP_RETURN_WIDE: /* 0x10 */ 682/* File: armv5te/OP_RETURN_WIDE.S */ 683 /* 684 * Return a 64-bit value. Copies the return value into the "glue" 685 * structure, then jumps to the return handler. 686 */ 687 /* return-wide vAA */ 688 mov r2, rINST, lsr #8 @ r2<- AA 689 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 690 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 691 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1 692 stmia r3, {r0-r1} @ retval<- r0/r1 693 b common_returnFromMethod 694 695/* ------------------------------ */ 696 .balign 64 697.L_OP_RETURN_OBJECT: /* 0x11 */ 698/* File: armv5te/OP_RETURN_OBJECT.S */ 699/* File: armv5te/OP_RETURN.S */ 700 /* 701 * Return a 32-bit value. Copies the return value into the "glue" 702 * structure, then jumps to the return handler. 703 * 704 * for: return, return-object 705 */ 706 /* op vAA */ 707 mov r2, rINST, lsr #8 @ r2<- AA 708 GET_VREG(r0, r2) @ r0<- vAA 709 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 710 b common_returnFromMethod 711 712 713/* ------------------------------ */ 714 .balign 64 715.L_OP_CONST_4: /* 0x12 */ 716/* File: armv6t2/OP_CONST_4.S */ 717 /* const/4 vA, #+B */ 718 mov r1, rINST, lsl #16 @ r1<- Bxxx0000 719 ubfx r0, rINST, #8, #4 @ r0<- A 720 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 721 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended) 722 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 723 SET_VREG(r1, r0) @ fp[A]<- r1 724 GOTO_OPCODE(ip) @ execute next instruction 725 726/* ------------------------------ */ 727 .balign 64 728.L_OP_CONST_16: /* 0x13 */ 729/* File: armv5te/OP_CONST_16.S */ 730 /* const/16 vAA, #+BBBB */ 731 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 732 mov r3, rINST, lsr #8 @ r3<- AA 733 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 734 SET_VREG(r0, r3) @ vAA<- r0 735 GET_INST_OPCODE(ip) @ extract opcode from rINST 736 GOTO_OPCODE(ip) @ jump to next instruction 737 738/* ------------------------------ */ 739 .balign 64 740.L_OP_CONST: /* 0x14 */ 741/* File: armv5te/OP_CONST.S */ 742 /* const vAA, #+BBBBbbbb */ 743 mov r3, rINST, lsr #8 @ r3<- AA 744 FETCH(r0, 1) @ r0<- bbbb (low) 745 FETCH(r1, 2) @ r1<- BBBB (high) 746 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 747 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 748 GET_INST_OPCODE(ip) @ extract opcode from rINST 749 SET_VREG(r0, r3) @ vAA<- r0 750 GOTO_OPCODE(ip) @ jump to next instruction 751 752/* ------------------------------ */ 753 .balign 64 754.L_OP_CONST_HIGH16: /* 0x15 */ 755/* File: armv5te/OP_CONST_HIGH16.S */ 756 /* const/high16 vAA, #+BBBB0000 */ 757 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended) 758 mov r3, rINST, lsr #8 @ r3<- AA 759 mov r0, r0, lsl #16 @ r0<- BBBB0000 760 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 761 SET_VREG(r0, r3) @ vAA<- r0 762 GET_INST_OPCODE(ip) @ extract opcode from rINST 763 GOTO_OPCODE(ip) @ jump to next instruction 764 765/* ------------------------------ */ 766 .balign 64 767.L_OP_CONST_WIDE_16: /* 0x16 */ 768/* File: armv5te/OP_CONST_WIDE_16.S */ 769 /* const-wide/16 vAA, #+BBBB */ 770 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 771 mov r3, rINST, lsr #8 @ r3<- AA 772 mov r1, r0, asr #31 @ r1<- ssssssss 773 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 774 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 775 GET_INST_OPCODE(ip) @ extract opcode from rINST 776 stmia r3, {r0-r1} @ vAA<- r0/r1 777 GOTO_OPCODE(ip) @ jump to next instruction 778 779/* ------------------------------ */ 780 .balign 64 781.L_OP_CONST_WIDE_32: /* 0x17 */ 782/* File: armv5te/OP_CONST_WIDE_32.S */ 783 /* const-wide/32 vAA, #+BBBBbbbb */ 784 FETCH(r0, 1) @ r0<- 0000bbbb (low) 785 mov r3, rINST, lsr #8 @ r3<- AA 786 FETCH_S(r2, 2) @ r2<- ssssBBBB (high) 787 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 788 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb 789 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 790 mov r1, r0, asr #31 @ r1<- ssssssss 791 GET_INST_OPCODE(ip) @ extract opcode from rINST 792 stmia r3, {r0-r1} @ vAA<- r0/r1 793 GOTO_OPCODE(ip) @ jump to next instruction 794 795/* ------------------------------ */ 796 .balign 64 797.L_OP_CONST_WIDE: /* 0x18 */ 798/* File: armv5te/OP_CONST_WIDE.S */ 799 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 800 FETCH(r0, 1) @ r0<- bbbb (low) 801 FETCH(r1, 2) @ r1<- BBBB (low middle) 802 FETCH(r2, 3) @ r2<- hhhh (high middle) 803 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word) 804 FETCH(r3, 4) @ r3<- HHHH (high) 805 mov r9, rINST, lsr #8 @ r9<- AA 806 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word) 807 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 808 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 809 GET_INST_OPCODE(ip) @ extract opcode from rINST 810 stmia r9, {r0-r1} @ vAA<- r0/r1 811 GOTO_OPCODE(ip) @ jump to next instruction 812 813/* ------------------------------ */ 814 .balign 64 815.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 816/* File: armv5te/OP_CONST_WIDE_HIGH16.S */ 817 /* const-wide/high16 vAA, #+BBBB000000000000 */ 818 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended) 819 mov r3, rINST, lsr #8 @ r3<- AA 820 mov r0, #0 @ r0<- 00000000 821 mov r1, r1, lsl #16 @ r1<- BBBB0000 822 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 823 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 824 GET_INST_OPCODE(ip) @ extract opcode from rINST 825 stmia r3, {r0-r1} @ vAA<- r0/r1 826 GOTO_OPCODE(ip) @ jump to next instruction 827 828/* ------------------------------ */ 829 .balign 64 830.L_OP_CONST_STRING: /* 0x1a */ 831/* File: armv5te/OP_CONST_STRING.S */ 832 /* const/string vAA, String@BBBB */ 833 FETCH(r1, 1) @ r1<- BBBB 834 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 835 mov r9, rINST, lsr #8 @ r9<- AA 836 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 837 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 838 cmp r0, #0 @ not yet resolved? 839 beq .LOP_CONST_STRING_resolve 840 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 841 GET_INST_OPCODE(ip) @ extract opcode from rINST 842 SET_VREG(r0, r9) @ vAA<- r0 843 GOTO_OPCODE(ip) @ jump to next instruction 844 845/* ------------------------------ */ 846 .balign 64 847.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 848/* File: armv5te/OP_CONST_STRING_JUMBO.S */ 849 /* const/string vAA, String@BBBBBBBB */ 850 FETCH(r0, 1) @ r0<- bbbb (low) 851 FETCH(r1, 2) @ r1<- BBBB (high) 852 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 853 mov r9, rINST, lsr #8 @ r9<- AA 854 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 855 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 856 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 857 cmp r0, #0 858 beq .LOP_CONST_STRING_JUMBO_resolve 859 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 860 GET_INST_OPCODE(ip) @ extract opcode from rINST 861 SET_VREG(r0, r9) @ vAA<- r0 862 GOTO_OPCODE(ip) @ jump to next instruction 863 864/* ------------------------------ */ 865 .balign 64 866.L_OP_CONST_CLASS: /* 0x1c */ 867/* File: armv5te/OP_CONST_CLASS.S */ 868 /* const/class vAA, Class@BBBB */ 869 FETCH(r1, 1) @ r1<- BBBB 870 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 871 mov r9, rINST, lsr #8 @ r9<- AA 872 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 873 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB] 874 cmp r0, #0 @ not yet resolved? 875 beq .LOP_CONST_CLASS_resolve 876 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 877 GET_INST_OPCODE(ip) @ extract opcode from rINST 878 SET_VREG(r0, r9) @ vAA<- r0 879 GOTO_OPCODE(ip) @ jump to next instruction 880 881/* ------------------------------ */ 882 .balign 64 883.L_OP_MONITOR_ENTER: /* 0x1d */ 884/* File: armv5te/OP_MONITOR_ENTER.S */ 885 /* 886 * Synchronize on an object. 887 */ 888 /* monitor-enter vAA */ 889 mov r2, rINST, lsr #8 @ r2<- AA 890 GET_VREG(r1, r2) @ r1<- vAA (object) 891 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 892 cmp r1, #0 @ null object? 893 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING 894 beq common_errNullObject @ null object, throw an exception 895 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 896 bl dvmLockObject @ call(self, obj) 897#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ 898 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 899 ldr r1, [r0, #offThread_exception] @ check for exception 900 cmp r1, #0 901 bne common_exceptionThrown @ exception raised, bail out 902#endif 903 GET_INST_OPCODE(ip) @ extract opcode from rINST 904 GOTO_OPCODE(ip) @ jump to next instruction 905 906/* ------------------------------ */ 907 .balign 64 908.L_OP_MONITOR_EXIT: /* 0x1e */ 909/* File: armv5te/OP_MONITOR_EXIT.S */ 910 /* 911 * Unlock an object. 912 * 913 * Exceptions that occur when unlocking a monitor need to appear as 914 * if they happened at the following instruction. See the Dalvik 915 * instruction spec. 916 */ 917 /* monitor-exit vAA */ 918 mov r2, rINST, lsr #8 @ r2<- AA 919 EXPORT_PC() @ before fetch: export the PC 920 GET_VREG(r1, r2) @ r1<- vAA (object) 921 cmp r1, #0 @ null object? 922 beq 1f @ yes 923 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 924 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 925 cmp r0, #0 @ failed? 926 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 927 beq common_exceptionThrown @ yes, exception is pending 928 GET_INST_OPCODE(ip) @ extract opcode from rINST 929 GOTO_OPCODE(ip) @ jump to next instruction 9301: 931 FETCH_ADVANCE_INST(1) @ advance before throw 932 b common_errNullObject 933 934/* ------------------------------ */ 935 .balign 64 936.L_OP_CHECK_CAST: /* 0x1f */ 937/* File: armv5te/OP_CHECK_CAST.S */ 938 /* 939 * Check to see if a cast from one class to another is allowed. 940 */ 941 /* check-cast vAA, class@BBBB */ 942 mov r3, rINST, lsr #8 @ r3<- AA 943 FETCH(r2, 1) @ r2<- BBBB 944 GET_VREG(r9, r3) @ r9<- object 945 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 946 cmp r9, #0 @ is object null? 947 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 948 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 949 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 950 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 951 cmp r1, #0 @ have we resolved this before? 952 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 953.LOP_CHECK_CAST_resolved: 954 cmp r0, r1 @ same class (trivial success)? 955 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 956.LOP_CHECK_CAST_okay: 957 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 958 GET_INST_OPCODE(ip) @ extract opcode from rINST 959 GOTO_OPCODE(ip) @ jump to next instruction 960 961/* ------------------------------ */ 962 .balign 64 963.L_OP_INSTANCE_OF: /* 0x20 */ 964/* File: armv5te/OP_INSTANCE_OF.S */ 965 /* 966 * Check to see if an object reference is an instance of a class. 967 * 968 * Most common situation is a non-null object, being compared against 969 * an already-resolved class. 970 */ 971 /* instance-of vA, vB, class@CCCC */ 972 mov r3, rINST, lsr #12 @ r3<- B 973 mov r9, rINST, lsr #8 @ r9<- A+ 974 GET_VREG(r0, r3) @ r0<- vB (object) 975 and r9, r9, #15 @ r9<- A 976 cmp r0, #0 @ is object null? 977 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 978 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 979 FETCH(r3, 1) @ r3<- CCCC 980 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 981 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 982 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 983 cmp r1, #0 @ have we resolved this before? 984 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 985.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 986 cmp r0, r1 @ same class (trivial success)? 987 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 988 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 989 990/* ------------------------------ */ 991 .balign 64 992.L_OP_ARRAY_LENGTH: /* 0x21 */ 993/* File: armv6t2/OP_ARRAY_LENGTH.S */ 994 /* 995 * Return the length of an array. 996 */ 997 mov r1, rINST, lsr #12 @ r1<- B 998 ubfx r2, rINST, #8, #4 @ r2<- A 999 GET_VREG(r0, r1) @ r0<- vB (object ref) 1000 cmp r0, #0 @ is object null? 1001 beq common_errNullObject @ yup, fail 1002 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 1003 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 1004 GET_INST_OPCODE(ip) @ extract opcode from rINST 1005 SET_VREG(r3, r2) @ vB<- length 1006 GOTO_OPCODE(ip) @ jump to next instruction 1007 1008/* ------------------------------ */ 1009 .balign 64 1010.L_OP_NEW_INSTANCE: /* 0x22 */ 1011/* File: armv5te/OP_NEW_INSTANCE.S */ 1012 /* 1013 * Create a new instance of a class. 1014 */ 1015 /* new-instance vAA, class@BBBB */ 1016 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1017 FETCH(r1, 1) @ r1<- BBBB 1018 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1019 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1020 EXPORT_PC() @ req'd for init, resolve, alloc 1021 cmp r0, #0 @ already resolved? 1022 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 1023.LOP_NEW_INSTANCE_resolved: @ r0=class 1024 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 1025 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 1026 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 1027.LOP_NEW_INSTANCE_initialized: @ r0=class 1028 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 1029 bl dvmAllocObject @ r0<- new object 1030 b .LOP_NEW_INSTANCE_finish @ continue 1031 1032/* ------------------------------ */ 1033 .balign 64 1034.L_OP_NEW_ARRAY: /* 0x23 */ 1035/* File: armv5te/OP_NEW_ARRAY.S */ 1036 /* 1037 * Allocate an array of objects, specified with the array class 1038 * and a count. 1039 * 1040 * The verifier guarantees that this is an array class, so we don't 1041 * check for it here. 1042 */ 1043 /* new-array vA, vB, class@CCCC */ 1044 mov r0, rINST, lsr #12 @ r0<- B 1045 FETCH(r2, 1) @ r2<- CCCC 1046 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1047 GET_VREG(r1, r0) @ r1<- vB (array length) 1048 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1049 cmp r1, #0 @ check length 1050 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 1051 bmi common_errNegativeArraySize @ negative length, bail 1052 cmp r0, #0 @ already resolved? 1053 EXPORT_PC() @ req'd for resolve, alloc 1054 bne .LOP_NEW_ARRAY_finish @ resolved, continue 1055 b .LOP_NEW_ARRAY_resolve @ do resolve now 1056 1057/* ------------------------------ */ 1058 .balign 64 1059.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1060/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1061 /* 1062 * Create a new array with elements filled from registers. 1063 * 1064 * for: filled-new-array, filled-new-array/range 1065 */ 1066 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1067 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1068 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1069 FETCH(r1, 1) @ r1<- BBBB 1070 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1071 EXPORT_PC() @ need for resolve and alloc 1072 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1073 mov r10, rINST, lsr #8 @ r10<- AA or BA 1074 cmp r0, #0 @ already resolved? 1075 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10768: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1077 mov r2, #0 @ r2<- false 1078 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1079 bl dvmResolveClass @ r0<- call(clazz, ref) 1080 cmp r0, #0 @ got null? 1081 beq common_exceptionThrown @ yes, handle exception 1082 b .LOP_FILLED_NEW_ARRAY_continue 1083 1084/* ------------------------------ */ 1085 .balign 64 1086.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1087/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1088/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1089 /* 1090 * Create a new array with elements filled from registers. 1091 * 1092 * for: filled-new-array, filled-new-array/range 1093 */ 1094 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1095 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1096 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1097 FETCH(r1, 1) @ r1<- BBBB 1098 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1099 EXPORT_PC() @ need for resolve and alloc 1100 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1101 mov r10, rINST, lsr #8 @ r10<- AA or BA 1102 cmp r0, #0 @ already resolved? 1103 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 11048: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1105 mov r2, #0 @ r2<- false 1106 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1107 bl dvmResolveClass @ r0<- call(clazz, ref) 1108 cmp r0, #0 @ got null? 1109 beq common_exceptionThrown @ yes, handle exception 1110 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1111 1112 1113/* ------------------------------ */ 1114 .balign 64 1115.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1116/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1117 /* fill-array-data vAA, +BBBBBBBB */ 1118 FETCH(r0, 1) @ r0<- bbbb (lo) 1119 FETCH(r1, 2) @ r1<- BBBB (hi) 1120 mov r3, rINST, lsr #8 @ r3<- AA 1121 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1122 GET_VREG(r0, r3) @ r0<- vAA (array object) 1123 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1124 EXPORT_PC(); 1125 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1126 cmp r0, #0 @ 0 means an exception is thrown 1127 beq common_exceptionThrown @ has exception 1128 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1129 GET_INST_OPCODE(ip) @ extract opcode from rINST 1130 GOTO_OPCODE(ip) @ jump to next instruction 1131 1132/* ------------------------------ */ 1133 .balign 64 1134.L_OP_THROW: /* 0x27 */ 1135/* File: armv5te/OP_THROW.S */ 1136 /* 1137 * Throw an exception object in the current thread. 1138 */ 1139 /* throw vAA */ 1140 mov r2, rINST, lsr #8 @ r2<- AA 1141 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1142 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1143 EXPORT_PC() @ exception handler can throw 1144 cmp r1, #0 @ null object? 1145 beq common_errNullObject @ yes, throw an NPE instead 1146 @ bypass dvmSetException, just store it 1147 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1148 b common_exceptionThrown 1149 1150/* ------------------------------ */ 1151 .balign 64 1152.L_OP_GOTO: /* 0x28 */ 1153/* File: armv5te/OP_GOTO.S */ 1154 /* 1155 * Unconditional branch, 8-bit offset. 1156 * 1157 * The branch distance is a signed code-unit offset, which we need to 1158 * double to get a byte offset. 1159 */ 1160 /* goto +AA */ 1161 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1162 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1163 mov r9, r9, lsl #1 @ r9<- byte offset 1164 bmi common_backwardBranch @ backward branch, do periodic checks 1165#if defined(WITH_JIT) 1166 GET_JIT_PROF_TABLE(r0) 1167 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1168 cmp r0,#0 1169 bne common_updateProfile 1170 GET_INST_OPCODE(ip) @ extract opcode from rINST 1171 GOTO_OPCODE(ip) @ jump to next instruction 1172#else 1173 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1174 GET_INST_OPCODE(ip) @ extract opcode from rINST 1175 GOTO_OPCODE(ip) @ jump to next instruction 1176#endif 1177 1178/* ------------------------------ */ 1179 .balign 64 1180.L_OP_GOTO_16: /* 0x29 */ 1181/* File: armv5te/OP_GOTO_16.S */ 1182 /* 1183 * Unconditional branch, 16-bit offset. 1184 * 1185 * The branch distance is a signed code-unit offset, which we need to 1186 * double to get a byte offset. 1187 */ 1188 /* goto/16 +AAAA */ 1189 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1190 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1191 bmi common_backwardBranch @ backward branch, do periodic checks 1192#if defined(WITH_JIT) 1193 GET_JIT_PROF_TABLE(r0) 1194 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1195 cmp r0,#0 1196 bne common_updateProfile 1197 GET_INST_OPCODE(ip) @ extract opcode from rINST 1198 GOTO_OPCODE(ip) @ jump to next instruction 1199#else 1200 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1201 GET_INST_OPCODE(ip) @ extract opcode from rINST 1202 GOTO_OPCODE(ip) @ jump to next instruction 1203#endif 1204 1205/* ------------------------------ */ 1206 .balign 64 1207.L_OP_GOTO_32: /* 0x2a */ 1208/* File: armv5te/OP_GOTO_32.S */ 1209 /* 1210 * Unconditional branch, 32-bit offset. 1211 * 1212 * The branch distance is a signed code-unit offset, which we need to 1213 * double to get a byte offset. 1214 * 1215 * Unlike most opcodes, this one is allowed to branch to itself, so 1216 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1217 * instruction doesn't affect the V flag, so we need to clear it 1218 * explicitly. 1219 */ 1220 /* goto/32 +AAAAAAAA */ 1221 FETCH(r0, 1) @ r0<- aaaa (lo) 1222 FETCH(r1, 2) @ r1<- AAAA (hi) 1223 cmp ip, ip @ (clear V flag during stall) 1224 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1225 mov r9, r0, asl #1 @ r9<- byte offset 1226 ble common_backwardBranch @ backward branch, do periodic checks 1227#if defined(WITH_JIT) 1228 GET_JIT_PROF_TABLE(r0) 1229 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1230 cmp r0,#0 1231 bne common_updateProfile 1232 GET_INST_OPCODE(ip) @ extract opcode from rINST 1233 GOTO_OPCODE(ip) @ jump to next instruction 1234#else 1235 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1236 GET_INST_OPCODE(ip) @ extract opcode from rINST 1237 GOTO_OPCODE(ip) @ jump to next instruction 1238#endif 1239 1240/* ------------------------------ */ 1241 .balign 64 1242.L_OP_PACKED_SWITCH: /* 0x2b */ 1243/* File: armv5te/OP_PACKED_SWITCH.S */ 1244 /* 1245 * Handle a packed-switch or sparse-switch instruction. In both cases 1246 * we decode it and hand it off to a helper function. 1247 * 1248 * We don't really expect backward branches in a switch statement, but 1249 * they're perfectly legal, so we check for them here. 1250 * 1251 * for: packed-switch, sparse-switch 1252 */ 1253 /* op vAA, +BBBB */ 1254 FETCH(r0, 1) @ r0<- bbbb (lo) 1255 FETCH(r1, 2) @ r1<- BBBB (hi) 1256 mov r3, rINST, lsr #8 @ r3<- AA 1257 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1258 GET_VREG(r1, r3) @ r1<- vAA 1259 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1260 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1261 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1262 bmi common_backwardBranch @ backward branch, do periodic checks 1263 beq common_backwardBranch @ (want to use BLE but V is unknown) 1264#if defined(WITH_JIT) 1265 GET_JIT_PROF_TABLE(r0) 1266 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1267 cmp r0,#0 1268 bne common_updateProfile 1269 GET_INST_OPCODE(ip) @ extract opcode from rINST 1270 GOTO_OPCODE(ip) @ jump to next instruction 1271#else 1272 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1273 GET_INST_OPCODE(ip) @ extract opcode from rINST 1274 GOTO_OPCODE(ip) @ jump to next instruction 1275#endif 1276 1277/* ------------------------------ */ 1278 .balign 64 1279.L_OP_SPARSE_SWITCH: /* 0x2c */ 1280/* File: armv5te/OP_SPARSE_SWITCH.S */ 1281/* File: armv5te/OP_PACKED_SWITCH.S */ 1282 /* 1283 * Handle a packed-switch or sparse-switch instruction. In both cases 1284 * we decode it and hand it off to a helper function. 1285 * 1286 * We don't really expect backward branches in a switch statement, but 1287 * they're perfectly legal, so we check for them here. 1288 * 1289 * for: packed-switch, sparse-switch 1290 */ 1291 /* op vAA, +BBBB */ 1292 FETCH(r0, 1) @ r0<- bbbb (lo) 1293 FETCH(r1, 2) @ r1<- BBBB (hi) 1294 mov r3, rINST, lsr #8 @ r3<- AA 1295 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1296 GET_VREG(r1, r3) @ r1<- vAA 1297 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1298 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1299 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1300 bmi common_backwardBranch @ backward branch, do periodic checks 1301 beq common_backwardBranch @ (want to use BLE but V is unknown) 1302#if defined(WITH_JIT) 1303 GET_JIT_PROF_TABLE(r0) 1304 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1305 cmp r0,#0 1306 bne common_updateProfile 1307 GET_INST_OPCODE(ip) @ extract opcode from rINST 1308 GOTO_OPCODE(ip) @ jump to next instruction 1309#else 1310 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1311 GET_INST_OPCODE(ip) @ extract opcode from rINST 1312 GOTO_OPCODE(ip) @ jump to next instruction 1313#endif 1314 1315 1316/* ------------------------------ */ 1317 .balign 64 1318.L_OP_CMPL_FLOAT: /* 0x2d */ 1319/* File: arm-vfp/OP_CMPL_FLOAT.S */ 1320 /* 1321 * Compare two floating-point values. Puts 0, 1, or -1 into the 1322 * destination register based on the results of the comparison. 1323 * 1324 * int compare(x, y) { 1325 * if (x == y) { 1326 * return 0; 1327 * } else if (x > y) { 1328 * return 1; 1329 * } else if (x < y) { 1330 * return -1; 1331 * } else { 1332 * return -1; 1333 * } 1334 * } 1335 */ 1336 /* op vAA, vBB, vCC */ 1337 FETCH(r0, 1) @ r0<- CCBB 1338 mov r9, rINST, lsr #8 @ r9<- AA 1339 and r2, r0, #255 @ r2<- BB 1340 mov r3, r0, lsr #8 @ r3<- CC 1341 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1342 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1343 flds s0, [r2] @ s0<- vBB 1344 flds s1, [r3] @ s1<- vCC 1345 fcmpes s0, s1 @ compare (vBB, vCC) 1346 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1347 mvn r0, #0 @ r0<- -1 (default) 1348 GET_INST_OPCODE(ip) @ extract opcode from rINST 1349 fmstat @ export status flags 1350 movgt r0, #1 @ (greater than) r1<- 1 1351 moveq r0, #0 @ (equal) r1<- 0 1352 b .LOP_CMPL_FLOAT_finish @ argh 1353 1354 1355/* ------------------------------ */ 1356 .balign 64 1357.L_OP_CMPG_FLOAT: /* 0x2e */ 1358/* File: arm-vfp/OP_CMPG_FLOAT.S */ 1359 /* 1360 * Compare two floating-point values. Puts 0, 1, or -1 into the 1361 * destination register based on the results of the comparison. 1362 * 1363 * int compare(x, y) { 1364 * if (x == y) { 1365 * return 0; 1366 * } else if (x < y) { 1367 * return -1; 1368 * } else if (x > y) { 1369 * return 1; 1370 * } else { 1371 * return 1; 1372 * } 1373 * } 1374 */ 1375 /* op vAA, vBB, vCC */ 1376 FETCH(r0, 1) @ r0<- CCBB 1377 mov r9, rINST, lsr #8 @ r9<- AA 1378 and r2, r0, #255 @ r2<- BB 1379 mov r3, r0, lsr #8 @ r3<- CC 1380 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1381 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1382 flds s0, [r2] @ s0<- vBB 1383 flds s1, [r3] @ s1<- vCC 1384 fcmpes s0, s1 @ compare (vBB, vCC) 1385 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1386 mov r0, #1 @ r0<- 1 (default) 1387 GET_INST_OPCODE(ip) @ extract opcode from rINST 1388 fmstat @ export status flags 1389 mvnmi r0, #0 @ (less than) r1<- -1 1390 moveq r0, #0 @ (equal) r1<- 0 1391 b .LOP_CMPG_FLOAT_finish @ argh 1392 1393 1394/* ------------------------------ */ 1395 .balign 64 1396.L_OP_CMPL_DOUBLE: /* 0x2f */ 1397/* File: arm-vfp/OP_CMPL_DOUBLE.S */ 1398 /* 1399 * Compare two floating-point values. Puts 0, 1, or -1 into the 1400 * destination register based on the results of the comparison. 1401 * 1402 * int compare(x, y) { 1403 * if (x == y) { 1404 * return 0; 1405 * } else if (x > y) { 1406 * return 1; 1407 * } else if (x < y) { 1408 * return -1; 1409 * } else { 1410 * return -1; 1411 * } 1412 * } 1413 */ 1414 /* op vAA, vBB, vCC */ 1415 FETCH(r0, 1) @ r0<- CCBB 1416 mov r9, rINST, lsr #8 @ r9<- AA 1417 and r2, r0, #255 @ r2<- BB 1418 mov r3, r0, lsr #8 @ r3<- CC 1419 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1420 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1421 fldd d0, [r2] @ d0<- vBB 1422 fldd d1, [r3] @ d1<- vCC 1423 fcmped d0, d1 @ compare (vBB, vCC) 1424 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1425 mvn r0, #0 @ r0<- -1 (default) 1426 GET_INST_OPCODE(ip) @ extract opcode from rINST 1427 fmstat @ export status flags 1428 movgt r0, #1 @ (greater than) r1<- 1 1429 moveq r0, #0 @ (equal) r1<- 0 1430 b .LOP_CMPL_DOUBLE_finish @ argh 1431 1432 1433/* ------------------------------ */ 1434 .balign 64 1435.L_OP_CMPG_DOUBLE: /* 0x30 */ 1436/* File: arm-vfp/OP_CMPG_DOUBLE.S */ 1437 /* 1438 * Compare two floating-point values. Puts 0, 1, or -1 into the 1439 * destination register based on the results of the comparison. 1440 * 1441 * int compare(x, y) { 1442 * if (x == y) { 1443 * return 0; 1444 * } else if (x < y) { 1445 * return -1; 1446 * } else if (x > y) { 1447 * return 1; 1448 * } else { 1449 * return 1; 1450 * } 1451 * } 1452 */ 1453 /* op vAA, vBB, vCC */ 1454 FETCH(r0, 1) @ r0<- CCBB 1455 mov r9, rINST, lsr #8 @ r9<- AA 1456 and r2, r0, #255 @ r2<- BB 1457 mov r3, r0, lsr #8 @ r3<- CC 1458 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1459 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1460 fldd d0, [r2] @ d0<- vBB 1461 fldd d1, [r3] @ d1<- vCC 1462 fcmped d0, d1 @ compare (vBB, vCC) 1463 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1464 mov r0, #1 @ r0<- 1 (default) 1465 GET_INST_OPCODE(ip) @ extract opcode from rINST 1466 fmstat @ export status flags 1467 mvnmi r0, #0 @ (less than) r1<- -1 1468 moveq r0, #0 @ (equal) r1<- 0 1469 b .LOP_CMPG_DOUBLE_finish @ argh 1470 1471 1472/* ------------------------------ */ 1473 .balign 64 1474.L_OP_CMP_LONG: /* 0x31 */ 1475/* File: armv5te/OP_CMP_LONG.S */ 1476 /* 1477 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1478 * register based on the results of the comparison. 1479 * 1480 * We load the full values with LDM, but in practice many values could 1481 * be resolved by only looking at the high word. This could be made 1482 * faster or slower by splitting the LDM into a pair of LDRs. 1483 * 1484 * If we just wanted to set condition flags, we could do this: 1485 * subs ip, r0, r2 1486 * sbcs ip, r1, r3 1487 * subeqs ip, r0, r2 1488 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1489 * integer value, which we can do with 2 conditional mov/mvn instructions 1490 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1491 * us a constant 5-cycle path plus a branch at the end to the 1492 * instruction epilogue code. The multi-compare approach below needs 1493 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1494 * in the worst case (the 64-bit values are equal). 1495 */ 1496 /* cmp-long vAA, vBB, vCC */ 1497 FETCH(r0, 1) @ r0<- CCBB 1498 mov r9, rINST, lsr #8 @ r9<- AA 1499 and r2, r0, #255 @ r2<- BB 1500 mov r3, r0, lsr #8 @ r3<- CC 1501 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1502 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1503 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1504 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1505 cmp r1, r3 @ compare (vBB+1, vCC+1) 1506 blt .LOP_CMP_LONG_less @ signed compare on high part 1507 bgt .LOP_CMP_LONG_greater 1508 subs r1, r0, r2 @ r1<- r0 - r2 1509 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1510 bne .LOP_CMP_LONG_less 1511 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1512 1513/* ------------------------------ */ 1514 .balign 64 1515.L_OP_IF_EQ: /* 0x32 */ 1516/* File: armv6t2/OP_IF_EQ.S */ 1517/* File: armv6t2/bincmp.S */ 1518 /* 1519 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1520 * fragment that specifies the *reverse* comparison to perform, e.g. 1521 * for "if-le" you would use "gt". 1522 * 1523 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1524 */ 1525 /* if-cmp vA, vB, +CCCC */ 1526 mov r1, rINST, lsr #12 @ r1<- B 1527 ubfx r0, rINST, #8, #4 @ r0<- A 1528 GET_VREG(r3, r1) @ r3<- vB 1529 GET_VREG(r2, r0) @ r2<- vA 1530 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1531 cmp r2, r3 @ compare (vA, vB) 1532 bne 1f @ branch to 1 if comparison failed 1533 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1534 movs r9, r9, asl #1 @ convert to bytes, check sign 1535 bmi common_backwardBranch @ yes, do periodic checks 15361: 1537#if defined(WITH_JIT) 1538 GET_JIT_PROF_TABLE(r0) 1539 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1540 b common_testUpdateProfile 1541#else 1542 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1543 GET_INST_OPCODE(ip) @ extract opcode from rINST 1544 GOTO_OPCODE(ip) @ jump to next instruction 1545#endif 1546 1547 1548/* ------------------------------ */ 1549 .balign 64 1550.L_OP_IF_NE: /* 0x33 */ 1551/* File: armv6t2/OP_IF_NE.S */ 1552/* File: armv6t2/bincmp.S */ 1553 /* 1554 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1555 * fragment that specifies the *reverse* comparison to perform, e.g. 1556 * for "if-le" you would use "gt". 1557 * 1558 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1559 */ 1560 /* if-cmp vA, vB, +CCCC */ 1561 mov r1, rINST, lsr #12 @ r1<- B 1562 ubfx r0, rINST, #8, #4 @ r0<- A 1563 GET_VREG(r3, r1) @ r3<- vB 1564 GET_VREG(r2, r0) @ r2<- vA 1565 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1566 cmp r2, r3 @ compare (vA, vB) 1567 beq 1f @ branch to 1 if comparison failed 1568 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1569 movs r9, r9, asl #1 @ convert to bytes, check sign 1570 bmi common_backwardBranch @ yes, do periodic checks 15711: 1572#if defined(WITH_JIT) 1573 GET_JIT_PROF_TABLE(r0) 1574 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1575 b common_testUpdateProfile 1576#else 1577 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1578 GET_INST_OPCODE(ip) @ extract opcode from rINST 1579 GOTO_OPCODE(ip) @ jump to next instruction 1580#endif 1581 1582 1583/* ------------------------------ */ 1584 .balign 64 1585.L_OP_IF_LT: /* 0x34 */ 1586/* File: armv6t2/OP_IF_LT.S */ 1587/* File: armv6t2/bincmp.S */ 1588 /* 1589 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1590 * fragment that specifies the *reverse* comparison to perform, e.g. 1591 * for "if-le" you would use "gt". 1592 * 1593 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1594 */ 1595 /* if-cmp vA, vB, +CCCC */ 1596 mov r1, rINST, lsr #12 @ r1<- B 1597 ubfx r0, rINST, #8, #4 @ r0<- A 1598 GET_VREG(r3, r1) @ r3<- vB 1599 GET_VREG(r2, r0) @ r2<- vA 1600 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1601 cmp r2, r3 @ compare (vA, vB) 1602 bge 1f @ branch to 1 if comparison failed 1603 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1604 movs r9, r9, asl #1 @ convert to bytes, check sign 1605 bmi common_backwardBranch @ yes, do periodic checks 16061: 1607#if defined(WITH_JIT) 1608 GET_JIT_PROF_TABLE(r0) 1609 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1610 b common_testUpdateProfile 1611#else 1612 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1613 GET_INST_OPCODE(ip) @ extract opcode from rINST 1614 GOTO_OPCODE(ip) @ jump to next instruction 1615#endif 1616 1617 1618/* ------------------------------ */ 1619 .balign 64 1620.L_OP_IF_GE: /* 0x35 */ 1621/* File: armv6t2/OP_IF_GE.S */ 1622/* File: armv6t2/bincmp.S */ 1623 /* 1624 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1625 * fragment that specifies the *reverse* comparison to perform, e.g. 1626 * for "if-le" you would use "gt". 1627 * 1628 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1629 */ 1630 /* if-cmp vA, vB, +CCCC */ 1631 mov r1, rINST, lsr #12 @ r1<- B 1632 ubfx r0, rINST, #8, #4 @ r0<- A 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 blt 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_GT: /* 0x36 */ 1656/* File: armv6t2/OP_IF_GT.S */ 1657/* File: armv6t2/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 r1, rINST, lsr #12 @ r1<- B 1667 ubfx r0, rINST, #8, #4 @ r0<- A 1668 GET_VREG(r3, r1) @ r3<- vB 1669 GET_VREG(r2, r0) @ r2<- vA 1670 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1671 cmp r2, r3 @ compare (vA, vB) 1672 ble 1f @ branch to 1 if comparison failed 1673 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1674 movs r9, r9, asl #1 @ convert to bytes, check sign 1675 bmi common_backwardBranch @ yes, do periodic checks 16761: 1677#if defined(WITH_JIT) 1678 GET_JIT_PROF_TABLE(r0) 1679 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1680 b common_testUpdateProfile 1681#else 1682 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1683 GET_INST_OPCODE(ip) @ extract opcode from rINST 1684 GOTO_OPCODE(ip) @ jump to next instruction 1685#endif 1686 1687 1688/* ------------------------------ */ 1689 .balign 64 1690.L_OP_IF_LE: /* 0x37 */ 1691/* File: armv6t2/OP_IF_LE.S */ 1692/* File: armv6t2/bincmp.S */ 1693 /* 1694 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1695 * fragment that specifies the *reverse* comparison to perform, e.g. 1696 * for "if-le" you would use "gt". 1697 * 1698 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1699 */ 1700 /* if-cmp vA, vB, +CCCC */ 1701 mov r1, rINST, lsr #12 @ r1<- B 1702 ubfx r0, rINST, #8, #4 @ r0<- A 1703 GET_VREG(r3, r1) @ r3<- vB 1704 GET_VREG(r2, r0) @ r2<- vA 1705 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1706 cmp r2, r3 @ compare (vA, vB) 1707 bgt 1f @ branch to 1 if comparison failed 1708 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1709 movs r9, r9, asl #1 @ convert to bytes, check sign 1710 bmi common_backwardBranch @ yes, do periodic checks 17111: 1712#if defined(WITH_JIT) 1713 GET_JIT_PROF_TABLE(r0) 1714 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1715 b common_testUpdateProfile 1716#else 1717 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1718 GET_INST_OPCODE(ip) @ extract opcode from rINST 1719 GOTO_OPCODE(ip) @ jump to next instruction 1720#endif 1721 1722 1723/* ------------------------------ */ 1724 .balign 64 1725.L_OP_IF_EQZ: /* 0x38 */ 1726/* File: armv5te/OP_IF_EQZ.S */ 1727/* File: armv5te/zcmp.S */ 1728 /* 1729 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1730 * fragment that specifies the *reverse* comparison to perform, e.g. 1731 * for "if-le" you would use "gt". 1732 * 1733 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1734 */ 1735 /* if-cmp vAA, +BBBB */ 1736 mov r0, rINST, lsr #8 @ r0<- AA 1737 GET_VREG(r2, r0) @ r2<- vAA 1738 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1739 cmp r2, #0 @ compare (vA, 0) 1740 bne 1f @ branch to 1 if comparison failed 1741 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1742 movs r9, r9, asl #1 @ convert to bytes, check sign 1743 bmi common_backwardBranch @ backward branch, do periodic checks 17441: 1745#if defined(WITH_JIT) 1746 GET_JIT_PROF_TABLE(r0) 1747 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1748 cmp r0,#0 1749 bne common_updateProfile 1750 GET_INST_OPCODE(ip) @ extract opcode from rINST 1751 GOTO_OPCODE(ip) @ jump to next instruction 1752#else 1753 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1754 GET_INST_OPCODE(ip) @ extract opcode from rINST 1755 GOTO_OPCODE(ip) @ jump to next instruction 1756#endif 1757 1758 1759/* ------------------------------ */ 1760 .balign 64 1761.L_OP_IF_NEZ: /* 0x39 */ 1762/* File: armv5te/OP_IF_NEZ.S */ 1763/* File: armv5te/zcmp.S */ 1764 /* 1765 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1766 * fragment that specifies the *reverse* comparison to perform, e.g. 1767 * for "if-le" you would use "gt". 1768 * 1769 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1770 */ 1771 /* if-cmp vAA, +BBBB */ 1772 mov r0, rINST, lsr #8 @ r0<- AA 1773 GET_VREG(r2, r0) @ r2<- vAA 1774 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1775 cmp r2, #0 @ compare (vA, 0) 1776 beq 1f @ branch to 1 if comparison failed 1777 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1778 movs r9, r9, asl #1 @ convert to bytes, check sign 1779 bmi common_backwardBranch @ backward branch, do periodic checks 17801: 1781#if defined(WITH_JIT) 1782 GET_JIT_PROF_TABLE(r0) 1783 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1784 cmp r0,#0 1785 bne common_updateProfile 1786 GET_INST_OPCODE(ip) @ extract opcode from rINST 1787 GOTO_OPCODE(ip) @ jump to next instruction 1788#else 1789 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1790 GET_INST_OPCODE(ip) @ extract opcode from rINST 1791 GOTO_OPCODE(ip) @ jump to next instruction 1792#endif 1793 1794 1795/* ------------------------------ */ 1796 .balign 64 1797.L_OP_IF_LTZ: /* 0x3a */ 1798/* File: armv5te/OP_IF_LTZ.S */ 1799/* File: armv5te/zcmp.S */ 1800 /* 1801 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1802 * fragment that specifies the *reverse* comparison to perform, e.g. 1803 * for "if-le" you would use "gt". 1804 * 1805 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1806 */ 1807 /* if-cmp vAA, +BBBB */ 1808 mov r0, rINST, lsr #8 @ r0<- AA 1809 GET_VREG(r2, r0) @ r2<- vAA 1810 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1811 cmp r2, #0 @ compare (vA, 0) 1812 bge 1f @ branch to 1 if comparison failed 1813 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1814 movs r9, r9, asl #1 @ convert to bytes, check sign 1815 bmi common_backwardBranch @ backward branch, do periodic checks 18161: 1817#if defined(WITH_JIT) 1818 GET_JIT_PROF_TABLE(r0) 1819 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1820 cmp r0,#0 1821 bne common_updateProfile 1822 GET_INST_OPCODE(ip) @ extract opcode from rINST 1823 GOTO_OPCODE(ip) @ jump to next instruction 1824#else 1825 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1826 GET_INST_OPCODE(ip) @ extract opcode from rINST 1827 GOTO_OPCODE(ip) @ jump to next instruction 1828#endif 1829 1830 1831/* ------------------------------ */ 1832 .balign 64 1833.L_OP_IF_GEZ: /* 0x3b */ 1834/* File: armv5te/OP_IF_GEZ.S */ 1835/* File: armv5te/zcmp.S */ 1836 /* 1837 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1838 * fragment that specifies the *reverse* comparison to perform, e.g. 1839 * for "if-le" you would use "gt". 1840 * 1841 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1842 */ 1843 /* if-cmp vAA, +BBBB */ 1844 mov r0, rINST, lsr #8 @ r0<- AA 1845 GET_VREG(r2, r0) @ r2<- vAA 1846 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1847 cmp r2, #0 @ compare (vA, 0) 1848 blt 1f @ branch to 1 if comparison failed 1849 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1850 movs r9, r9, asl #1 @ convert to bytes, check sign 1851 bmi common_backwardBranch @ backward branch, do periodic checks 18521: 1853#if defined(WITH_JIT) 1854 GET_JIT_PROF_TABLE(r0) 1855 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1856 cmp r0,#0 1857 bne common_updateProfile 1858 GET_INST_OPCODE(ip) @ extract opcode from rINST 1859 GOTO_OPCODE(ip) @ jump to next instruction 1860#else 1861 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1862 GET_INST_OPCODE(ip) @ extract opcode from rINST 1863 GOTO_OPCODE(ip) @ jump to next instruction 1864#endif 1865 1866 1867/* ------------------------------ */ 1868 .balign 64 1869.L_OP_IF_GTZ: /* 0x3c */ 1870/* File: armv5te/OP_IF_GTZ.S */ 1871/* File: armv5te/zcmp.S */ 1872 /* 1873 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1874 * fragment that specifies the *reverse* comparison to perform, e.g. 1875 * for "if-le" you would use "gt". 1876 * 1877 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1878 */ 1879 /* if-cmp vAA, +BBBB */ 1880 mov r0, rINST, lsr #8 @ r0<- AA 1881 GET_VREG(r2, r0) @ r2<- vAA 1882 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1883 cmp r2, #0 @ compare (vA, 0) 1884 ble 1f @ branch to 1 if comparison failed 1885 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1886 movs r9, r9, asl #1 @ convert to bytes, check sign 1887 bmi common_backwardBranch @ backward branch, do periodic checks 18881: 1889#if defined(WITH_JIT) 1890 GET_JIT_PROF_TABLE(r0) 1891 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1892 cmp r0,#0 1893 bne common_updateProfile 1894 GET_INST_OPCODE(ip) @ extract opcode from rINST 1895 GOTO_OPCODE(ip) @ jump to next instruction 1896#else 1897 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1898 GET_INST_OPCODE(ip) @ extract opcode from rINST 1899 GOTO_OPCODE(ip) @ jump to next instruction 1900#endif 1901 1902 1903/* ------------------------------ */ 1904 .balign 64 1905.L_OP_IF_LEZ: /* 0x3d */ 1906/* File: armv5te/OP_IF_LEZ.S */ 1907/* File: armv5te/zcmp.S */ 1908 /* 1909 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1910 * fragment that specifies the *reverse* comparison to perform, e.g. 1911 * for "if-le" you would use "gt". 1912 * 1913 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1914 */ 1915 /* if-cmp vAA, +BBBB */ 1916 mov r0, rINST, lsr #8 @ r0<- AA 1917 GET_VREG(r2, r0) @ r2<- vAA 1918 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1919 cmp r2, #0 @ compare (vA, 0) 1920 bgt 1f @ branch to 1 if comparison failed 1921 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1922 movs r9, r9, asl #1 @ convert to bytes, check sign 1923 bmi common_backwardBranch @ backward branch, do periodic checks 19241: 1925#if defined(WITH_JIT) 1926 GET_JIT_PROF_TABLE(r0) 1927 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1928 cmp r0,#0 1929 bne common_updateProfile 1930 GET_INST_OPCODE(ip) @ extract opcode from rINST 1931 GOTO_OPCODE(ip) @ jump to next instruction 1932#else 1933 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1934 GET_INST_OPCODE(ip) @ extract opcode from rINST 1935 GOTO_OPCODE(ip) @ jump to next instruction 1936#endif 1937 1938 1939/* ------------------------------ */ 1940 .balign 64 1941.L_OP_UNUSED_3E: /* 0x3e */ 1942/* File: armv5te/OP_UNUSED_3E.S */ 1943/* File: armv5te/unused.S */ 1944 bl common_abort 1945 1946 1947/* ------------------------------ */ 1948 .balign 64 1949.L_OP_UNUSED_3F: /* 0x3f */ 1950/* File: armv5te/OP_UNUSED_3F.S */ 1951/* File: armv5te/unused.S */ 1952 bl common_abort 1953 1954 1955/* ------------------------------ */ 1956 .balign 64 1957.L_OP_UNUSED_40: /* 0x40 */ 1958/* File: armv5te/OP_UNUSED_40.S */ 1959/* File: armv5te/unused.S */ 1960 bl common_abort 1961 1962 1963/* ------------------------------ */ 1964 .balign 64 1965.L_OP_UNUSED_41: /* 0x41 */ 1966/* File: armv5te/OP_UNUSED_41.S */ 1967/* File: armv5te/unused.S */ 1968 bl common_abort 1969 1970 1971/* ------------------------------ */ 1972 .balign 64 1973.L_OP_UNUSED_42: /* 0x42 */ 1974/* File: armv5te/OP_UNUSED_42.S */ 1975/* File: armv5te/unused.S */ 1976 bl common_abort 1977 1978 1979/* ------------------------------ */ 1980 .balign 64 1981.L_OP_UNUSED_43: /* 0x43 */ 1982/* File: armv5te/OP_UNUSED_43.S */ 1983/* File: armv5te/unused.S */ 1984 bl common_abort 1985 1986 1987/* ------------------------------ */ 1988 .balign 64 1989.L_OP_AGET: /* 0x44 */ 1990/* File: armv5te/OP_AGET.S */ 1991 /* 1992 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1993 * 1994 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1995 * instructions. We use a pair of FETCH_Bs instead. 1996 * 1997 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1998 */ 1999 /* op vAA, vBB, vCC */ 2000 FETCH_B(r2, 1, 0) @ r2<- BB 2001 mov r9, rINST, lsr #8 @ r9<- AA 2002 FETCH_B(r3, 1, 1) @ r3<- CC 2003 GET_VREG(r0, r2) @ r0<- vBB (array object) 2004 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2005 cmp r0, #0 @ null array object? 2006 beq common_errNullObject @ yes, bail 2007 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2008 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2009 cmp r1, r3 @ compare unsigned index, length 2010 bcs common_errArrayIndex @ index >= length, bail 2011 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2012 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2013 GET_INST_OPCODE(ip) @ extract opcode from rINST 2014 SET_VREG(r2, r9) @ vAA<- r2 2015 GOTO_OPCODE(ip) @ jump to next instruction 2016 2017/* ------------------------------ */ 2018 .balign 64 2019.L_OP_AGET_WIDE: /* 0x45 */ 2020/* File: armv5te/OP_AGET_WIDE.S */ 2021 /* 2022 * Array get, 64 bits. vAA <- vBB[vCC]. 2023 * 2024 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 2025 */ 2026 /* aget-wide vAA, vBB, vCC */ 2027 FETCH(r0, 1) @ r0<- CCBB 2028 mov r9, rINST, lsr #8 @ r9<- AA 2029 and r2, r0, #255 @ r2<- BB 2030 mov r3, r0, lsr #8 @ r3<- CC 2031 GET_VREG(r0, r2) @ r0<- vBB (array object) 2032 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2033 cmp r0, #0 @ null array object? 2034 beq common_errNullObject @ yes, bail 2035 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2036 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2037 cmp r1, r3 @ compare unsigned index, length 2038 bcc .LOP_AGET_WIDE_finish @ okay, continue below 2039 b common_errArrayIndex @ index >= length, bail 2040 @ May want to swap the order of these two branches depending on how the 2041 @ branch prediction (if any) handles conditional forward branches vs. 2042 @ unconditional forward branches. 2043 2044/* ------------------------------ */ 2045 .balign 64 2046.L_OP_AGET_OBJECT: /* 0x46 */ 2047/* File: armv5te/OP_AGET_OBJECT.S */ 2048/* File: armv5te/OP_AGET.S */ 2049 /* 2050 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2051 * 2052 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2053 * instructions. We use a pair of FETCH_Bs instead. 2054 * 2055 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2056 */ 2057 /* op vAA, vBB, vCC */ 2058 FETCH_B(r2, 1, 0) @ r2<- BB 2059 mov r9, rINST, lsr #8 @ r9<- AA 2060 FETCH_B(r3, 1, 1) @ r3<- CC 2061 GET_VREG(r0, r2) @ r0<- vBB (array object) 2062 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2063 cmp r0, #0 @ null array object? 2064 beq common_errNullObject @ yes, bail 2065 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2066 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2067 cmp r1, r3 @ compare unsigned index, length 2068 bcs common_errArrayIndex @ index >= length, bail 2069 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2070 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2071 GET_INST_OPCODE(ip) @ extract opcode from rINST 2072 SET_VREG(r2, r9) @ vAA<- r2 2073 GOTO_OPCODE(ip) @ jump to next instruction 2074 2075 2076/* ------------------------------ */ 2077 .balign 64 2078.L_OP_AGET_BOOLEAN: /* 0x47 */ 2079/* File: armv5te/OP_AGET_BOOLEAN.S */ 2080/* File: armv5te/OP_AGET.S */ 2081 /* 2082 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2083 * 2084 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2085 * instructions. We use a pair of FETCH_Bs instead. 2086 * 2087 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2088 */ 2089 /* op vAA, vBB, vCC */ 2090 FETCH_B(r2, 1, 0) @ r2<- BB 2091 mov r9, rINST, lsr #8 @ r9<- AA 2092 FETCH_B(r3, 1, 1) @ r3<- CC 2093 GET_VREG(r0, r2) @ r0<- vBB (array object) 2094 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2095 cmp r0, #0 @ null array object? 2096 beq common_errNullObject @ yes, bail 2097 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2098 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2099 cmp r1, r3 @ compare unsigned index, length 2100 bcs common_errArrayIndex @ index >= length, bail 2101 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2102 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2103 GET_INST_OPCODE(ip) @ extract opcode from rINST 2104 SET_VREG(r2, r9) @ vAA<- r2 2105 GOTO_OPCODE(ip) @ jump to next instruction 2106 2107 2108/* ------------------------------ */ 2109 .balign 64 2110.L_OP_AGET_BYTE: /* 0x48 */ 2111/* File: armv5te/OP_AGET_BYTE.S */ 2112/* File: armv5te/OP_AGET.S */ 2113 /* 2114 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2115 * 2116 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2117 * instructions. We use a pair of FETCH_Bs instead. 2118 * 2119 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2120 */ 2121 /* op vAA, vBB, vCC */ 2122 FETCH_B(r2, 1, 0) @ r2<- BB 2123 mov r9, rINST, lsr #8 @ r9<- AA 2124 FETCH_B(r3, 1, 1) @ r3<- CC 2125 GET_VREG(r0, r2) @ r0<- vBB (array object) 2126 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2127 cmp r0, #0 @ null array object? 2128 beq common_errNullObject @ yes, bail 2129 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2130 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2131 cmp r1, r3 @ compare unsigned index, length 2132 bcs common_errArrayIndex @ index >= length, bail 2133 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2134 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2135 GET_INST_OPCODE(ip) @ extract opcode from rINST 2136 SET_VREG(r2, r9) @ vAA<- r2 2137 GOTO_OPCODE(ip) @ jump to next instruction 2138 2139 2140/* ------------------------------ */ 2141 .balign 64 2142.L_OP_AGET_CHAR: /* 0x49 */ 2143/* File: armv5te/OP_AGET_CHAR.S */ 2144/* File: armv5te/OP_AGET.S */ 2145 /* 2146 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2147 * 2148 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2149 * instructions. We use a pair of FETCH_Bs instead. 2150 * 2151 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2152 */ 2153 /* op vAA, vBB, vCC */ 2154 FETCH_B(r2, 1, 0) @ r2<- BB 2155 mov r9, rINST, lsr #8 @ r9<- AA 2156 FETCH_B(r3, 1, 1) @ r3<- CC 2157 GET_VREG(r0, r2) @ r0<- vBB (array object) 2158 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2159 cmp r0, #0 @ null array object? 2160 beq common_errNullObject @ yes, bail 2161 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2162 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2163 cmp r1, r3 @ compare unsigned index, length 2164 bcs common_errArrayIndex @ index >= length, bail 2165 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2166 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2167 GET_INST_OPCODE(ip) @ extract opcode from rINST 2168 SET_VREG(r2, r9) @ vAA<- r2 2169 GOTO_OPCODE(ip) @ jump to next instruction 2170 2171 2172/* ------------------------------ */ 2173 .balign 64 2174.L_OP_AGET_SHORT: /* 0x4a */ 2175/* File: armv5te/OP_AGET_SHORT.S */ 2176/* File: armv5te/OP_AGET.S */ 2177 /* 2178 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2179 * 2180 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2181 * instructions. We use a pair of FETCH_Bs instead. 2182 * 2183 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2184 */ 2185 /* op vAA, vBB, vCC */ 2186 FETCH_B(r2, 1, 0) @ r2<- BB 2187 mov r9, rINST, lsr #8 @ r9<- AA 2188 FETCH_B(r3, 1, 1) @ r3<- CC 2189 GET_VREG(r0, r2) @ r0<- vBB (array object) 2190 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2191 cmp r0, #0 @ null array object? 2192 beq common_errNullObject @ yes, bail 2193 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2194 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2195 cmp r1, r3 @ compare unsigned index, length 2196 bcs common_errArrayIndex @ index >= length, bail 2197 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2198 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2199 GET_INST_OPCODE(ip) @ extract opcode from rINST 2200 SET_VREG(r2, r9) @ vAA<- r2 2201 GOTO_OPCODE(ip) @ jump to next instruction 2202 2203 2204/* ------------------------------ */ 2205 .balign 64 2206.L_OP_APUT: /* 0x4b */ 2207/* File: armv5te/OP_APUT.S */ 2208 /* 2209 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2210 * 2211 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2212 * instructions. We use a pair of FETCH_Bs instead. 2213 * 2214 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2215 */ 2216 /* op vAA, vBB, vCC */ 2217 FETCH_B(r2, 1, 0) @ r2<- BB 2218 mov r9, rINST, lsr #8 @ r9<- AA 2219 FETCH_B(r3, 1, 1) @ r3<- CC 2220 GET_VREG(r0, r2) @ r0<- vBB (array object) 2221 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2222 cmp r0, #0 @ null array object? 2223 beq common_errNullObject @ yes, bail 2224 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2225 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2226 cmp r1, r3 @ compare unsigned index, length 2227 bcs common_errArrayIndex @ index >= length, bail 2228 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2229 GET_VREG(r2, r9) @ r2<- vAA 2230 GET_INST_OPCODE(ip) @ extract opcode from rINST 2231 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2232 GOTO_OPCODE(ip) @ jump to next instruction 2233 2234/* ------------------------------ */ 2235 .balign 64 2236.L_OP_APUT_WIDE: /* 0x4c */ 2237/* File: armv5te/OP_APUT_WIDE.S */ 2238 /* 2239 * Array put, 64 bits. vBB[vCC] <- vAA. 2240 * 2241 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 2242 */ 2243 /* aput-wide vAA, vBB, vCC */ 2244 FETCH(r0, 1) @ r0<- CCBB 2245 mov r9, rINST, lsr #8 @ r9<- AA 2246 and r2, r0, #255 @ r2<- BB 2247 mov r3, r0, lsr #8 @ r3<- CC 2248 GET_VREG(r0, r2) @ r0<- vBB (array object) 2249 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2250 cmp r0, #0 @ null array object? 2251 beq common_errNullObject @ yes, bail 2252 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2253 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2254 cmp r1, r3 @ compare unsigned index, length 2255 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2256 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2257 b common_errArrayIndex @ index >= length, bail 2258 @ May want to swap the order of these two branches depending on how the 2259 @ branch prediction (if any) handles conditional forward branches vs. 2260 @ unconditional forward branches. 2261 2262/* ------------------------------ */ 2263 .balign 64 2264.L_OP_APUT_OBJECT: /* 0x4d */ 2265/* File: armv5te/OP_APUT_OBJECT.S */ 2266 /* 2267 * Store an object into an array. vBB[vCC] <- vAA. 2268 * 2269 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2270 * instructions. We use a pair of FETCH_Bs instead. 2271 */ 2272 /* op vAA, vBB, vCC */ 2273 FETCH(r0, 1) @ r0<- CCBB 2274 mov r9, rINST, lsr #8 @ r9<- AA 2275 and r2, r0, #255 @ r2<- BB 2276 mov r3, r0, lsr #8 @ r3<- CC 2277 GET_VREG(rINST, r2) @ rINST<- vBB (array object) 2278 GET_VREG(r0, r3) @ r0<- vCC (requested index) 2279 cmp rINST, #0 @ null array object? 2280 GET_VREG(r9, r9) @ r9<- vAA 2281 beq common_errNullObject @ yes, bail 2282 ldr r3, [rINST, #offArrayObject_length] @ r3<- arrayObj->length 2283 add r10, rINST, r0, lsl #2 @ r10<- arrayObj + index*width 2284 cmp r0, r3 @ compare unsigned index, length 2285 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2286 b common_errArrayIndex @ index >= length, bail 2287 2288 2289/* ------------------------------ */ 2290 .balign 64 2291.L_OP_APUT_BOOLEAN: /* 0x4e */ 2292/* File: armv5te/OP_APUT_BOOLEAN.S */ 2293/* File: armv5te/OP_APUT.S */ 2294 /* 2295 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2296 * 2297 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2298 * instructions. We use a pair of FETCH_Bs instead. 2299 * 2300 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2301 */ 2302 /* op vAA, vBB, vCC */ 2303 FETCH_B(r2, 1, 0) @ r2<- BB 2304 mov r9, rINST, lsr #8 @ r9<- AA 2305 FETCH_B(r3, 1, 1) @ r3<- CC 2306 GET_VREG(r0, r2) @ r0<- vBB (array object) 2307 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2308 cmp r0, #0 @ null array object? 2309 beq common_errNullObject @ yes, bail 2310 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2311 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2312 cmp r1, r3 @ compare unsigned index, length 2313 bcs common_errArrayIndex @ index >= length, bail 2314 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2315 GET_VREG(r2, r9) @ r2<- vAA 2316 GET_INST_OPCODE(ip) @ extract opcode from rINST 2317 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2318 GOTO_OPCODE(ip) @ jump to next instruction 2319 2320 2321/* ------------------------------ */ 2322 .balign 64 2323.L_OP_APUT_BYTE: /* 0x4f */ 2324/* File: armv5te/OP_APUT_BYTE.S */ 2325/* File: armv5te/OP_APUT.S */ 2326 /* 2327 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2328 * 2329 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2330 * instructions. We use a pair of FETCH_Bs instead. 2331 * 2332 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2333 */ 2334 /* op vAA, vBB, vCC */ 2335 FETCH_B(r2, 1, 0) @ r2<- BB 2336 mov r9, rINST, lsr #8 @ r9<- AA 2337 FETCH_B(r3, 1, 1) @ r3<- CC 2338 GET_VREG(r0, r2) @ r0<- vBB (array object) 2339 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2340 cmp r0, #0 @ null array object? 2341 beq common_errNullObject @ yes, bail 2342 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2343 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2344 cmp r1, r3 @ compare unsigned index, length 2345 bcs common_errArrayIndex @ index >= length, bail 2346 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2347 GET_VREG(r2, r9) @ r2<- vAA 2348 GET_INST_OPCODE(ip) @ extract opcode from rINST 2349 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2350 GOTO_OPCODE(ip) @ jump to next instruction 2351 2352 2353/* ------------------------------ */ 2354 .balign 64 2355.L_OP_APUT_CHAR: /* 0x50 */ 2356/* File: armv5te/OP_APUT_CHAR.S */ 2357/* File: armv5te/OP_APUT.S */ 2358 /* 2359 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2360 * 2361 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2362 * instructions. We use a pair of FETCH_Bs instead. 2363 * 2364 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2365 */ 2366 /* op vAA, vBB, vCC */ 2367 FETCH_B(r2, 1, 0) @ r2<- BB 2368 mov r9, rINST, lsr #8 @ r9<- AA 2369 FETCH_B(r3, 1, 1) @ r3<- CC 2370 GET_VREG(r0, r2) @ r0<- vBB (array object) 2371 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2372 cmp r0, #0 @ null array object? 2373 beq common_errNullObject @ yes, bail 2374 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2375 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2376 cmp r1, r3 @ compare unsigned index, length 2377 bcs common_errArrayIndex @ index >= length, bail 2378 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2379 GET_VREG(r2, r9) @ r2<- vAA 2380 GET_INST_OPCODE(ip) @ extract opcode from rINST 2381 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2382 GOTO_OPCODE(ip) @ jump to next instruction 2383 2384 2385/* ------------------------------ */ 2386 .balign 64 2387.L_OP_APUT_SHORT: /* 0x51 */ 2388/* File: armv5te/OP_APUT_SHORT.S */ 2389/* File: armv5te/OP_APUT.S */ 2390 /* 2391 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2392 * 2393 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2394 * instructions. We use a pair of FETCH_Bs instead. 2395 * 2396 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2397 */ 2398 /* op vAA, vBB, vCC */ 2399 FETCH_B(r2, 1, 0) @ r2<- BB 2400 mov r9, rINST, lsr #8 @ r9<- AA 2401 FETCH_B(r3, 1, 1) @ r3<- CC 2402 GET_VREG(r0, r2) @ r0<- vBB (array object) 2403 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2404 cmp r0, #0 @ null array object? 2405 beq common_errNullObject @ yes, bail 2406 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2407 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2408 cmp r1, r3 @ compare unsigned index, length 2409 bcs common_errArrayIndex @ index >= length, bail 2410 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2411 GET_VREG(r2, r9) @ r2<- vAA 2412 GET_INST_OPCODE(ip) @ extract opcode from rINST 2413 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2414 GOTO_OPCODE(ip) @ jump to next instruction 2415 2416 2417/* ------------------------------ */ 2418 .balign 64 2419.L_OP_IGET: /* 0x52 */ 2420/* File: armv6t2/OP_IGET.S */ 2421 /* 2422 * General 32-bit instance field get. 2423 * 2424 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2425 */ 2426 /* op vA, vB, field@CCCC */ 2427 mov r0, rINST, lsr #12 @ r0<- B 2428 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2429 FETCH(r1, 1) @ r1<- field ref CCCC 2430 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2431 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2432 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2433 cmp r0, #0 @ is resolved entry null? 2434 bne .LOP_IGET_finish @ no, already resolved 24358: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2436 EXPORT_PC() @ resolve() could throw 2437 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2438 bl dvmResolveInstField @ r0<- resolved InstField ptr 2439 cmp r0, #0 2440 bne .LOP_IGET_finish 2441 b common_exceptionThrown 2442 2443/* ------------------------------ */ 2444 .balign 64 2445.L_OP_IGET_WIDE: /* 0x53 */ 2446/* File: armv6t2/OP_IGET_WIDE.S */ 2447 /* 2448 * Wide 32-bit instance field get. 2449 */ 2450 /* iget-wide vA, vB, field@CCCC */ 2451 mov r0, rINST, lsr #12 @ r0<- B 2452 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2453 FETCH(r1, 1) @ r1<- field ref CCCC 2454 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2455 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2456 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2457 cmp r0, #0 @ is resolved entry null? 2458 bne .LOP_IGET_WIDE_finish @ no, already resolved 24598: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2460 EXPORT_PC() @ resolve() could throw 2461 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2462 bl dvmResolveInstField @ r0<- resolved InstField ptr 2463 cmp r0, #0 2464 bne .LOP_IGET_WIDE_finish 2465 b common_exceptionThrown 2466 2467/* ------------------------------ */ 2468 .balign 64 2469.L_OP_IGET_OBJECT: /* 0x54 */ 2470/* File: armv5te/OP_IGET_OBJECT.S */ 2471/* File: armv5te/OP_IGET.S */ 2472 /* 2473 * General 32-bit instance field get. 2474 * 2475 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2476 */ 2477 /* op vA, vB, field@CCCC */ 2478 mov r0, rINST, lsr #12 @ r0<- B 2479 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2480 FETCH(r1, 1) @ r1<- field ref CCCC 2481 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2482 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2483 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2484 cmp r0, #0 @ is resolved entry null? 2485 bne .LOP_IGET_OBJECT_finish @ no, already resolved 24868: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2487 EXPORT_PC() @ resolve() could throw 2488 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2489 bl dvmResolveInstField @ r0<- resolved InstField ptr 2490 cmp r0, #0 2491 bne .LOP_IGET_OBJECT_finish 2492 b common_exceptionThrown 2493 2494 2495/* ------------------------------ */ 2496 .balign 64 2497.L_OP_IGET_BOOLEAN: /* 0x55 */ 2498/* File: armv5te/OP_IGET_BOOLEAN.S */ 2499@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2500/* File: armv5te/OP_IGET.S */ 2501 /* 2502 * General 32-bit instance field get. 2503 * 2504 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2505 */ 2506 /* op vA, vB, field@CCCC */ 2507 mov r0, rINST, lsr #12 @ r0<- B 2508 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2509 FETCH(r1, 1) @ r1<- field ref CCCC 2510 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2511 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2512 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2513 cmp r0, #0 @ is resolved entry null? 2514 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 25158: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2516 EXPORT_PC() @ resolve() could throw 2517 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2518 bl dvmResolveInstField @ r0<- resolved InstField ptr 2519 cmp r0, #0 2520 bne .LOP_IGET_BOOLEAN_finish 2521 b common_exceptionThrown 2522 2523 2524/* ------------------------------ */ 2525 .balign 64 2526.L_OP_IGET_BYTE: /* 0x56 */ 2527/* File: armv5te/OP_IGET_BYTE.S */ 2528@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2529/* File: armv5te/OP_IGET.S */ 2530 /* 2531 * General 32-bit instance field get. 2532 * 2533 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2534 */ 2535 /* op vA, vB, field@CCCC */ 2536 mov r0, rINST, lsr #12 @ r0<- B 2537 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2538 FETCH(r1, 1) @ r1<- field ref CCCC 2539 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2540 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2541 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2542 cmp r0, #0 @ is resolved entry null? 2543 bne .LOP_IGET_BYTE_finish @ no, already resolved 25448: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2545 EXPORT_PC() @ resolve() could throw 2546 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2547 bl dvmResolveInstField @ r0<- resolved InstField ptr 2548 cmp r0, #0 2549 bne .LOP_IGET_BYTE_finish 2550 b common_exceptionThrown 2551 2552 2553/* ------------------------------ */ 2554 .balign 64 2555.L_OP_IGET_CHAR: /* 0x57 */ 2556/* File: armv5te/OP_IGET_CHAR.S */ 2557@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2558/* File: armv5te/OP_IGET.S */ 2559 /* 2560 * General 32-bit instance field get. 2561 * 2562 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2563 */ 2564 /* op vA, vB, field@CCCC */ 2565 mov r0, rINST, lsr #12 @ r0<- B 2566 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2567 FETCH(r1, 1) @ r1<- field ref CCCC 2568 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2569 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2570 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2571 cmp r0, #0 @ is resolved entry null? 2572 bne .LOP_IGET_CHAR_finish @ no, already resolved 25738: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2574 EXPORT_PC() @ resolve() could throw 2575 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2576 bl dvmResolveInstField @ r0<- resolved InstField ptr 2577 cmp r0, #0 2578 bne .LOP_IGET_CHAR_finish 2579 b common_exceptionThrown 2580 2581 2582/* ------------------------------ */ 2583 .balign 64 2584.L_OP_IGET_SHORT: /* 0x58 */ 2585/* File: armv5te/OP_IGET_SHORT.S */ 2586@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2587/* File: armv5te/OP_IGET.S */ 2588 /* 2589 * General 32-bit instance field get. 2590 * 2591 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2592 */ 2593 /* op vA, vB, field@CCCC */ 2594 mov r0, rINST, lsr #12 @ r0<- B 2595 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2596 FETCH(r1, 1) @ r1<- field ref CCCC 2597 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2598 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2599 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2600 cmp r0, #0 @ is resolved entry null? 2601 bne .LOP_IGET_SHORT_finish @ no, already resolved 26028: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2603 EXPORT_PC() @ resolve() could throw 2604 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2605 bl dvmResolveInstField @ r0<- resolved InstField ptr 2606 cmp r0, #0 2607 bne .LOP_IGET_SHORT_finish 2608 b common_exceptionThrown 2609 2610 2611/* ------------------------------ */ 2612 .balign 64 2613.L_OP_IPUT: /* 0x59 */ 2614/* File: armv6t2/OP_IPUT.S */ 2615 /* 2616 * General 32-bit instance field put. 2617 * 2618 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2619 */ 2620 /* op vA, vB, field@CCCC */ 2621 mov r0, rINST, lsr #12 @ r0<- B 2622 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2623 FETCH(r1, 1) @ r1<- field ref CCCC 2624 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2625 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2626 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2627 cmp r0, #0 @ is resolved entry null? 2628 bne .LOP_IPUT_finish @ no, already resolved 26298: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2630 EXPORT_PC() @ resolve() could throw 2631 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2632 bl dvmResolveInstField @ r0<- resolved InstField ptr 2633 cmp r0, #0 @ success? 2634 bne .LOP_IPUT_finish @ yes, finish up 2635 b common_exceptionThrown 2636 2637/* ------------------------------ */ 2638 .balign 64 2639.L_OP_IPUT_WIDE: /* 0x5a */ 2640/* File: armv6t2/OP_IPUT_WIDE.S */ 2641 /* iput-wide vA, vB, field@CCCC */ 2642 mov r0, rINST, lsr #12 @ r0<- B 2643 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2644 FETCH(r1, 1) @ r1<- field ref CCCC 2645 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2646 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2647 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2648 cmp r0, #0 @ is resolved entry null? 2649 bne .LOP_IPUT_WIDE_finish @ no, already resolved 26508: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2651 EXPORT_PC() @ resolve() could throw 2652 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2653 bl dvmResolveInstField @ r0<- resolved InstField ptr 2654 cmp r0, #0 @ success? 2655 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2656 b common_exceptionThrown 2657 2658/* ------------------------------ */ 2659 .balign 64 2660.L_OP_IPUT_OBJECT: /* 0x5b */ 2661/* File: armv5te/OP_IPUT_OBJECT.S */ 2662 /* 2663 * 32-bit instance field put. 2664 * 2665 * for: iput-object, iput-object-volatile 2666 */ 2667 /* op vA, vB, field@CCCC */ 2668 mov r0, rINST, lsr #12 @ r0<- B 2669 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2670 FETCH(r1, 1) @ r1<- field ref CCCC 2671 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2672 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2673 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2674 cmp r0, #0 @ is resolved entry null? 2675 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 26768: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2677 EXPORT_PC() @ resolve() could throw 2678 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2679 bl dvmResolveInstField @ r0<- resolved InstField ptr 2680 cmp r0, #0 @ success? 2681 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2682 b common_exceptionThrown 2683 2684/* ------------------------------ */ 2685 .balign 64 2686.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2687/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2688@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2689/* File: armv5te/OP_IPUT.S */ 2690 /* 2691 * General 32-bit instance field put. 2692 * 2693 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2694 */ 2695 /* op vA, vB, field@CCCC */ 2696 mov r0, rINST, lsr #12 @ r0<- B 2697 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2698 FETCH(r1, 1) @ r1<- field ref CCCC 2699 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2700 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2701 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2702 cmp r0, #0 @ is resolved entry null? 2703 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 27048: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2705 EXPORT_PC() @ resolve() could throw 2706 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2707 bl dvmResolveInstField @ r0<- resolved InstField ptr 2708 cmp r0, #0 @ success? 2709 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2710 b common_exceptionThrown 2711 2712 2713/* ------------------------------ */ 2714 .balign 64 2715.L_OP_IPUT_BYTE: /* 0x5d */ 2716/* File: armv5te/OP_IPUT_BYTE.S */ 2717@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2718/* File: armv5te/OP_IPUT.S */ 2719 /* 2720 * General 32-bit instance field put. 2721 * 2722 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2723 */ 2724 /* op vA, vB, field@CCCC */ 2725 mov r0, rINST, lsr #12 @ r0<- B 2726 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2727 FETCH(r1, 1) @ r1<- field ref CCCC 2728 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2729 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2730 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2731 cmp r0, #0 @ is resolved entry null? 2732 bne .LOP_IPUT_BYTE_finish @ no, already resolved 27338: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2734 EXPORT_PC() @ resolve() could throw 2735 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2736 bl dvmResolveInstField @ r0<- resolved InstField ptr 2737 cmp r0, #0 @ success? 2738 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2739 b common_exceptionThrown 2740 2741 2742/* ------------------------------ */ 2743 .balign 64 2744.L_OP_IPUT_CHAR: /* 0x5e */ 2745/* File: armv5te/OP_IPUT_CHAR.S */ 2746@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2747/* File: armv5te/OP_IPUT.S */ 2748 /* 2749 * General 32-bit instance field put. 2750 * 2751 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2752 */ 2753 /* op vA, vB, field@CCCC */ 2754 mov r0, rINST, lsr #12 @ r0<- B 2755 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2756 FETCH(r1, 1) @ r1<- field ref CCCC 2757 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2758 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2759 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2760 cmp r0, #0 @ is resolved entry null? 2761 bne .LOP_IPUT_CHAR_finish @ no, already resolved 27628: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2763 EXPORT_PC() @ resolve() could throw 2764 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2765 bl dvmResolveInstField @ r0<- resolved InstField ptr 2766 cmp r0, #0 @ success? 2767 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2768 b common_exceptionThrown 2769 2770 2771/* ------------------------------ */ 2772 .balign 64 2773.L_OP_IPUT_SHORT: /* 0x5f */ 2774/* File: armv5te/OP_IPUT_SHORT.S */ 2775@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2776/* File: armv5te/OP_IPUT.S */ 2777 /* 2778 * General 32-bit instance field put. 2779 * 2780 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2781 */ 2782 /* op vA, vB, field@CCCC */ 2783 mov r0, rINST, lsr #12 @ r0<- B 2784 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2785 FETCH(r1, 1) @ r1<- field ref CCCC 2786 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2787 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2788 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2789 cmp r0, #0 @ is resolved entry null? 2790 bne .LOP_IPUT_SHORT_finish @ no, already resolved 27918: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2792 EXPORT_PC() @ resolve() could throw 2793 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2794 bl dvmResolveInstField @ r0<- resolved InstField ptr 2795 cmp r0, #0 @ success? 2796 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2797 b common_exceptionThrown 2798 2799 2800/* ------------------------------ */ 2801 .balign 64 2802.L_OP_SGET: /* 0x60 */ 2803/* File: armv5te/OP_SGET.S */ 2804 /* 2805 * General 32-bit SGET handler. 2806 * 2807 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2808 */ 2809 /* op vAA, field@BBBB */ 2810 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2811 FETCH(r1, 1) @ r1<- field ref BBBB 2812 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2813 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2814 cmp r0, #0 @ is resolved entry null? 2815 beq .LOP_SGET_resolve @ yes, do resolve 2816.LOP_SGET_finish: @ field ptr in r0 2817 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2818 @ no-op @ acquiring load 2819 mov r2, rINST, lsr #8 @ r2<- AA 2820 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2821 SET_VREG(r1, r2) @ fp[AA]<- r1 2822 GET_INST_OPCODE(ip) @ extract opcode from rINST 2823 GOTO_OPCODE(ip) @ jump to next instruction 2824 2825/* ------------------------------ */ 2826 .balign 64 2827.L_OP_SGET_WIDE: /* 0x61 */ 2828/* File: armv5te/OP_SGET_WIDE.S */ 2829 /* 2830 * 64-bit SGET handler. 2831 */ 2832 /* sget-wide vAA, field@BBBB */ 2833 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2834 FETCH(r1, 1) @ r1<- field ref BBBB 2835 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2836 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2837 cmp r0, #0 @ is resolved entry null? 2838 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2839.LOP_SGET_WIDE_finish: 2840 mov r9, rINST, lsr #8 @ r9<- AA 2841 .if 0 2842 add r0, r0, #offStaticField_value @ r0<- pointer to data 2843 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 2844 .else 2845 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 2846 .endif 2847 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2848 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2849 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 2850 GET_INST_OPCODE(ip) @ extract opcode from rINST 2851 GOTO_OPCODE(ip) @ jump to next instruction 2852 2853/* ------------------------------ */ 2854 .balign 64 2855.L_OP_SGET_OBJECT: /* 0x62 */ 2856/* File: armv5te/OP_SGET_OBJECT.S */ 2857/* File: armv5te/OP_SGET.S */ 2858 /* 2859 * General 32-bit SGET handler. 2860 * 2861 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2862 */ 2863 /* op vAA, field@BBBB */ 2864 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2865 FETCH(r1, 1) @ r1<- field ref BBBB 2866 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2867 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2868 cmp r0, #0 @ is resolved entry null? 2869 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2870.LOP_SGET_OBJECT_finish: @ field ptr in r0 2871 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2872 @ no-op @ acquiring load 2873 mov r2, rINST, lsr #8 @ r2<- AA 2874 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2875 SET_VREG(r1, r2) @ fp[AA]<- r1 2876 GET_INST_OPCODE(ip) @ extract opcode from rINST 2877 GOTO_OPCODE(ip) @ jump to next instruction 2878 2879 2880/* ------------------------------ */ 2881 .balign 64 2882.L_OP_SGET_BOOLEAN: /* 0x63 */ 2883/* File: armv5te/OP_SGET_BOOLEAN.S */ 2884/* File: armv5te/OP_SGET.S */ 2885 /* 2886 * General 32-bit SGET handler. 2887 * 2888 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2889 */ 2890 /* op vAA, field@BBBB */ 2891 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2892 FETCH(r1, 1) @ r1<- field ref BBBB 2893 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2894 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2895 cmp r0, #0 @ is resolved entry null? 2896 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2897.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2898 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2899 @ no-op @ acquiring load 2900 mov r2, rINST, lsr #8 @ r2<- AA 2901 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2902 SET_VREG(r1, r2) @ fp[AA]<- r1 2903 GET_INST_OPCODE(ip) @ extract opcode from rINST 2904 GOTO_OPCODE(ip) @ jump to next instruction 2905 2906 2907/* ------------------------------ */ 2908 .balign 64 2909.L_OP_SGET_BYTE: /* 0x64 */ 2910/* File: armv5te/OP_SGET_BYTE.S */ 2911/* File: armv5te/OP_SGET.S */ 2912 /* 2913 * General 32-bit SGET handler. 2914 * 2915 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2916 */ 2917 /* op vAA, field@BBBB */ 2918 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2919 FETCH(r1, 1) @ r1<- field ref BBBB 2920 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2921 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2922 cmp r0, #0 @ is resolved entry null? 2923 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2924.LOP_SGET_BYTE_finish: @ field ptr in r0 2925 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2926 @ no-op @ acquiring load 2927 mov r2, rINST, lsr #8 @ r2<- AA 2928 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2929 SET_VREG(r1, r2) @ fp[AA]<- r1 2930 GET_INST_OPCODE(ip) @ extract opcode from rINST 2931 GOTO_OPCODE(ip) @ jump to next instruction 2932 2933 2934/* ------------------------------ */ 2935 .balign 64 2936.L_OP_SGET_CHAR: /* 0x65 */ 2937/* File: armv5te/OP_SGET_CHAR.S */ 2938/* File: armv5te/OP_SGET.S */ 2939 /* 2940 * General 32-bit SGET handler. 2941 * 2942 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2943 */ 2944 /* op vAA, field@BBBB */ 2945 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2946 FETCH(r1, 1) @ r1<- field ref BBBB 2947 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2948 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2949 cmp r0, #0 @ is resolved entry null? 2950 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2951.LOP_SGET_CHAR_finish: @ field ptr in r0 2952 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2953 @ no-op @ acquiring load 2954 mov r2, rINST, lsr #8 @ r2<- AA 2955 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2956 SET_VREG(r1, r2) @ fp[AA]<- r1 2957 GET_INST_OPCODE(ip) @ extract opcode from rINST 2958 GOTO_OPCODE(ip) @ jump to next instruction 2959 2960 2961/* ------------------------------ */ 2962 .balign 64 2963.L_OP_SGET_SHORT: /* 0x66 */ 2964/* File: armv5te/OP_SGET_SHORT.S */ 2965/* File: armv5te/OP_SGET.S */ 2966 /* 2967 * General 32-bit SGET handler. 2968 * 2969 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2970 */ 2971 /* op vAA, field@BBBB */ 2972 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2973 FETCH(r1, 1) @ r1<- field ref BBBB 2974 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2975 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2976 cmp r0, #0 @ is resolved entry null? 2977 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 2978.LOP_SGET_SHORT_finish: @ field ptr in r0 2979 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2980 @ no-op @ acquiring load 2981 mov r2, rINST, lsr #8 @ r2<- AA 2982 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2983 SET_VREG(r1, r2) @ fp[AA]<- r1 2984 GET_INST_OPCODE(ip) @ extract opcode from rINST 2985 GOTO_OPCODE(ip) @ jump to next instruction 2986 2987 2988/* ------------------------------ */ 2989 .balign 64 2990.L_OP_SPUT: /* 0x67 */ 2991/* File: armv5te/OP_SPUT.S */ 2992 /* 2993 * General 32-bit SPUT handler. 2994 * 2995 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 2996 */ 2997 /* op vAA, field@BBBB */ 2998 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2999 FETCH(r1, 1) @ r1<- field ref BBBB 3000 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3001 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3002 cmp r0, #0 @ is resolved entry null? 3003 beq .LOP_SPUT_resolve @ yes, do resolve 3004.LOP_SPUT_finish: @ field ptr in r0 3005 mov r2, rINST, lsr #8 @ r2<- AA 3006 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3007 GET_VREG(r1, r2) @ r1<- fp[AA] 3008 GET_INST_OPCODE(ip) @ extract opcode from rINST 3009 @ no-op @ releasing store 3010 str r1, [r0, #offStaticField_value] @ field<- vAA 3011 GOTO_OPCODE(ip) @ jump to next instruction 3012 3013/* ------------------------------ */ 3014 .balign 64 3015.L_OP_SPUT_WIDE: /* 0x68 */ 3016/* File: armv5te/OP_SPUT_WIDE.S */ 3017 /* 3018 * 64-bit SPUT handler. 3019 */ 3020 /* sput-wide vAA, field@BBBB */ 3021 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 3022 FETCH(r1, 1) @ r1<- field ref BBBB 3023 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 3024 mov r9, rINST, lsr #8 @ r9<- AA 3025 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 3026 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 3027 cmp r2, #0 @ is resolved entry null? 3028 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 3029.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9 3030 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3031 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 3032 GET_INST_OPCODE(r10) @ extract opcode from rINST 3033 .if 0 3034 add r2, r2, #offStaticField_value @ r2<- pointer to data 3035 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 3036 .else 3037 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 3038 .endif 3039 GOTO_OPCODE(r10) @ jump to next instruction 3040 3041/* ------------------------------ */ 3042 .balign 64 3043.L_OP_SPUT_OBJECT: /* 0x69 */ 3044/* File: armv5te/OP_SPUT_OBJECT.S */ 3045 /* 3046 * 32-bit SPUT handler for objects 3047 * 3048 * for: sput-object, sput-object-volatile 3049 */ 3050 /* op vAA, field@BBBB */ 3051 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3052 FETCH(r1, 1) @ r1<- field ref BBBB 3053 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3054 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3055 cmp r0, #0 @ is resolved entry null? 3056 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3057 bne .LOP_SPUT_OBJECT_finish @ no, continue 3058 EXPORT_PC() @ resolve() could throw, so export now 3059 ldr r0, [r9, #offMethod_clazz] @ r0<- method->clazz 3060 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 3061 cmp r0, #0 @ success? 3062 bne .LOP_SPUT_OBJECT_finish @ yes, finish 3063 b common_exceptionThrown @ no, handle exception 3064 3065 3066/* ------------------------------ */ 3067 .balign 64 3068.L_OP_SPUT_BOOLEAN: /* 0x6a */ 3069/* File: armv5te/OP_SPUT_BOOLEAN.S */ 3070/* File: armv5te/OP_SPUT.S */ 3071 /* 3072 * General 32-bit SPUT handler. 3073 * 3074 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3075 */ 3076 /* op vAA, field@BBBB */ 3077 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3078 FETCH(r1, 1) @ r1<- field ref BBBB 3079 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3080 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3081 cmp r0, #0 @ is resolved entry null? 3082 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 3083.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 3084 mov r2, rINST, lsr #8 @ r2<- AA 3085 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3086 GET_VREG(r1, r2) @ r1<- fp[AA] 3087 GET_INST_OPCODE(ip) @ extract opcode from rINST 3088 @ no-op @ releasing store 3089 str r1, [r0, #offStaticField_value] @ field<- vAA 3090 GOTO_OPCODE(ip) @ jump to next instruction 3091 3092 3093/* ------------------------------ */ 3094 .balign 64 3095.L_OP_SPUT_BYTE: /* 0x6b */ 3096/* File: armv5te/OP_SPUT_BYTE.S */ 3097/* File: armv5te/OP_SPUT.S */ 3098 /* 3099 * General 32-bit SPUT handler. 3100 * 3101 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3102 */ 3103 /* op vAA, field@BBBB */ 3104 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3105 FETCH(r1, 1) @ r1<- field ref BBBB 3106 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3107 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3108 cmp r0, #0 @ is resolved entry null? 3109 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 3110.LOP_SPUT_BYTE_finish: @ field ptr in r0 3111 mov r2, rINST, lsr #8 @ r2<- AA 3112 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3113 GET_VREG(r1, r2) @ r1<- fp[AA] 3114 GET_INST_OPCODE(ip) @ extract opcode from rINST 3115 @ no-op @ releasing store 3116 str r1, [r0, #offStaticField_value] @ field<- vAA 3117 GOTO_OPCODE(ip) @ jump to next instruction 3118 3119 3120/* ------------------------------ */ 3121 .balign 64 3122.L_OP_SPUT_CHAR: /* 0x6c */ 3123/* File: armv5te/OP_SPUT_CHAR.S */ 3124/* File: armv5te/OP_SPUT.S */ 3125 /* 3126 * General 32-bit SPUT handler. 3127 * 3128 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3129 */ 3130 /* op vAA, field@BBBB */ 3131 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3132 FETCH(r1, 1) @ r1<- field ref BBBB 3133 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3134 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3135 cmp r0, #0 @ is resolved entry null? 3136 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 3137.LOP_SPUT_CHAR_finish: @ field ptr in r0 3138 mov r2, rINST, lsr #8 @ r2<- AA 3139 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3140 GET_VREG(r1, r2) @ r1<- fp[AA] 3141 GET_INST_OPCODE(ip) @ extract opcode from rINST 3142 @ no-op @ releasing store 3143 str r1, [r0, #offStaticField_value] @ field<- vAA 3144 GOTO_OPCODE(ip) @ jump to next instruction 3145 3146 3147/* ------------------------------ */ 3148 .balign 64 3149.L_OP_SPUT_SHORT: /* 0x6d */ 3150/* File: armv5te/OP_SPUT_SHORT.S */ 3151/* File: armv5te/OP_SPUT.S */ 3152 /* 3153 * General 32-bit SPUT handler. 3154 * 3155 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3156 */ 3157 /* op vAA, field@BBBB */ 3158 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3159 FETCH(r1, 1) @ r1<- field ref BBBB 3160 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3161 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3162 cmp r0, #0 @ is resolved entry null? 3163 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 3164.LOP_SPUT_SHORT_finish: @ field ptr in r0 3165 mov r2, rINST, lsr #8 @ r2<- AA 3166 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3167 GET_VREG(r1, r2) @ r1<- fp[AA] 3168 GET_INST_OPCODE(ip) @ extract opcode from rINST 3169 @ no-op @ releasing store 3170 str r1, [r0, #offStaticField_value] @ field<- vAA 3171 GOTO_OPCODE(ip) @ jump to next instruction 3172 3173 3174/* ------------------------------ */ 3175 .balign 64 3176.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3177/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3178 /* 3179 * Handle a virtual method call. 3180 * 3181 * for: invoke-virtual, invoke-virtual/range 3182 */ 3183 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3184 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3185 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3186 FETCH(r1, 1) @ r1<- BBBB 3187 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3188 FETCH(r10, 2) @ r10<- GFED or CCCC 3189 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3190 .if (!0) 3191 and r10, r10, #15 @ r10<- D (or stays CCCC) 3192 .endif 3193 cmp r0, #0 @ already resolved? 3194 EXPORT_PC() @ must export for invoke 3195 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3196 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3197 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3198 mov r2, #METHOD_VIRTUAL @ resolver method type 3199 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3200 cmp r0, #0 @ got null? 3201 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3202 b common_exceptionThrown @ yes, handle exception 3203 3204/* ------------------------------ */ 3205 .balign 64 3206.L_OP_INVOKE_SUPER: /* 0x6f */ 3207/* File: armv5te/OP_INVOKE_SUPER.S */ 3208 /* 3209 * Handle a "super" method call. 3210 * 3211 * for: invoke-super, invoke-super/range 3212 */ 3213 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3214 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3215 FETCH(r10, 2) @ r10<- GFED or CCCC 3216 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3217 .if (!0) 3218 and r10, r10, #15 @ r10<- D (or stays CCCC) 3219 .endif 3220 FETCH(r1, 1) @ r1<- BBBB 3221 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3222 GET_VREG(r2, r10) @ r2<- "this" ptr 3223 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3224 cmp r2, #0 @ null "this"? 3225 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3226 beq common_errNullObject @ null "this", throw exception 3227 cmp r0, #0 @ already resolved? 3228 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3229 EXPORT_PC() @ must export for invoke 3230 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3231 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3232 3233/* ------------------------------ */ 3234 .balign 64 3235.L_OP_INVOKE_DIRECT: /* 0x70 */ 3236/* File: armv5te/OP_INVOKE_DIRECT.S */ 3237 /* 3238 * Handle a direct method call. 3239 * 3240 * (We could defer the "is 'this' pointer null" test to the common 3241 * method invocation code, and use a flag to indicate that static 3242 * calls don't count. If we do this as part of copying the arguments 3243 * out we could avoiding loading the first arg twice.) 3244 * 3245 * for: invoke-direct, invoke-direct/range 3246 */ 3247 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3248 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3249 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3250 FETCH(r1, 1) @ r1<- BBBB 3251 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3252 FETCH(r10, 2) @ r10<- GFED or CCCC 3253 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3254 .if (!0) 3255 and r10, r10, #15 @ r10<- D (or stays CCCC) 3256 .endif 3257 cmp r0, #0 @ already resolved? 3258 EXPORT_PC() @ must export for invoke 3259 GET_VREG(r2, r10) @ r2<- "this" ptr 3260 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3261.LOP_INVOKE_DIRECT_finish: 3262 cmp r2, #0 @ null "this" ref? 3263 bne common_invokeMethodNoRange @ no, continue on 3264 b common_errNullObject @ yes, throw exception 3265 3266/* ------------------------------ */ 3267 .balign 64 3268.L_OP_INVOKE_STATIC: /* 0x71 */ 3269/* File: armv5te/OP_INVOKE_STATIC.S */ 3270 /* 3271 * Handle a static method call. 3272 * 3273 * for: invoke-static, invoke-static/range 3274 */ 3275 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3276 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3277 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3278 FETCH(r1, 1) @ r1<- BBBB 3279 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3280 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3281 cmp r0, #0 @ already resolved? 3282 EXPORT_PC() @ must export for invoke 3283 bne common_invokeMethodNoRange @ yes, continue on 32840: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3285 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3286 mov r2, #METHOD_STATIC @ resolver method type 3287 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3288 cmp r0, #0 @ got null? 3289 bne common_invokeMethodNoRange @ no, continue 3290 b common_exceptionThrown @ yes, handle exception 3291 3292/* ------------------------------ */ 3293 .balign 64 3294.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3295/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3296 /* 3297 * Handle an interface method call. 3298 * 3299 * for: invoke-interface, invoke-interface/range 3300 */ 3301 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3302 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3303 FETCH(r2, 2) @ r2<- FEDC or CCCC 3304 FETCH(r1, 1) @ r1<- BBBB 3305 .if (!0) 3306 and r2, r2, #15 @ r2<- C (or stays CCCC) 3307 .endif 3308 EXPORT_PC() @ must export for invoke 3309 GET_VREG(r0, r2) @ r0<- first arg ("this") 3310 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3311 cmp r0, #0 @ null obj? 3312 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3313 beq common_errNullObject @ yes, fail 3314 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3315 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3316 cmp r0, #0 @ failed? 3317 beq common_exceptionThrown @ yes, handle exception 3318 b common_invokeMethodNoRange @ jump to common handler 3319 3320/* ------------------------------ */ 3321 .balign 64 3322.L_OP_UNUSED_73: /* 0x73 */ 3323/* File: armv5te/OP_UNUSED_73.S */ 3324/* File: armv5te/unused.S */ 3325 bl common_abort 3326 3327 3328/* ------------------------------ */ 3329 .balign 64 3330.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3331/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3332/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3333 /* 3334 * Handle a virtual method call. 3335 * 3336 * for: invoke-virtual, invoke-virtual/range 3337 */ 3338 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3339 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3340 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3341 FETCH(r1, 1) @ r1<- BBBB 3342 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3343 FETCH(r10, 2) @ r10<- GFED or CCCC 3344 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3345 .if (!1) 3346 and r10, r10, #15 @ r10<- D (or stays CCCC) 3347 .endif 3348 cmp r0, #0 @ already resolved? 3349 EXPORT_PC() @ must export for invoke 3350 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3351 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3352 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3353 mov r2, #METHOD_VIRTUAL @ resolver method type 3354 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3355 cmp r0, #0 @ got null? 3356 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3357 b common_exceptionThrown @ yes, handle exception 3358 3359 3360/* ------------------------------ */ 3361 .balign 64 3362.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3363/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3364/* File: armv5te/OP_INVOKE_SUPER.S */ 3365 /* 3366 * Handle a "super" method call. 3367 * 3368 * for: invoke-super, invoke-super/range 3369 */ 3370 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3371 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3372 FETCH(r10, 2) @ r10<- GFED or CCCC 3373 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3374 .if (!1) 3375 and r10, r10, #15 @ r10<- D (or stays CCCC) 3376 .endif 3377 FETCH(r1, 1) @ r1<- BBBB 3378 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3379 GET_VREG(r2, r10) @ r2<- "this" ptr 3380 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3381 cmp r2, #0 @ null "this"? 3382 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3383 beq common_errNullObject @ null "this", throw exception 3384 cmp r0, #0 @ already resolved? 3385 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3386 EXPORT_PC() @ must export for invoke 3387 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3388 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3389 3390 3391/* ------------------------------ */ 3392 .balign 64 3393.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3394/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3395/* File: armv5te/OP_INVOKE_DIRECT.S */ 3396 /* 3397 * Handle a direct method call. 3398 * 3399 * (We could defer the "is 'this' pointer null" test to the common 3400 * method invocation code, and use a flag to indicate that static 3401 * calls don't count. If we do this as part of copying the arguments 3402 * out we could avoiding loading the first arg twice.) 3403 * 3404 * for: invoke-direct, invoke-direct/range 3405 */ 3406 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3407 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3408 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3409 FETCH(r1, 1) @ r1<- BBBB 3410 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3411 FETCH(r10, 2) @ r10<- GFED or CCCC 3412 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3413 .if (!1) 3414 and r10, r10, #15 @ r10<- D (or stays CCCC) 3415 .endif 3416 cmp r0, #0 @ already resolved? 3417 EXPORT_PC() @ must export for invoke 3418 GET_VREG(r2, r10) @ r2<- "this" ptr 3419 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3420.LOP_INVOKE_DIRECT_RANGE_finish: 3421 cmp r2, #0 @ null "this" ref? 3422 bne common_invokeMethodRange @ no, continue on 3423 b common_errNullObject @ yes, throw exception 3424 3425 3426/* ------------------------------ */ 3427 .balign 64 3428.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3429/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3430/* File: armv5te/OP_INVOKE_STATIC.S */ 3431 /* 3432 * Handle a static method call. 3433 * 3434 * for: invoke-static, invoke-static/range 3435 */ 3436 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3437 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3438 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3439 FETCH(r1, 1) @ r1<- BBBB 3440 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3441 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3442 cmp r0, #0 @ already resolved? 3443 EXPORT_PC() @ must export for invoke 3444 bne common_invokeMethodRange @ yes, continue on 34450: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3446 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3447 mov r2, #METHOD_STATIC @ resolver method type 3448 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3449 cmp r0, #0 @ got null? 3450 bne common_invokeMethodRange @ no, continue 3451 b common_exceptionThrown @ yes, handle exception 3452 3453 3454/* ------------------------------ */ 3455 .balign 64 3456.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3457/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3458/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3459 /* 3460 * Handle an interface method call. 3461 * 3462 * for: invoke-interface, invoke-interface/range 3463 */ 3464 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3465 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3466 FETCH(r2, 2) @ r2<- FEDC or CCCC 3467 FETCH(r1, 1) @ r1<- BBBB 3468 .if (!1) 3469 and r2, r2, #15 @ r2<- C (or stays CCCC) 3470 .endif 3471 EXPORT_PC() @ must export for invoke 3472 GET_VREG(r0, r2) @ r0<- first arg ("this") 3473 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3474 cmp r0, #0 @ null obj? 3475 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3476 beq common_errNullObject @ yes, fail 3477 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3478 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3479 cmp r0, #0 @ failed? 3480 beq common_exceptionThrown @ yes, handle exception 3481 b common_invokeMethodRange @ jump to common handler 3482 3483 3484/* ------------------------------ */ 3485 .balign 64 3486.L_OP_UNUSED_79: /* 0x79 */ 3487/* File: armv5te/OP_UNUSED_79.S */ 3488/* File: armv5te/unused.S */ 3489 bl common_abort 3490 3491 3492/* ------------------------------ */ 3493 .balign 64 3494.L_OP_UNUSED_7A: /* 0x7a */ 3495/* File: armv5te/OP_UNUSED_7A.S */ 3496/* File: armv5te/unused.S */ 3497 bl common_abort 3498 3499 3500/* ------------------------------ */ 3501 .balign 64 3502.L_OP_NEG_INT: /* 0x7b */ 3503/* File: armv6t2/OP_NEG_INT.S */ 3504/* File: armv6t2/unop.S */ 3505 /* 3506 * Generic 32-bit unary operation. Provide an "instr" line that 3507 * specifies an instruction that performs "result = op r0". 3508 * This could be an ARM instruction or a function call. 3509 * 3510 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3511 * int-to-byte, int-to-char, int-to-short 3512 */ 3513 /* unop vA, vB */ 3514 mov r3, rINST, lsr #12 @ r3<- B 3515 ubfx r9, rINST, #8, #4 @ r9<- A 3516 GET_VREG(r0, r3) @ r0<- vB 3517 @ optional op; may set condition codes 3518 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3519 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3520 GET_INST_OPCODE(ip) @ extract opcode from rINST 3521 SET_VREG(r0, r9) @ vAA<- r0 3522 GOTO_OPCODE(ip) @ jump to next instruction 3523 /* 8-9 instructions */ 3524 3525 3526/* ------------------------------ */ 3527 .balign 64 3528.L_OP_NOT_INT: /* 0x7c */ 3529/* File: armv6t2/OP_NOT_INT.S */ 3530/* File: armv6t2/unop.S */ 3531 /* 3532 * Generic 32-bit unary operation. Provide an "instr" line that 3533 * specifies an instruction that performs "result = op r0". 3534 * This could be an ARM instruction or a function call. 3535 * 3536 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3537 * int-to-byte, int-to-char, int-to-short 3538 */ 3539 /* unop vA, vB */ 3540 mov r3, rINST, lsr #12 @ r3<- B 3541 ubfx r9, rINST, #8, #4 @ r9<- A 3542 GET_VREG(r0, r3) @ r0<- vB 3543 @ optional op; may set condition codes 3544 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3545 mvn r0, r0 @ r0<- op, r0-r3 changed 3546 GET_INST_OPCODE(ip) @ extract opcode from rINST 3547 SET_VREG(r0, r9) @ vAA<- r0 3548 GOTO_OPCODE(ip) @ jump to next instruction 3549 /* 8-9 instructions */ 3550 3551 3552/* ------------------------------ */ 3553 .balign 64 3554.L_OP_NEG_LONG: /* 0x7d */ 3555/* File: armv6t2/OP_NEG_LONG.S */ 3556/* File: armv6t2/unopWide.S */ 3557 /* 3558 * Generic 64-bit unary operation. Provide an "instr" line that 3559 * specifies an instruction that performs "result = op r0/r1". 3560 * This could be an ARM instruction or a function call. 3561 * 3562 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3563 */ 3564 /* unop vA, vB */ 3565 mov r3, rINST, lsr #12 @ r3<- B 3566 ubfx r9, rINST, #8, #4 @ r9<- A 3567 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3568 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3569 ldmia r3, {r0-r1} @ r0/r1<- vAA 3570 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3571 rsbs r0, r0, #0 @ optional op; may set condition codes 3572 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3573 GET_INST_OPCODE(ip) @ extract opcode from rINST 3574 stmia r9, {r0-r1} @ vAA<- r0/r1 3575 GOTO_OPCODE(ip) @ jump to next instruction 3576 /* 10-11 instructions */ 3577 3578 3579/* ------------------------------ */ 3580 .balign 64 3581.L_OP_NOT_LONG: /* 0x7e */ 3582/* File: armv6t2/OP_NOT_LONG.S */ 3583/* File: armv6t2/unopWide.S */ 3584 /* 3585 * Generic 64-bit unary operation. Provide an "instr" line that 3586 * specifies an instruction that performs "result = op r0/r1". 3587 * This could be an ARM instruction or a function call. 3588 * 3589 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3590 */ 3591 /* unop vA, vB */ 3592 mov r3, rINST, lsr #12 @ r3<- B 3593 ubfx r9, rINST, #8, #4 @ r9<- A 3594 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3595 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3596 ldmia r3, {r0-r1} @ r0/r1<- vAA 3597 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3598 mvn r0, r0 @ optional op; may set condition codes 3599 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3600 GET_INST_OPCODE(ip) @ extract opcode from rINST 3601 stmia r9, {r0-r1} @ vAA<- r0/r1 3602 GOTO_OPCODE(ip) @ jump to next instruction 3603 /* 10-11 instructions */ 3604 3605 3606/* ------------------------------ */ 3607 .balign 64 3608.L_OP_NEG_FLOAT: /* 0x7f */ 3609/* File: armv6t2/OP_NEG_FLOAT.S */ 3610/* File: armv6t2/unop.S */ 3611 /* 3612 * Generic 32-bit unary operation. Provide an "instr" line that 3613 * specifies an instruction that performs "result = op r0". 3614 * This could be an ARM instruction or a function call. 3615 * 3616 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3617 * int-to-byte, int-to-char, int-to-short 3618 */ 3619 /* unop vA, vB */ 3620 mov r3, rINST, lsr #12 @ r3<- B 3621 ubfx r9, rINST, #8, #4 @ r9<- A 3622 GET_VREG(r0, r3) @ r0<- vB 3623 @ optional op; may set condition codes 3624 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3625 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3626 GET_INST_OPCODE(ip) @ extract opcode from rINST 3627 SET_VREG(r0, r9) @ vAA<- r0 3628 GOTO_OPCODE(ip) @ jump to next instruction 3629 /* 8-9 instructions */ 3630 3631 3632/* ------------------------------ */ 3633 .balign 64 3634.L_OP_NEG_DOUBLE: /* 0x80 */ 3635/* File: armv6t2/OP_NEG_DOUBLE.S */ 3636/* File: armv6t2/unopWide.S */ 3637 /* 3638 * Generic 64-bit unary operation. Provide an "instr" line that 3639 * specifies an instruction that performs "result = op r0/r1". 3640 * This could be an ARM instruction or a function call. 3641 * 3642 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3643 */ 3644 /* unop vA, vB */ 3645 mov r3, rINST, lsr #12 @ r3<- B 3646 ubfx r9, rINST, #8, #4 @ r9<- A 3647 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3648 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3649 ldmia r3, {r0-r1} @ r0/r1<- vAA 3650 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3651 @ optional op; may set condition codes 3652 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3653 GET_INST_OPCODE(ip) @ extract opcode from rINST 3654 stmia r9, {r0-r1} @ vAA<- r0/r1 3655 GOTO_OPCODE(ip) @ jump to next instruction 3656 /* 10-11 instructions */ 3657 3658 3659/* ------------------------------ */ 3660 .balign 64 3661.L_OP_INT_TO_LONG: /* 0x81 */ 3662/* File: armv6t2/OP_INT_TO_LONG.S */ 3663/* File: armv6t2/unopWider.S */ 3664 /* 3665 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3666 * that specifies an instruction that performs "result = op r0", where 3667 * "result" is a 64-bit quantity in r0/r1. 3668 * 3669 * For: int-to-long, int-to-double, float-to-long, float-to-double 3670 */ 3671 /* unop vA, vB */ 3672 mov r3, rINST, lsr #12 @ r3<- B 3673 ubfx r9, rINST, #8, #4 @ r9<- A 3674 GET_VREG(r0, r3) @ r0<- vB 3675 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3676 @ optional op; may set condition codes 3677 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3678 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3679 GET_INST_OPCODE(ip) @ extract opcode from rINST 3680 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3681 GOTO_OPCODE(ip) @ jump to next instruction 3682 /* 9-10 instructions */ 3683 3684 3685/* ------------------------------ */ 3686 .balign 64 3687.L_OP_INT_TO_FLOAT: /* 0x82 */ 3688/* File: arm-vfp/OP_INT_TO_FLOAT.S */ 3689/* File: arm-vfp/funop.S */ 3690 /* 3691 * Generic 32-bit unary floating-point operation. Provide an "instr" 3692 * line that specifies an instruction that performs "s1 = op s0". 3693 * 3694 * for: int-to-float, float-to-int 3695 */ 3696 /* unop vA, vB */ 3697 mov r3, rINST, lsr #12 @ r3<- B 3698 mov r9, rINST, lsr #8 @ r9<- A+ 3699 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3700 flds s0, [r3] @ s0<- vB 3701 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3702 and r9, r9, #15 @ r9<- A 3703 fsitos s1, s0 @ s1<- op 3704 GET_INST_OPCODE(ip) @ extract opcode from rINST 3705 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3706 fsts s1, [r9] @ vA<- s1 3707 GOTO_OPCODE(ip) @ jump to next instruction 3708 3709 3710/* ------------------------------ */ 3711 .balign 64 3712.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3713/* File: arm-vfp/OP_INT_TO_DOUBLE.S */ 3714/* File: arm-vfp/funopWider.S */ 3715 /* 3716 * Generic 32bit-to-64bit floating point unary operation. Provide an 3717 * "instr" line that specifies an instruction that performs "d0 = op s0". 3718 * 3719 * For: int-to-double, float-to-double 3720 */ 3721 /* unop vA, vB */ 3722 mov r3, rINST, lsr #12 @ r3<- B 3723 mov r9, rINST, lsr #8 @ r9<- A+ 3724 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3725 flds s0, [r3] @ s0<- vB 3726 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3727 and r9, r9, #15 @ r9<- A 3728 fsitod d0, s0 @ d0<- op 3729 GET_INST_OPCODE(ip) @ extract opcode from rINST 3730 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3731 fstd d0, [r9] @ vA<- d0 3732 GOTO_OPCODE(ip) @ jump to next instruction 3733 3734 3735/* ------------------------------ */ 3736 .balign 64 3737.L_OP_LONG_TO_INT: /* 0x84 */ 3738/* File: armv5te/OP_LONG_TO_INT.S */ 3739/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3740/* File: armv5te/OP_MOVE.S */ 3741 /* for move, move-object, long-to-int */ 3742 /* op vA, vB */ 3743 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3744 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3745 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3746 GET_VREG(r2, r1) @ r2<- fp[B] 3747 and r0, r0, #15 3748 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3749 SET_VREG(r2, r0) @ fp[A]<- r2 3750 GOTO_OPCODE(ip) @ execute next instruction 3751 3752 3753/* ------------------------------ */ 3754 .balign 64 3755.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3756/* File: armv6t2/OP_LONG_TO_FLOAT.S */ 3757/* File: armv6t2/unopNarrower.S */ 3758 /* 3759 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3760 * that specifies an instruction that performs "result = op r0/r1", where 3761 * "result" is a 32-bit quantity in r0. 3762 * 3763 * For: long-to-float, double-to-int, double-to-float 3764 * 3765 * (This would work for long-to-int, but that instruction is actually 3766 * an exact match for OP_MOVE.) 3767 */ 3768 /* unop vA, vB */ 3769 mov r3, rINST, lsr #12 @ r3<- B 3770 ubfx r9, rINST, #8, #4 @ r9<- A 3771 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3772 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3773 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3774 @ optional op; may set condition codes 3775 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3776 GET_INST_OPCODE(ip) @ extract opcode from rINST 3777 SET_VREG(r0, r9) @ vA<- r0 3778 GOTO_OPCODE(ip) @ jump to next instruction 3779 /* 9-10 instructions */ 3780 3781 3782/* ------------------------------ */ 3783 .balign 64 3784.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3785/* File: armv6t2/OP_LONG_TO_DOUBLE.S */ 3786/* File: armv6t2/unopWide.S */ 3787 /* 3788 * Generic 64-bit unary operation. Provide an "instr" line that 3789 * specifies an instruction that performs "result = op r0/r1". 3790 * This could be an ARM instruction or a function call. 3791 * 3792 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3793 */ 3794 /* unop vA, vB */ 3795 mov r3, rINST, lsr #12 @ r3<- B 3796 ubfx r9, rINST, #8, #4 @ r9<- A 3797 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3798 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3799 ldmia r3, {r0-r1} @ r0/r1<- vAA 3800 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3801 @ optional op; may set condition codes 3802 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3803 GET_INST_OPCODE(ip) @ extract opcode from rINST 3804 stmia r9, {r0-r1} @ vAA<- r0/r1 3805 GOTO_OPCODE(ip) @ jump to next instruction 3806 /* 10-11 instructions */ 3807 3808 3809/* ------------------------------ */ 3810 .balign 64 3811.L_OP_FLOAT_TO_INT: /* 0x87 */ 3812/* File: arm-vfp/OP_FLOAT_TO_INT.S */ 3813/* File: arm-vfp/funop.S */ 3814 /* 3815 * Generic 32-bit unary floating-point operation. Provide an "instr" 3816 * line that specifies an instruction that performs "s1 = op s0". 3817 * 3818 * for: int-to-float, float-to-int 3819 */ 3820 /* unop vA, vB */ 3821 mov r3, rINST, lsr #12 @ r3<- B 3822 mov r9, rINST, lsr #8 @ r9<- A+ 3823 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3824 flds s0, [r3] @ s0<- vB 3825 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3826 and r9, r9, #15 @ r9<- A 3827 ftosizs s1, s0 @ s1<- op 3828 GET_INST_OPCODE(ip) @ extract opcode from rINST 3829 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3830 fsts s1, [r9] @ vA<- s1 3831 GOTO_OPCODE(ip) @ jump to next instruction 3832 3833 3834/* ------------------------------ */ 3835 .balign 64 3836.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3837/* File: armv6t2/OP_FLOAT_TO_LONG.S */ 3838@include "armv6t2/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3839/* File: armv6t2/unopWider.S */ 3840 /* 3841 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3842 * that specifies an instruction that performs "result = op r0", where 3843 * "result" is a 64-bit quantity in r0/r1. 3844 * 3845 * For: int-to-long, int-to-double, float-to-long, float-to-double 3846 */ 3847 /* unop vA, vB */ 3848 mov r3, rINST, lsr #12 @ r3<- B 3849 ubfx r9, rINST, #8, #4 @ r9<- A 3850 GET_VREG(r0, r3) @ r0<- vB 3851 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3852 @ optional op; may set condition codes 3853 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3854 bl f2l_doconv @ r0<- op, r0-r3 changed 3855 GET_INST_OPCODE(ip) @ extract opcode from rINST 3856 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3857 GOTO_OPCODE(ip) @ jump to next instruction 3858 /* 9-10 instructions */ 3859 3860 3861 3862/* ------------------------------ */ 3863 .balign 64 3864.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3865/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */ 3866/* File: arm-vfp/funopWider.S */ 3867 /* 3868 * Generic 32bit-to-64bit floating point unary operation. Provide an 3869 * "instr" line that specifies an instruction that performs "d0 = op s0". 3870 * 3871 * For: int-to-double, float-to-double 3872 */ 3873 /* unop vA, vB */ 3874 mov r3, rINST, lsr #12 @ r3<- B 3875 mov r9, rINST, lsr #8 @ r9<- A+ 3876 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3877 flds s0, [r3] @ s0<- vB 3878 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3879 and r9, r9, #15 @ r9<- A 3880 fcvtds d0, s0 @ d0<- op 3881 GET_INST_OPCODE(ip) @ extract opcode from rINST 3882 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3883 fstd d0, [r9] @ vA<- d0 3884 GOTO_OPCODE(ip) @ jump to next instruction 3885 3886 3887/* ------------------------------ */ 3888 .balign 64 3889.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3890/* File: arm-vfp/OP_DOUBLE_TO_INT.S */ 3891/* File: arm-vfp/funopNarrower.S */ 3892 /* 3893 * Generic 64bit-to-32bit unary floating point operation. Provide an 3894 * "instr" line that specifies an instruction that performs "s0 = op d0". 3895 * 3896 * For: double-to-int, double-to-float 3897 */ 3898 /* unop vA, vB */ 3899 mov r3, rINST, lsr #12 @ r3<- B 3900 mov r9, rINST, lsr #8 @ r9<- A+ 3901 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3902 fldd d0, [r3] @ d0<- vB 3903 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3904 and r9, r9, #15 @ r9<- A 3905 ftosizd s0, d0 @ s0<- op 3906 GET_INST_OPCODE(ip) @ extract opcode from rINST 3907 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3908 fsts s0, [r9] @ vA<- s0 3909 GOTO_OPCODE(ip) @ jump to next instruction 3910 3911 3912/* ------------------------------ */ 3913 .balign 64 3914.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3915/* File: armv6t2/OP_DOUBLE_TO_LONG.S */ 3916@include "armv6t2/unopWide.S" {"instr":"bl __aeabi_d2lz"} 3917/* File: armv6t2/unopWide.S */ 3918 /* 3919 * Generic 64-bit unary operation. Provide an "instr" line that 3920 * specifies an instruction that performs "result = op r0/r1". 3921 * This could be an ARM instruction or a function call. 3922 * 3923 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3924 */ 3925 /* unop vA, vB */ 3926 mov r3, rINST, lsr #12 @ r3<- B 3927 ubfx r9, rINST, #8, #4 @ r9<- A 3928 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3929 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3930 ldmia r3, {r0-r1} @ r0/r1<- vAA 3931 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3932 @ optional op; may set condition codes 3933 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 3934 GET_INST_OPCODE(ip) @ extract opcode from rINST 3935 stmia r9, {r0-r1} @ vAA<- r0/r1 3936 GOTO_OPCODE(ip) @ jump to next instruction 3937 /* 10-11 instructions */ 3938 3939 3940 3941/* ------------------------------ */ 3942 .balign 64 3943.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3944/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */ 3945/* File: arm-vfp/funopNarrower.S */ 3946 /* 3947 * Generic 64bit-to-32bit unary floating point operation. Provide an 3948 * "instr" line that specifies an instruction that performs "s0 = op d0". 3949 * 3950 * For: double-to-int, double-to-float 3951 */ 3952 /* unop vA, vB */ 3953 mov r3, rINST, lsr #12 @ r3<- B 3954 mov r9, rINST, lsr #8 @ r9<- A+ 3955 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3956 fldd d0, [r3] @ d0<- vB 3957 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3958 and r9, r9, #15 @ r9<- A 3959 fcvtsd s0, d0 @ s0<- op 3960 GET_INST_OPCODE(ip) @ extract opcode from rINST 3961 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3962 fsts s0, [r9] @ vA<- s0 3963 GOTO_OPCODE(ip) @ jump to next instruction 3964 3965 3966/* ------------------------------ */ 3967 .balign 64 3968.L_OP_INT_TO_BYTE: /* 0x8d */ 3969/* File: armv6t2/OP_INT_TO_BYTE.S */ 3970/* File: armv6t2/unop.S */ 3971 /* 3972 * Generic 32-bit unary operation. Provide an "instr" line that 3973 * specifies an instruction that performs "result = op r0". 3974 * This could be an ARM instruction or a function call. 3975 * 3976 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3977 * int-to-byte, int-to-char, int-to-short 3978 */ 3979 /* unop vA, vB */ 3980 mov r3, rINST, lsr #12 @ r3<- B 3981 ubfx r9, rINST, #8, #4 @ r9<- A 3982 GET_VREG(r0, r3) @ r0<- vB 3983 @ optional op; may set condition codes 3984 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3985 sxtb r0, r0 @ r0<- op, r0-r3 changed 3986 GET_INST_OPCODE(ip) @ extract opcode from rINST 3987 SET_VREG(r0, r9) @ vAA<- r0 3988 GOTO_OPCODE(ip) @ jump to next instruction 3989 /* 8-9 instructions */ 3990 3991 3992/* ------------------------------ */ 3993 .balign 64 3994.L_OP_INT_TO_CHAR: /* 0x8e */ 3995/* File: armv6t2/OP_INT_TO_CHAR.S */ 3996/* File: armv6t2/unop.S */ 3997 /* 3998 * Generic 32-bit unary operation. Provide an "instr" line that 3999 * specifies an instruction that performs "result = op r0". 4000 * This could be an ARM instruction or a function call. 4001 * 4002 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4003 * int-to-byte, int-to-char, int-to-short 4004 */ 4005 /* unop vA, vB */ 4006 mov r3, rINST, lsr #12 @ r3<- B 4007 ubfx r9, rINST, #8, #4 @ r9<- A 4008 GET_VREG(r0, r3) @ r0<- vB 4009 @ optional op; may set condition codes 4010 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4011 uxth r0, r0 @ r0<- op, r0-r3 changed 4012 GET_INST_OPCODE(ip) @ extract opcode from rINST 4013 SET_VREG(r0, r9) @ vAA<- r0 4014 GOTO_OPCODE(ip) @ jump to next instruction 4015 /* 8-9 instructions */ 4016 4017 4018/* ------------------------------ */ 4019 .balign 64 4020.L_OP_INT_TO_SHORT: /* 0x8f */ 4021/* File: armv6t2/OP_INT_TO_SHORT.S */ 4022/* File: armv6t2/unop.S */ 4023 /* 4024 * Generic 32-bit unary operation. Provide an "instr" line that 4025 * specifies an instruction that performs "result = op r0". 4026 * This could be an ARM instruction or a function call. 4027 * 4028 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4029 * int-to-byte, int-to-char, int-to-short 4030 */ 4031 /* unop vA, vB */ 4032 mov r3, rINST, lsr #12 @ r3<- B 4033 ubfx r9, rINST, #8, #4 @ r9<- A 4034 GET_VREG(r0, r3) @ r0<- vB 4035 @ optional op; may set condition codes 4036 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4037 sxth r0, r0 @ r0<- op, r0-r3 changed 4038 GET_INST_OPCODE(ip) @ extract opcode from rINST 4039 SET_VREG(r0, r9) @ vAA<- r0 4040 GOTO_OPCODE(ip) @ jump to next instruction 4041 /* 8-9 instructions */ 4042 4043 4044/* ------------------------------ */ 4045 .balign 64 4046.L_OP_ADD_INT: /* 0x90 */ 4047/* File: armv5te/OP_ADD_INT.S */ 4048/* File: armv5te/binop.S */ 4049 /* 4050 * Generic 32-bit binary operation. Provide an "instr" line that 4051 * specifies an instruction that performs "result = r0 op r1". 4052 * This could be an ARM instruction or a function call. (If the result 4053 * comes back in a register other than r0, you can override "result".) 4054 * 4055 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4056 * vCC (r1). Useful for integer division and modulus. Note that we 4057 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4058 * handles it correctly. 4059 * 4060 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4061 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4062 * mul-float, div-float, rem-float 4063 */ 4064 /* binop vAA, vBB, vCC */ 4065 FETCH(r0, 1) @ r0<- CCBB 4066 mov r9, rINST, lsr #8 @ r9<- AA 4067 mov r3, r0, lsr #8 @ r3<- CC 4068 and r2, r0, #255 @ r2<- BB 4069 GET_VREG(r1, r3) @ r1<- vCC 4070 GET_VREG(r0, r2) @ r0<- vBB 4071 .if 0 4072 cmp r1, #0 @ is second operand zero? 4073 beq common_errDivideByZero 4074 .endif 4075 4076 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4077 @ optional op; may set condition codes 4078 add r0, r0, r1 @ r0<- op, r0-r3 changed 4079 GET_INST_OPCODE(ip) @ extract opcode from rINST 4080 SET_VREG(r0, r9) @ vAA<- r0 4081 GOTO_OPCODE(ip) @ jump to next instruction 4082 /* 11-14 instructions */ 4083 4084 4085/* ------------------------------ */ 4086 .balign 64 4087.L_OP_SUB_INT: /* 0x91 */ 4088/* File: armv5te/OP_SUB_INT.S */ 4089/* File: armv5te/binop.S */ 4090 /* 4091 * Generic 32-bit binary operation. Provide an "instr" line that 4092 * specifies an instruction that performs "result = r0 op r1". 4093 * This could be an ARM instruction or a function call. (If the result 4094 * comes back in a register other than r0, you can override "result".) 4095 * 4096 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4097 * vCC (r1). Useful for integer division and modulus. Note that we 4098 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4099 * handles it correctly. 4100 * 4101 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4102 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4103 * mul-float, div-float, rem-float 4104 */ 4105 /* binop vAA, vBB, vCC */ 4106 FETCH(r0, 1) @ r0<- CCBB 4107 mov r9, rINST, lsr #8 @ r9<- AA 4108 mov r3, r0, lsr #8 @ r3<- CC 4109 and r2, r0, #255 @ r2<- BB 4110 GET_VREG(r1, r3) @ r1<- vCC 4111 GET_VREG(r0, r2) @ r0<- vBB 4112 .if 0 4113 cmp r1, #0 @ is second operand zero? 4114 beq common_errDivideByZero 4115 .endif 4116 4117 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4118 @ optional op; may set condition codes 4119 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4120 GET_INST_OPCODE(ip) @ extract opcode from rINST 4121 SET_VREG(r0, r9) @ vAA<- r0 4122 GOTO_OPCODE(ip) @ jump to next instruction 4123 /* 11-14 instructions */ 4124 4125 4126/* ------------------------------ */ 4127 .balign 64 4128.L_OP_MUL_INT: /* 0x92 */ 4129/* File: armv5te/OP_MUL_INT.S */ 4130/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4131/* File: armv5te/binop.S */ 4132 /* 4133 * Generic 32-bit binary operation. Provide an "instr" line that 4134 * specifies an instruction that performs "result = r0 op r1". 4135 * This could be an ARM instruction or a function call. (If the result 4136 * comes back in a register other than r0, you can override "result".) 4137 * 4138 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4139 * vCC (r1). Useful for integer division and modulus. Note that we 4140 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4141 * handles it correctly. 4142 * 4143 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4144 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4145 * mul-float, div-float, rem-float 4146 */ 4147 /* binop vAA, vBB, vCC */ 4148 FETCH(r0, 1) @ r0<- CCBB 4149 mov r9, rINST, lsr #8 @ r9<- AA 4150 mov r3, r0, lsr #8 @ r3<- CC 4151 and r2, r0, #255 @ r2<- BB 4152 GET_VREG(r1, r3) @ r1<- vCC 4153 GET_VREG(r0, r2) @ r0<- vBB 4154 .if 0 4155 cmp r1, #0 @ is second operand zero? 4156 beq common_errDivideByZero 4157 .endif 4158 4159 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4160 @ optional op; may set condition codes 4161 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4162 GET_INST_OPCODE(ip) @ extract opcode from rINST 4163 SET_VREG(r0, r9) @ vAA<- r0 4164 GOTO_OPCODE(ip) @ jump to next instruction 4165 /* 11-14 instructions */ 4166 4167 4168/* ------------------------------ */ 4169 .balign 64 4170.L_OP_DIV_INT: /* 0x93 */ 4171/* File: armv5te/OP_DIV_INT.S */ 4172/* File: armv5te/binop.S */ 4173 /* 4174 * Generic 32-bit binary operation. Provide an "instr" line that 4175 * specifies an instruction that performs "result = r0 op r1". 4176 * This could be an ARM instruction or a function call. (If the result 4177 * comes back in a register other than r0, you can override "result".) 4178 * 4179 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4180 * vCC (r1). Useful for integer division and modulus. Note that we 4181 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4182 * handles it correctly. 4183 * 4184 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4185 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4186 * mul-float, div-float, rem-float 4187 */ 4188 /* binop vAA, vBB, vCC */ 4189 FETCH(r0, 1) @ r0<- CCBB 4190 mov r9, rINST, lsr #8 @ r9<- AA 4191 mov r3, r0, lsr #8 @ r3<- CC 4192 and r2, r0, #255 @ r2<- BB 4193 GET_VREG(r1, r3) @ r1<- vCC 4194 GET_VREG(r0, r2) @ r0<- vBB 4195 .if 1 4196 cmp r1, #0 @ is second operand zero? 4197 beq common_errDivideByZero 4198 .endif 4199 4200 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4201 @ optional op; may set condition codes 4202 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4203 GET_INST_OPCODE(ip) @ extract opcode from rINST 4204 SET_VREG(r0, r9) @ vAA<- r0 4205 GOTO_OPCODE(ip) @ jump to next instruction 4206 /* 11-14 instructions */ 4207 4208 4209/* ------------------------------ */ 4210 .balign 64 4211.L_OP_REM_INT: /* 0x94 */ 4212/* File: armv5te/OP_REM_INT.S */ 4213/* idivmod returns quotient in r0 and remainder in r1 */ 4214/* File: armv5te/binop.S */ 4215 /* 4216 * Generic 32-bit binary operation. Provide an "instr" line that 4217 * specifies an instruction that performs "result = r0 op r1". 4218 * This could be an ARM instruction or a function call. (If the result 4219 * comes back in a register other than r0, you can override "result".) 4220 * 4221 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4222 * vCC (r1). Useful for integer division and modulus. Note that we 4223 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4224 * handles it correctly. 4225 * 4226 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4227 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4228 * mul-float, div-float, rem-float 4229 */ 4230 /* binop vAA, vBB, vCC */ 4231 FETCH(r0, 1) @ r0<- CCBB 4232 mov r9, rINST, lsr #8 @ r9<- AA 4233 mov r3, r0, lsr #8 @ r3<- CC 4234 and r2, r0, #255 @ r2<- BB 4235 GET_VREG(r1, r3) @ r1<- vCC 4236 GET_VREG(r0, r2) @ r0<- vBB 4237 .if 1 4238 cmp r1, #0 @ is second operand zero? 4239 beq common_errDivideByZero 4240 .endif 4241 4242 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4243 @ optional op; may set condition codes 4244 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4245 GET_INST_OPCODE(ip) @ extract opcode from rINST 4246 SET_VREG(r1, r9) @ vAA<- r1 4247 GOTO_OPCODE(ip) @ jump to next instruction 4248 /* 11-14 instructions */ 4249 4250 4251/* ------------------------------ */ 4252 .balign 64 4253.L_OP_AND_INT: /* 0x95 */ 4254/* File: armv5te/OP_AND_INT.S */ 4255/* File: armv5te/binop.S */ 4256 /* 4257 * Generic 32-bit binary operation. Provide an "instr" line that 4258 * specifies an instruction that performs "result = r0 op r1". 4259 * This could be an ARM instruction or a function call. (If the result 4260 * comes back in a register other than r0, you can override "result".) 4261 * 4262 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4263 * vCC (r1). Useful for integer division and modulus. Note that we 4264 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4265 * handles it correctly. 4266 * 4267 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4268 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4269 * mul-float, div-float, rem-float 4270 */ 4271 /* binop vAA, vBB, vCC */ 4272 FETCH(r0, 1) @ r0<- CCBB 4273 mov r9, rINST, lsr #8 @ r9<- AA 4274 mov r3, r0, lsr #8 @ r3<- CC 4275 and r2, r0, #255 @ r2<- BB 4276 GET_VREG(r1, r3) @ r1<- vCC 4277 GET_VREG(r0, r2) @ r0<- vBB 4278 .if 0 4279 cmp r1, #0 @ is second operand zero? 4280 beq common_errDivideByZero 4281 .endif 4282 4283 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4284 @ optional op; may set condition codes 4285 and r0, r0, r1 @ r0<- op, r0-r3 changed 4286 GET_INST_OPCODE(ip) @ extract opcode from rINST 4287 SET_VREG(r0, r9) @ vAA<- r0 4288 GOTO_OPCODE(ip) @ jump to next instruction 4289 /* 11-14 instructions */ 4290 4291 4292/* ------------------------------ */ 4293 .balign 64 4294.L_OP_OR_INT: /* 0x96 */ 4295/* File: armv5te/OP_OR_INT.S */ 4296/* File: armv5te/binop.S */ 4297 /* 4298 * Generic 32-bit binary operation. Provide an "instr" line that 4299 * specifies an instruction that performs "result = r0 op r1". 4300 * This could be an ARM instruction or a function call. (If the result 4301 * comes back in a register other than r0, you can override "result".) 4302 * 4303 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4304 * vCC (r1). Useful for integer division and modulus. Note that we 4305 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4306 * handles it correctly. 4307 * 4308 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4309 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4310 * mul-float, div-float, rem-float 4311 */ 4312 /* binop vAA, vBB, vCC */ 4313 FETCH(r0, 1) @ r0<- CCBB 4314 mov r9, rINST, lsr #8 @ r9<- AA 4315 mov r3, r0, lsr #8 @ r3<- CC 4316 and r2, r0, #255 @ r2<- BB 4317 GET_VREG(r1, r3) @ r1<- vCC 4318 GET_VREG(r0, r2) @ r0<- vBB 4319 .if 0 4320 cmp r1, #0 @ is second operand zero? 4321 beq common_errDivideByZero 4322 .endif 4323 4324 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4325 @ optional op; may set condition codes 4326 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4327 GET_INST_OPCODE(ip) @ extract opcode from rINST 4328 SET_VREG(r0, r9) @ vAA<- r0 4329 GOTO_OPCODE(ip) @ jump to next instruction 4330 /* 11-14 instructions */ 4331 4332 4333/* ------------------------------ */ 4334 .balign 64 4335.L_OP_XOR_INT: /* 0x97 */ 4336/* File: armv5te/OP_XOR_INT.S */ 4337/* File: armv5te/binop.S */ 4338 /* 4339 * Generic 32-bit binary operation. Provide an "instr" line that 4340 * specifies an instruction that performs "result = r0 op r1". 4341 * This could be an ARM instruction or a function call. (If the result 4342 * comes back in a register other than r0, you can override "result".) 4343 * 4344 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4345 * vCC (r1). Useful for integer division and modulus. Note that we 4346 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4347 * handles it correctly. 4348 * 4349 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4350 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4351 * mul-float, div-float, rem-float 4352 */ 4353 /* binop vAA, vBB, vCC */ 4354 FETCH(r0, 1) @ r0<- CCBB 4355 mov r9, rINST, lsr #8 @ r9<- AA 4356 mov r3, r0, lsr #8 @ r3<- CC 4357 and r2, r0, #255 @ r2<- BB 4358 GET_VREG(r1, r3) @ r1<- vCC 4359 GET_VREG(r0, r2) @ r0<- vBB 4360 .if 0 4361 cmp r1, #0 @ is second operand zero? 4362 beq common_errDivideByZero 4363 .endif 4364 4365 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4366 @ optional op; may set condition codes 4367 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4368 GET_INST_OPCODE(ip) @ extract opcode from rINST 4369 SET_VREG(r0, r9) @ vAA<- r0 4370 GOTO_OPCODE(ip) @ jump to next instruction 4371 /* 11-14 instructions */ 4372 4373 4374/* ------------------------------ */ 4375 .balign 64 4376.L_OP_SHL_INT: /* 0x98 */ 4377/* File: armv5te/OP_SHL_INT.S */ 4378/* File: armv5te/binop.S */ 4379 /* 4380 * Generic 32-bit binary operation. Provide an "instr" line that 4381 * specifies an instruction that performs "result = r0 op r1". 4382 * This could be an ARM instruction or a function call. (If the result 4383 * comes back in a register other than r0, you can override "result".) 4384 * 4385 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4386 * vCC (r1). Useful for integer division and modulus. Note that we 4387 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4388 * handles it correctly. 4389 * 4390 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4391 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4392 * mul-float, div-float, rem-float 4393 */ 4394 /* binop vAA, vBB, vCC */ 4395 FETCH(r0, 1) @ r0<- CCBB 4396 mov r9, rINST, lsr #8 @ r9<- AA 4397 mov r3, r0, lsr #8 @ r3<- CC 4398 and r2, r0, #255 @ r2<- BB 4399 GET_VREG(r1, r3) @ r1<- vCC 4400 GET_VREG(r0, r2) @ r0<- vBB 4401 .if 0 4402 cmp r1, #0 @ is second operand zero? 4403 beq common_errDivideByZero 4404 .endif 4405 4406 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4407 and r1, r1, #31 @ optional op; may set condition codes 4408 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4409 GET_INST_OPCODE(ip) @ extract opcode from rINST 4410 SET_VREG(r0, r9) @ vAA<- r0 4411 GOTO_OPCODE(ip) @ jump to next instruction 4412 /* 11-14 instructions */ 4413 4414 4415/* ------------------------------ */ 4416 .balign 64 4417.L_OP_SHR_INT: /* 0x99 */ 4418/* File: armv5te/OP_SHR_INT.S */ 4419/* File: armv5te/binop.S */ 4420 /* 4421 * Generic 32-bit binary operation. Provide an "instr" line that 4422 * specifies an instruction that performs "result = r0 op r1". 4423 * This could be an ARM instruction or a function call. (If the result 4424 * comes back in a register other than r0, you can override "result".) 4425 * 4426 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4427 * vCC (r1). Useful for integer division and modulus. Note that we 4428 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4429 * handles it correctly. 4430 * 4431 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4432 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4433 * mul-float, div-float, rem-float 4434 */ 4435 /* binop vAA, vBB, vCC */ 4436 FETCH(r0, 1) @ r0<- CCBB 4437 mov r9, rINST, lsr #8 @ r9<- AA 4438 mov r3, r0, lsr #8 @ r3<- CC 4439 and r2, r0, #255 @ r2<- BB 4440 GET_VREG(r1, r3) @ r1<- vCC 4441 GET_VREG(r0, r2) @ r0<- vBB 4442 .if 0 4443 cmp r1, #0 @ is second operand zero? 4444 beq common_errDivideByZero 4445 .endif 4446 4447 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4448 and r1, r1, #31 @ optional op; may set condition codes 4449 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4450 GET_INST_OPCODE(ip) @ extract opcode from rINST 4451 SET_VREG(r0, r9) @ vAA<- r0 4452 GOTO_OPCODE(ip) @ jump to next instruction 4453 /* 11-14 instructions */ 4454 4455 4456/* ------------------------------ */ 4457 .balign 64 4458.L_OP_USHR_INT: /* 0x9a */ 4459/* File: armv5te/OP_USHR_INT.S */ 4460/* File: armv5te/binop.S */ 4461 /* 4462 * Generic 32-bit binary operation. Provide an "instr" line that 4463 * specifies an instruction that performs "result = r0 op r1". 4464 * This could be an ARM instruction or a function call. (If the result 4465 * comes back in a register other than r0, you can override "result".) 4466 * 4467 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4468 * vCC (r1). Useful for integer division and modulus. Note that we 4469 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4470 * handles it correctly. 4471 * 4472 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4473 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4474 * mul-float, div-float, rem-float 4475 */ 4476 /* binop vAA, vBB, vCC */ 4477 FETCH(r0, 1) @ r0<- CCBB 4478 mov r9, rINST, lsr #8 @ r9<- AA 4479 mov r3, r0, lsr #8 @ r3<- CC 4480 and r2, r0, #255 @ r2<- BB 4481 GET_VREG(r1, r3) @ r1<- vCC 4482 GET_VREG(r0, r2) @ r0<- vBB 4483 .if 0 4484 cmp r1, #0 @ is second operand zero? 4485 beq common_errDivideByZero 4486 .endif 4487 4488 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4489 and r1, r1, #31 @ optional op; may set condition codes 4490 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4491 GET_INST_OPCODE(ip) @ extract opcode from rINST 4492 SET_VREG(r0, r9) @ vAA<- r0 4493 GOTO_OPCODE(ip) @ jump to next instruction 4494 /* 11-14 instructions */ 4495 4496 4497/* ------------------------------ */ 4498 .balign 64 4499.L_OP_ADD_LONG: /* 0x9b */ 4500/* File: armv5te/OP_ADD_LONG.S */ 4501/* File: armv5te/binopWide.S */ 4502 /* 4503 * Generic 64-bit binary operation. Provide an "instr" line that 4504 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4505 * This could be an ARM instruction or a function call. (If the result 4506 * comes back in a register other than r0, you can override "result".) 4507 * 4508 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4509 * vCC (r1). Useful for integer division and modulus. 4510 * 4511 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4512 * xor-long, add-double, sub-double, mul-double, div-double, 4513 * rem-double 4514 * 4515 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4516 */ 4517 /* binop vAA, vBB, vCC */ 4518 FETCH(r0, 1) @ r0<- CCBB 4519 mov r9, rINST, lsr #8 @ r9<- AA 4520 and r2, r0, #255 @ r2<- BB 4521 mov r3, r0, lsr #8 @ r3<- CC 4522 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4523 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4524 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4525 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4526 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4527 .if 0 4528 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4529 beq common_errDivideByZero 4530 .endif 4531 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4532 4533 adds r0, r0, r2 @ optional op; may set condition codes 4534 adc r1, r1, r3 @ result<- op, r0-r3 changed 4535 GET_INST_OPCODE(ip) @ extract opcode from rINST 4536 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4537 GOTO_OPCODE(ip) @ jump to next instruction 4538 /* 14-17 instructions */ 4539 4540 4541/* ------------------------------ */ 4542 .balign 64 4543.L_OP_SUB_LONG: /* 0x9c */ 4544/* File: armv5te/OP_SUB_LONG.S */ 4545/* File: armv5te/binopWide.S */ 4546 /* 4547 * Generic 64-bit binary operation. Provide an "instr" line that 4548 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4549 * This could be an ARM instruction or a function call. (If the result 4550 * comes back in a register other than r0, you can override "result".) 4551 * 4552 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4553 * vCC (r1). Useful for integer division and modulus. 4554 * 4555 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4556 * xor-long, add-double, sub-double, mul-double, div-double, 4557 * rem-double 4558 * 4559 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4560 */ 4561 /* binop vAA, vBB, vCC */ 4562 FETCH(r0, 1) @ r0<- CCBB 4563 mov r9, rINST, lsr #8 @ r9<- AA 4564 and r2, r0, #255 @ r2<- BB 4565 mov r3, r0, lsr #8 @ r3<- CC 4566 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4567 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4568 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4569 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4570 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4571 .if 0 4572 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4573 beq common_errDivideByZero 4574 .endif 4575 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4576 4577 subs r0, r0, r2 @ optional op; may set condition codes 4578 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4579 GET_INST_OPCODE(ip) @ extract opcode from rINST 4580 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4581 GOTO_OPCODE(ip) @ jump to next instruction 4582 /* 14-17 instructions */ 4583 4584 4585/* ------------------------------ */ 4586 .balign 64 4587.L_OP_MUL_LONG: /* 0x9d */ 4588/* File: armv5te/OP_MUL_LONG.S */ 4589 /* 4590 * Signed 64-bit integer multiply. 4591 * 4592 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4593 * WX 4594 * x YZ 4595 * -------- 4596 * ZW ZX 4597 * YW YX 4598 * 4599 * The low word of the result holds ZX, the high word holds 4600 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4601 * it doesn't fit in the low 64 bits. 4602 * 4603 * Unlike most ARM math operations, multiply instructions have 4604 * restrictions on using the same register more than once (Rd and Rm 4605 * cannot be the same). 4606 */ 4607 /* mul-long vAA, vBB, vCC */ 4608 FETCH(r0, 1) @ r0<- CCBB 4609 and r2, r0, #255 @ r2<- BB 4610 mov r3, r0, lsr #8 @ r3<- CC 4611 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4612 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4613 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4614 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4615 mul ip, r2, r1 @ ip<- ZxW 4616 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4617 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4618 mov r0, rINST, lsr #8 @ r0<- AA 4619 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4620 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4621 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4622 b .LOP_MUL_LONG_finish 4623 4624/* ------------------------------ */ 4625 .balign 64 4626.L_OP_DIV_LONG: /* 0x9e */ 4627/* File: armv5te/OP_DIV_LONG.S */ 4628/* File: armv5te/binopWide.S */ 4629 /* 4630 * Generic 64-bit binary operation. Provide an "instr" line that 4631 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4632 * This could be an ARM instruction or a function call. (If the result 4633 * comes back in a register other than r0, you can override "result".) 4634 * 4635 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4636 * vCC (r1). Useful for integer division and modulus. 4637 * 4638 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4639 * xor-long, add-double, sub-double, mul-double, div-double, 4640 * rem-double 4641 * 4642 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4643 */ 4644 /* binop vAA, vBB, vCC */ 4645 FETCH(r0, 1) @ r0<- CCBB 4646 mov r9, rINST, lsr #8 @ r9<- AA 4647 and r2, r0, #255 @ r2<- BB 4648 mov r3, r0, lsr #8 @ r3<- CC 4649 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4650 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4651 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4652 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4653 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4654 .if 1 4655 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4656 beq common_errDivideByZero 4657 .endif 4658 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4659 4660 @ optional op; may set condition codes 4661 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4662 GET_INST_OPCODE(ip) @ extract opcode from rINST 4663 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4664 GOTO_OPCODE(ip) @ jump to next instruction 4665 /* 14-17 instructions */ 4666 4667 4668/* ------------------------------ */ 4669 .balign 64 4670.L_OP_REM_LONG: /* 0x9f */ 4671/* File: armv5te/OP_REM_LONG.S */ 4672/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4673/* File: armv5te/binopWide.S */ 4674 /* 4675 * Generic 64-bit binary operation. Provide an "instr" line that 4676 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4677 * This could be an ARM instruction or a function call. (If the result 4678 * comes back in a register other than r0, you can override "result".) 4679 * 4680 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4681 * vCC (r1). Useful for integer division and modulus. 4682 * 4683 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4684 * xor-long, add-double, sub-double, mul-double, div-double, 4685 * rem-double 4686 * 4687 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4688 */ 4689 /* binop vAA, vBB, vCC */ 4690 FETCH(r0, 1) @ r0<- CCBB 4691 mov r9, rINST, lsr #8 @ r9<- AA 4692 and r2, r0, #255 @ r2<- BB 4693 mov r3, r0, lsr #8 @ r3<- CC 4694 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4695 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4696 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4697 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4698 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4699 .if 1 4700 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4701 beq common_errDivideByZero 4702 .endif 4703 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4704 4705 @ optional op; may set condition codes 4706 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4707 GET_INST_OPCODE(ip) @ extract opcode from rINST 4708 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4709 GOTO_OPCODE(ip) @ jump to next instruction 4710 /* 14-17 instructions */ 4711 4712 4713/* ------------------------------ */ 4714 .balign 64 4715.L_OP_AND_LONG: /* 0xa0 */ 4716/* File: armv5te/OP_AND_LONG.S */ 4717/* File: armv5te/binopWide.S */ 4718 /* 4719 * Generic 64-bit binary operation. Provide an "instr" line that 4720 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4721 * This could be an ARM instruction or a function call. (If the result 4722 * comes back in a register other than r0, you can override "result".) 4723 * 4724 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4725 * vCC (r1). Useful for integer division and modulus. 4726 * 4727 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4728 * xor-long, add-double, sub-double, mul-double, div-double, 4729 * rem-double 4730 * 4731 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4732 */ 4733 /* binop vAA, vBB, vCC */ 4734 FETCH(r0, 1) @ r0<- CCBB 4735 mov r9, rINST, lsr #8 @ r9<- AA 4736 and r2, r0, #255 @ r2<- BB 4737 mov r3, r0, lsr #8 @ r3<- CC 4738 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4739 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4740 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4741 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4742 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4743 .if 0 4744 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4745 beq common_errDivideByZero 4746 .endif 4747 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4748 4749 and r0, r0, r2 @ optional op; may set condition codes 4750 and r1, r1, r3 @ result<- op, r0-r3 changed 4751 GET_INST_OPCODE(ip) @ extract opcode from rINST 4752 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4753 GOTO_OPCODE(ip) @ jump to next instruction 4754 /* 14-17 instructions */ 4755 4756 4757/* ------------------------------ */ 4758 .balign 64 4759.L_OP_OR_LONG: /* 0xa1 */ 4760/* File: armv5te/OP_OR_LONG.S */ 4761/* File: armv5te/binopWide.S */ 4762 /* 4763 * Generic 64-bit binary operation. Provide an "instr" line that 4764 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4765 * This could be an ARM instruction or a function call. (If the result 4766 * comes back in a register other than r0, you can override "result".) 4767 * 4768 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4769 * vCC (r1). Useful for integer division and modulus. 4770 * 4771 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4772 * xor-long, add-double, sub-double, mul-double, div-double, 4773 * rem-double 4774 * 4775 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4776 */ 4777 /* binop vAA, vBB, vCC */ 4778 FETCH(r0, 1) @ r0<- CCBB 4779 mov r9, rINST, lsr #8 @ r9<- AA 4780 and r2, r0, #255 @ r2<- BB 4781 mov r3, r0, lsr #8 @ r3<- CC 4782 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4783 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4784 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4785 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4786 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4787 .if 0 4788 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4789 beq common_errDivideByZero 4790 .endif 4791 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4792 4793 orr r0, r0, r2 @ optional op; may set condition codes 4794 orr r1, r1, r3 @ result<- op, r0-r3 changed 4795 GET_INST_OPCODE(ip) @ extract opcode from rINST 4796 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4797 GOTO_OPCODE(ip) @ jump to next instruction 4798 /* 14-17 instructions */ 4799 4800 4801/* ------------------------------ */ 4802 .balign 64 4803.L_OP_XOR_LONG: /* 0xa2 */ 4804/* File: armv5te/OP_XOR_LONG.S */ 4805/* File: armv5te/binopWide.S */ 4806 /* 4807 * Generic 64-bit binary operation. Provide an "instr" line that 4808 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4809 * This could be an ARM instruction or a function call. (If the result 4810 * comes back in a register other than r0, you can override "result".) 4811 * 4812 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4813 * vCC (r1). Useful for integer division and modulus. 4814 * 4815 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4816 * xor-long, add-double, sub-double, mul-double, div-double, 4817 * rem-double 4818 * 4819 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4820 */ 4821 /* binop vAA, vBB, vCC */ 4822 FETCH(r0, 1) @ r0<- CCBB 4823 mov r9, rINST, lsr #8 @ r9<- AA 4824 and r2, r0, #255 @ r2<- BB 4825 mov r3, r0, lsr #8 @ r3<- CC 4826 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4827 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4828 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4829 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4830 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4831 .if 0 4832 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4833 beq common_errDivideByZero 4834 .endif 4835 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4836 4837 eor r0, r0, r2 @ optional op; may set condition codes 4838 eor r1, r1, r3 @ result<- op, r0-r3 changed 4839 GET_INST_OPCODE(ip) @ extract opcode from rINST 4840 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4841 GOTO_OPCODE(ip) @ jump to next instruction 4842 /* 14-17 instructions */ 4843 4844 4845/* ------------------------------ */ 4846 .balign 64 4847.L_OP_SHL_LONG: /* 0xa3 */ 4848/* File: armv5te/OP_SHL_LONG.S */ 4849 /* 4850 * Long integer shift. This is different from the generic 32/64-bit 4851 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4852 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4853 * 6 bits of the shift distance. 4854 */ 4855 /* shl-long vAA, vBB, vCC */ 4856 FETCH(r0, 1) @ r0<- CCBB 4857 mov r9, rINST, lsr #8 @ r9<- AA 4858 and r3, r0, #255 @ r3<- BB 4859 mov r0, r0, lsr #8 @ r0<- CC 4860 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4861 GET_VREG(r2, r0) @ r2<- vCC 4862 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4863 and r2, r2, #63 @ r2<- r2 & 0x3f 4864 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4865 4866 mov r1, r1, asl r2 @ r1<- r1 << r2 4867 rsb r3, r2, #32 @ r3<- 32 - r2 4868 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 4869 subs ip, r2, #32 @ ip<- r2 - 32 4870 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 4871 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4872 b .LOP_SHL_LONG_finish 4873 4874/* ------------------------------ */ 4875 .balign 64 4876.L_OP_SHR_LONG: /* 0xa4 */ 4877/* File: armv5te/OP_SHR_LONG.S */ 4878 /* 4879 * Long integer shift. This is different from the generic 32/64-bit 4880 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4881 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4882 * 6 bits of the shift distance. 4883 */ 4884 /* shr-long vAA, vBB, vCC */ 4885 FETCH(r0, 1) @ r0<- CCBB 4886 mov r9, rINST, lsr #8 @ r9<- AA 4887 and r3, r0, #255 @ r3<- BB 4888 mov r0, r0, lsr #8 @ r0<- CC 4889 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4890 GET_VREG(r2, r0) @ r2<- vCC 4891 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4892 and r2, r2, #63 @ r0<- r0 & 0x3f 4893 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4894 4895 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4896 rsb r3, r2, #32 @ r3<- 32 - r2 4897 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4898 subs ip, r2, #32 @ ip<- r2 - 32 4899 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 4900 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4901 b .LOP_SHR_LONG_finish 4902 4903/* ------------------------------ */ 4904 .balign 64 4905.L_OP_USHR_LONG: /* 0xa5 */ 4906/* File: armv5te/OP_USHR_LONG.S */ 4907 /* 4908 * Long integer shift. This is different from the generic 32/64-bit 4909 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4910 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4911 * 6 bits of the shift distance. 4912 */ 4913 /* ushr-long vAA, vBB, vCC */ 4914 FETCH(r0, 1) @ r0<- CCBB 4915 mov r9, rINST, lsr #8 @ r9<- AA 4916 and r3, r0, #255 @ r3<- BB 4917 mov r0, r0, lsr #8 @ r0<- CC 4918 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4919 GET_VREG(r2, r0) @ r2<- vCC 4920 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4921 and r2, r2, #63 @ r0<- r0 & 0x3f 4922 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4923 4924 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4925 rsb r3, r2, #32 @ r3<- 32 - r2 4926 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4927 subs ip, r2, #32 @ ip<- r2 - 32 4928 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 4929 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4930 b .LOP_USHR_LONG_finish 4931 4932/* ------------------------------ */ 4933 .balign 64 4934.L_OP_ADD_FLOAT: /* 0xa6 */ 4935/* File: arm-vfp/OP_ADD_FLOAT.S */ 4936/* File: arm-vfp/fbinop.S */ 4937 /* 4938 * Generic 32-bit floating-point operation. Provide an "instr" line that 4939 * specifies an instruction that performs "s2 = s0 op s1". Because we 4940 * use the "softfp" ABI, this must be an instruction, not a function call. 4941 * 4942 * For: add-float, sub-float, mul-float, div-float 4943 */ 4944 /* floatop vAA, vBB, vCC */ 4945 FETCH(r0, 1) @ r0<- CCBB 4946 mov r9, rINST, lsr #8 @ r9<- AA 4947 mov r3, r0, lsr #8 @ r3<- CC 4948 and r2, r0, #255 @ r2<- BB 4949 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4950 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4951 flds s1, [r3] @ s1<- vCC 4952 flds s0, [r2] @ s0<- vBB 4953 4954 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4955 fadds s2, s0, s1 @ s2<- op 4956 GET_INST_OPCODE(ip) @ extract opcode from rINST 4957 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4958 fsts s2, [r9] @ vAA<- s2 4959 GOTO_OPCODE(ip) @ jump to next instruction 4960 4961 4962/* ------------------------------ */ 4963 .balign 64 4964.L_OP_SUB_FLOAT: /* 0xa7 */ 4965/* File: arm-vfp/OP_SUB_FLOAT.S */ 4966/* File: arm-vfp/fbinop.S */ 4967 /* 4968 * Generic 32-bit floating-point operation. Provide an "instr" line that 4969 * specifies an instruction that performs "s2 = s0 op s1". Because we 4970 * use the "softfp" ABI, this must be an instruction, not a function call. 4971 * 4972 * For: add-float, sub-float, mul-float, div-float 4973 */ 4974 /* floatop vAA, vBB, vCC */ 4975 FETCH(r0, 1) @ r0<- CCBB 4976 mov r9, rINST, lsr #8 @ r9<- AA 4977 mov r3, r0, lsr #8 @ r3<- CC 4978 and r2, r0, #255 @ r2<- BB 4979 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4980 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4981 flds s1, [r3] @ s1<- vCC 4982 flds s0, [r2] @ s0<- vBB 4983 4984 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4985 fsubs s2, s0, s1 @ s2<- op 4986 GET_INST_OPCODE(ip) @ extract opcode from rINST 4987 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4988 fsts s2, [r9] @ vAA<- s2 4989 GOTO_OPCODE(ip) @ jump to next instruction 4990 4991 4992/* ------------------------------ */ 4993 .balign 64 4994.L_OP_MUL_FLOAT: /* 0xa8 */ 4995/* File: arm-vfp/OP_MUL_FLOAT.S */ 4996/* File: arm-vfp/fbinop.S */ 4997 /* 4998 * Generic 32-bit floating-point operation. Provide an "instr" line that 4999 * specifies an instruction that performs "s2 = s0 op s1". Because we 5000 * use the "softfp" ABI, this must be an instruction, not a function call. 5001 * 5002 * For: add-float, sub-float, mul-float, div-float 5003 */ 5004 /* floatop vAA, vBB, vCC */ 5005 FETCH(r0, 1) @ r0<- CCBB 5006 mov r9, rINST, lsr #8 @ r9<- AA 5007 mov r3, r0, lsr #8 @ r3<- CC 5008 and r2, r0, #255 @ r2<- BB 5009 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5010 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5011 flds s1, [r3] @ s1<- vCC 5012 flds s0, [r2] @ s0<- vBB 5013 5014 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5015 fmuls s2, s0, s1 @ s2<- op 5016 GET_INST_OPCODE(ip) @ extract opcode from rINST 5017 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5018 fsts s2, [r9] @ vAA<- s2 5019 GOTO_OPCODE(ip) @ jump to next instruction 5020 5021 5022/* ------------------------------ */ 5023 .balign 64 5024.L_OP_DIV_FLOAT: /* 0xa9 */ 5025/* File: arm-vfp/OP_DIV_FLOAT.S */ 5026/* File: arm-vfp/fbinop.S */ 5027 /* 5028 * Generic 32-bit floating-point operation. Provide an "instr" line that 5029 * specifies an instruction that performs "s2 = s0 op s1". Because we 5030 * use the "softfp" ABI, this must be an instruction, not a function call. 5031 * 5032 * For: add-float, sub-float, mul-float, div-float 5033 */ 5034 /* floatop vAA, vBB, vCC */ 5035 FETCH(r0, 1) @ r0<- CCBB 5036 mov r9, rINST, lsr #8 @ r9<- AA 5037 mov r3, r0, lsr #8 @ r3<- CC 5038 and r2, r0, #255 @ r2<- BB 5039 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5040 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5041 flds s1, [r3] @ s1<- vCC 5042 flds s0, [r2] @ s0<- vBB 5043 5044 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5045 fdivs s2, s0, s1 @ s2<- op 5046 GET_INST_OPCODE(ip) @ extract opcode from rINST 5047 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5048 fsts s2, [r9] @ vAA<- s2 5049 GOTO_OPCODE(ip) @ jump to next instruction 5050 5051 5052/* ------------------------------ */ 5053 .balign 64 5054.L_OP_REM_FLOAT: /* 0xaa */ 5055/* File: armv5te/OP_REM_FLOAT.S */ 5056/* EABI doesn't define a float remainder function, but libm does */ 5057/* File: armv5te/binop.S */ 5058 /* 5059 * Generic 32-bit binary operation. Provide an "instr" line that 5060 * specifies an instruction that performs "result = r0 op r1". 5061 * This could be an ARM instruction or a function call. (If the result 5062 * comes back in a register other than r0, you can override "result".) 5063 * 5064 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5065 * vCC (r1). Useful for integer division and modulus. Note that we 5066 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5067 * handles it correctly. 5068 * 5069 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5070 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5071 * mul-float, div-float, rem-float 5072 */ 5073 /* binop vAA, vBB, vCC */ 5074 FETCH(r0, 1) @ r0<- CCBB 5075 mov r9, rINST, lsr #8 @ r9<- AA 5076 mov r3, r0, lsr #8 @ r3<- CC 5077 and r2, r0, #255 @ r2<- BB 5078 GET_VREG(r1, r3) @ r1<- vCC 5079 GET_VREG(r0, r2) @ r0<- vBB 5080 .if 0 5081 cmp r1, #0 @ is second operand zero? 5082 beq common_errDivideByZero 5083 .endif 5084 5085 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5086 @ optional op; may set condition codes 5087 bl fmodf @ r0<- op, r0-r3 changed 5088 GET_INST_OPCODE(ip) @ extract opcode from rINST 5089 SET_VREG(r0, r9) @ vAA<- r0 5090 GOTO_OPCODE(ip) @ jump to next instruction 5091 /* 11-14 instructions */ 5092 5093 5094/* ------------------------------ */ 5095 .balign 64 5096.L_OP_ADD_DOUBLE: /* 0xab */ 5097/* File: arm-vfp/OP_ADD_DOUBLE.S */ 5098/* File: arm-vfp/fbinopWide.S */ 5099 /* 5100 * Generic 64-bit double-precision floating point binary operation. 5101 * Provide an "instr" line that specifies an instruction that performs 5102 * "d2 = d0 op d1". 5103 * 5104 * for: add-double, sub-double, mul-double, div-double 5105 */ 5106 /* doubleop vAA, vBB, vCC */ 5107 FETCH(r0, 1) @ r0<- CCBB 5108 mov r9, rINST, lsr #8 @ r9<- AA 5109 mov r3, r0, lsr #8 @ r3<- CC 5110 and r2, r0, #255 @ r2<- BB 5111 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5112 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5113 fldd d1, [r3] @ d1<- vCC 5114 fldd d0, [r2] @ d0<- vBB 5115 5116 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5117 faddd d2, d0, d1 @ s2<- op 5118 GET_INST_OPCODE(ip) @ extract opcode from rINST 5119 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5120 fstd d2, [r9] @ vAA<- d2 5121 GOTO_OPCODE(ip) @ jump to next instruction 5122 5123 5124/* ------------------------------ */ 5125 .balign 64 5126.L_OP_SUB_DOUBLE: /* 0xac */ 5127/* File: arm-vfp/OP_SUB_DOUBLE.S */ 5128/* File: arm-vfp/fbinopWide.S */ 5129 /* 5130 * Generic 64-bit double-precision floating point binary operation. 5131 * Provide an "instr" line that specifies an instruction that performs 5132 * "d2 = d0 op d1". 5133 * 5134 * for: add-double, sub-double, mul-double, div-double 5135 */ 5136 /* doubleop vAA, vBB, vCC */ 5137 FETCH(r0, 1) @ r0<- CCBB 5138 mov r9, rINST, lsr #8 @ r9<- AA 5139 mov r3, r0, lsr #8 @ r3<- CC 5140 and r2, r0, #255 @ r2<- BB 5141 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5142 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5143 fldd d1, [r3] @ d1<- vCC 5144 fldd d0, [r2] @ d0<- vBB 5145 5146 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5147 fsubd d2, d0, d1 @ s2<- op 5148 GET_INST_OPCODE(ip) @ extract opcode from rINST 5149 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5150 fstd d2, [r9] @ vAA<- d2 5151 GOTO_OPCODE(ip) @ jump to next instruction 5152 5153 5154/* ------------------------------ */ 5155 .balign 64 5156.L_OP_MUL_DOUBLE: /* 0xad */ 5157/* File: arm-vfp/OP_MUL_DOUBLE.S */ 5158/* File: arm-vfp/fbinopWide.S */ 5159 /* 5160 * Generic 64-bit double-precision floating point binary operation. 5161 * Provide an "instr" line that specifies an instruction that performs 5162 * "d2 = d0 op d1". 5163 * 5164 * for: add-double, sub-double, mul-double, div-double 5165 */ 5166 /* doubleop vAA, vBB, vCC */ 5167 FETCH(r0, 1) @ r0<- CCBB 5168 mov r9, rINST, lsr #8 @ r9<- AA 5169 mov r3, r0, lsr #8 @ r3<- CC 5170 and r2, r0, #255 @ r2<- BB 5171 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5172 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5173 fldd d1, [r3] @ d1<- vCC 5174 fldd d0, [r2] @ d0<- vBB 5175 5176 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5177 fmuld d2, d0, d1 @ s2<- op 5178 GET_INST_OPCODE(ip) @ extract opcode from rINST 5179 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5180 fstd d2, [r9] @ vAA<- d2 5181 GOTO_OPCODE(ip) @ jump to next instruction 5182 5183 5184/* ------------------------------ */ 5185 .balign 64 5186.L_OP_DIV_DOUBLE: /* 0xae */ 5187/* File: arm-vfp/OP_DIV_DOUBLE.S */ 5188/* File: arm-vfp/fbinopWide.S */ 5189 /* 5190 * Generic 64-bit double-precision floating point binary operation. 5191 * Provide an "instr" line that specifies an instruction that performs 5192 * "d2 = d0 op d1". 5193 * 5194 * for: add-double, sub-double, mul-double, div-double 5195 */ 5196 /* doubleop vAA, vBB, vCC */ 5197 FETCH(r0, 1) @ r0<- CCBB 5198 mov r9, rINST, lsr #8 @ r9<- AA 5199 mov r3, r0, lsr #8 @ r3<- CC 5200 and r2, r0, #255 @ r2<- BB 5201 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5202 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5203 fldd d1, [r3] @ d1<- vCC 5204 fldd d0, [r2] @ d0<- vBB 5205 5206 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5207 fdivd d2, d0, d1 @ s2<- op 5208 GET_INST_OPCODE(ip) @ extract opcode from rINST 5209 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5210 fstd d2, [r9] @ vAA<- d2 5211 GOTO_OPCODE(ip) @ jump to next instruction 5212 5213 5214/* ------------------------------ */ 5215 .balign 64 5216.L_OP_REM_DOUBLE: /* 0xaf */ 5217/* File: armv5te/OP_REM_DOUBLE.S */ 5218/* EABI doesn't define a double remainder function, but libm does */ 5219/* File: armv5te/binopWide.S */ 5220 /* 5221 * Generic 64-bit binary operation. Provide an "instr" line that 5222 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5223 * This could be an ARM instruction or a function call. (If the result 5224 * comes back in a register other than r0, you can override "result".) 5225 * 5226 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5227 * vCC (r1). Useful for integer division and modulus. 5228 * 5229 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5230 * xor-long, add-double, sub-double, mul-double, div-double, 5231 * rem-double 5232 * 5233 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5234 */ 5235 /* binop vAA, vBB, vCC */ 5236 FETCH(r0, 1) @ r0<- CCBB 5237 mov r9, rINST, lsr #8 @ r9<- AA 5238 and r2, r0, #255 @ r2<- BB 5239 mov r3, r0, lsr #8 @ r3<- CC 5240 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5241 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5242 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5243 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5244 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5245 .if 0 5246 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5247 beq common_errDivideByZero 5248 .endif 5249 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5250 5251 @ optional op; may set condition codes 5252 bl fmod @ result<- op, r0-r3 changed 5253 GET_INST_OPCODE(ip) @ extract opcode from rINST 5254 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5255 GOTO_OPCODE(ip) @ jump to next instruction 5256 /* 14-17 instructions */ 5257 5258 5259/* ------------------------------ */ 5260 .balign 64 5261.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5262/* File: armv6t2/OP_ADD_INT_2ADDR.S */ 5263/* File: armv6t2/binop2addr.S */ 5264 /* 5265 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5266 * that specifies an instruction that performs "result = r0 op r1". 5267 * This could be an ARM instruction or a function call. (If the result 5268 * comes back in a register other than r0, you can override "result".) 5269 * 5270 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5271 * vCC (r1). Useful for integer division and modulus. 5272 * 5273 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5274 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5275 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5276 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5277 */ 5278 /* binop/2addr vA, vB */ 5279 mov r3, rINST, lsr #12 @ r3<- B 5280 ubfx r9, rINST, #8, #4 @ r9<- A 5281 GET_VREG(r1, r3) @ r1<- vB 5282 GET_VREG(r0, r9) @ r0<- vA 5283 .if 0 5284 cmp r1, #0 @ is second operand zero? 5285 beq common_errDivideByZero 5286 .endif 5287 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5288 5289 @ optional op; may set condition codes 5290 add r0, r0, r1 @ r0<- op, r0-r3 changed 5291 GET_INST_OPCODE(ip) @ extract opcode from rINST 5292 SET_VREG(r0, r9) @ vAA<- r0 5293 GOTO_OPCODE(ip) @ jump to next instruction 5294 /* 10-13 instructions */ 5295 5296 5297/* ------------------------------ */ 5298 .balign 64 5299.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5300/* File: armv6t2/OP_SUB_INT_2ADDR.S */ 5301/* File: armv6t2/binop2addr.S */ 5302 /* 5303 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5304 * that specifies an instruction that performs "result = r0 op r1". 5305 * This could be an ARM instruction or a function call. (If the result 5306 * comes back in a register other than r0, you can override "result".) 5307 * 5308 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5309 * vCC (r1). Useful for integer division and modulus. 5310 * 5311 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5312 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5313 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5314 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5315 */ 5316 /* binop/2addr vA, vB */ 5317 mov r3, rINST, lsr #12 @ r3<- B 5318 ubfx r9, rINST, #8, #4 @ r9<- A 5319 GET_VREG(r1, r3) @ r1<- vB 5320 GET_VREG(r0, r9) @ r0<- vA 5321 .if 0 5322 cmp r1, #0 @ is second operand zero? 5323 beq common_errDivideByZero 5324 .endif 5325 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5326 5327 @ optional op; may set condition codes 5328 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5329 GET_INST_OPCODE(ip) @ extract opcode from rINST 5330 SET_VREG(r0, r9) @ vAA<- r0 5331 GOTO_OPCODE(ip) @ jump to next instruction 5332 /* 10-13 instructions */ 5333 5334 5335/* ------------------------------ */ 5336 .balign 64 5337.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5338/* File: armv6t2/OP_MUL_INT_2ADDR.S */ 5339/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5340/* File: armv6t2/binop2addr.S */ 5341 /* 5342 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5343 * that specifies an instruction that performs "result = r0 op r1". 5344 * This could be an ARM instruction or a function call. (If the result 5345 * comes back in a register other than r0, you can override "result".) 5346 * 5347 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5348 * vCC (r1). Useful for integer division and modulus. 5349 * 5350 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5351 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5352 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5353 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5354 */ 5355 /* binop/2addr vA, vB */ 5356 mov r3, rINST, lsr #12 @ r3<- B 5357 ubfx r9, rINST, #8, #4 @ r9<- A 5358 GET_VREG(r1, r3) @ r1<- vB 5359 GET_VREG(r0, r9) @ r0<- vA 5360 .if 0 5361 cmp r1, #0 @ is second operand zero? 5362 beq common_errDivideByZero 5363 .endif 5364 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5365 5366 @ optional op; may set condition codes 5367 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5368 GET_INST_OPCODE(ip) @ extract opcode from rINST 5369 SET_VREG(r0, r9) @ vAA<- r0 5370 GOTO_OPCODE(ip) @ jump to next instruction 5371 /* 10-13 instructions */ 5372 5373 5374/* ------------------------------ */ 5375 .balign 64 5376.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5377/* File: armv6t2/OP_DIV_INT_2ADDR.S */ 5378/* File: armv6t2/binop2addr.S */ 5379 /* 5380 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5381 * that specifies an instruction that performs "result = r0 op r1". 5382 * This could be an ARM instruction or a function call. (If the result 5383 * comes back in a register other than r0, you can override "result".) 5384 * 5385 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5386 * vCC (r1). Useful for integer division and modulus. 5387 * 5388 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5389 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5390 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5391 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5392 */ 5393 /* binop/2addr vA, vB */ 5394 mov r3, rINST, lsr #12 @ r3<- B 5395 ubfx r9, rINST, #8, #4 @ r9<- A 5396 GET_VREG(r1, r3) @ r1<- vB 5397 GET_VREG(r0, r9) @ r0<- vA 5398 .if 1 5399 cmp r1, #0 @ is second operand zero? 5400 beq common_errDivideByZero 5401 .endif 5402 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5403 5404 @ optional op; may set condition codes 5405 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5406 GET_INST_OPCODE(ip) @ extract opcode from rINST 5407 SET_VREG(r0, r9) @ vAA<- r0 5408 GOTO_OPCODE(ip) @ jump to next instruction 5409 /* 10-13 instructions */ 5410 5411 5412/* ------------------------------ */ 5413 .balign 64 5414.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5415/* File: armv6t2/OP_REM_INT_2ADDR.S */ 5416/* idivmod returns quotient in r0 and remainder in r1 */ 5417/* File: armv6t2/binop2addr.S */ 5418 /* 5419 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5420 * that specifies an instruction that performs "result = r0 op r1". 5421 * This could be an ARM instruction or a function call. (If the result 5422 * comes back in a register other than r0, you can override "result".) 5423 * 5424 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5425 * vCC (r1). Useful for integer division and modulus. 5426 * 5427 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5428 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5429 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5430 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5431 */ 5432 /* binop/2addr vA, vB */ 5433 mov r3, rINST, lsr #12 @ r3<- B 5434 ubfx r9, rINST, #8, #4 @ r9<- A 5435 GET_VREG(r1, r3) @ r1<- vB 5436 GET_VREG(r0, r9) @ r0<- vA 5437 .if 1 5438 cmp r1, #0 @ is second operand zero? 5439 beq common_errDivideByZero 5440 .endif 5441 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5442 5443 @ optional op; may set condition codes 5444 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5445 GET_INST_OPCODE(ip) @ extract opcode from rINST 5446 SET_VREG(r1, r9) @ vAA<- r1 5447 GOTO_OPCODE(ip) @ jump to next instruction 5448 /* 10-13 instructions */ 5449 5450 5451/* ------------------------------ */ 5452 .balign 64 5453.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5454/* File: armv6t2/OP_AND_INT_2ADDR.S */ 5455/* File: armv6t2/binop2addr.S */ 5456 /* 5457 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5458 * that specifies an instruction that performs "result = r0 op r1". 5459 * This could be an ARM instruction or a function call. (If the result 5460 * comes back in a register other than r0, you can override "result".) 5461 * 5462 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5463 * vCC (r1). Useful for integer division and modulus. 5464 * 5465 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5466 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5467 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5468 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5469 */ 5470 /* binop/2addr vA, vB */ 5471 mov r3, rINST, lsr #12 @ r3<- B 5472 ubfx r9, rINST, #8, #4 @ r9<- A 5473 GET_VREG(r1, r3) @ r1<- vB 5474 GET_VREG(r0, r9) @ r0<- vA 5475 .if 0 5476 cmp r1, #0 @ is second operand zero? 5477 beq common_errDivideByZero 5478 .endif 5479 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5480 5481 @ optional op; may set condition codes 5482 and r0, r0, r1 @ r0<- op, r0-r3 changed 5483 GET_INST_OPCODE(ip) @ extract opcode from rINST 5484 SET_VREG(r0, r9) @ vAA<- r0 5485 GOTO_OPCODE(ip) @ jump to next instruction 5486 /* 10-13 instructions */ 5487 5488 5489/* ------------------------------ */ 5490 .balign 64 5491.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5492/* File: armv6t2/OP_OR_INT_2ADDR.S */ 5493/* File: armv6t2/binop2addr.S */ 5494 /* 5495 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5496 * that specifies an instruction that performs "result = r0 op r1". 5497 * This could be an ARM instruction or a function call. (If the result 5498 * comes back in a register other than r0, you can override "result".) 5499 * 5500 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5501 * vCC (r1). Useful for integer division and modulus. 5502 * 5503 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5504 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5505 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5506 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5507 */ 5508 /* binop/2addr vA, vB */ 5509 mov r3, rINST, lsr #12 @ r3<- B 5510 ubfx r9, rINST, #8, #4 @ r9<- A 5511 GET_VREG(r1, r3) @ r1<- vB 5512 GET_VREG(r0, r9) @ r0<- vA 5513 .if 0 5514 cmp r1, #0 @ is second operand zero? 5515 beq common_errDivideByZero 5516 .endif 5517 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5518 5519 @ optional op; may set condition codes 5520 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5521 GET_INST_OPCODE(ip) @ extract opcode from rINST 5522 SET_VREG(r0, r9) @ vAA<- r0 5523 GOTO_OPCODE(ip) @ jump to next instruction 5524 /* 10-13 instructions */ 5525 5526 5527/* ------------------------------ */ 5528 .balign 64 5529.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5530/* File: armv6t2/OP_XOR_INT_2ADDR.S */ 5531/* File: armv6t2/binop2addr.S */ 5532 /* 5533 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5534 * that specifies an instruction that performs "result = r0 op r1". 5535 * This could be an ARM instruction or a function call. (If the result 5536 * comes back in a register other than r0, you can override "result".) 5537 * 5538 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5539 * vCC (r1). Useful for integer division and modulus. 5540 * 5541 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5542 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5543 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5544 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5545 */ 5546 /* binop/2addr vA, vB */ 5547 mov r3, rINST, lsr #12 @ r3<- B 5548 ubfx r9, rINST, #8, #4 @ r9<- A 5549 GET_VREG(r1, r3) @ r1<- vB 5550 GET_VREG(r0, r9) @ r0<- vA 5551 .if 0 5552 cmp r1, #0 @ is second operand zero? 5553 beq common_errDivideByZero 5554 .endif 5555 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5556 5557 @ optional op; may set condition codes 5558 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5559 GET_INST_OPCODE(ip) @ extract opcode from rINST 5560 SET_VREG(r0, r9) @ vAA<- r0 5561 GOTO_OPCODE(ip) @ jump to next instruction 5562 /* 10-13 instructions */ 5563 5564 5565/* ------------------------------ */ 5566 .balign 64 5567.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5568/* File: armv6t2/OP_SHL_INT_2ADDR.S */ 5569/* File: armv6t2/binop2addr.S */ 5570 /* 5571 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5572 * that specifies an instruction that performs "result = r0 op r1". 5573 * This could be an ARM instruction or a function call. (If the result 5574 * comes back in a register other than r0, you can override "result".) 5575 * 5576 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5577 * vCC (r1). Useful for integer division and modulus. 5578 * 5579 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5580 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5581 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5582 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5583 */ 5584 /* binop/2addr vA, vB */ 5585 mov r3, rINST, lsr #12 @ r3<- B 5586 ubfx r9, rINST, #8, #4 @ r9<- A 5587 GET_VREG(r1, r3) @ r1<- vB 5588 GET_VREG(r0, r9) @ r0<- vA 5589 .if 0 5590 cmp r1, #0 @ is second operand zero? 5591 beq common_errDivideByZero 5592 .endif 5593 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5594 5595 and r1, r1, #31 @ optional op; may set condition codes 5596 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5597 GET_INST_OPCODE(ip) @ extract opcode from rINST 5598 SET_VREG(r0, r9) @ vAA<- r0 5599 GOTO_OPCODE(ip) @ jump to next instruction 5600 /* 10-13 instructions */ 5601 5602 5603/* ------------------------------ */ 5604 .balign 64 5605.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5606/* File: armv6t2/OP_SHR_INT_2ADDR.S */ 5607/* File: armv6t2/binop2addr.S */ 5608 /* 5609 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5610 * that specifies an instruction that performs "result = r0 op r1". 5611 * This could be an ARM instruction or a function call. (If the result 5612 * comes back in a register other than r0, you can override "result".) 5613 * 5614 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5615 * vCC (r1). Useful for integer division and modulus. 5616 * 5617 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5618 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5619 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5620 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5621 */ 5622 /* binop/2addr vA, vB */ 5623 mov r3, rINST, lsr #12 @ r3<- B 5624 ubfx r9, rINST, #8, #4 @ r9<- A 5625 GET_VREG(r1, r3) @ r1<- vB 5626 GET_VREG(r0, r9) @ r0<- vA 5627 .if 0 5628 cmp r1, #0 @ is second operand zero? 5629 beq common_errDivideByZero 5630 .endif 5631 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5632 5633 and r1, r1, #31 @ optional op; may set condition codes 5634 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5635 GET_INST_OPCODE(ip) @ extract opcode from rINST 5636 SET_VREG(r0, r9) @ vAA<- r0 5637 GOTO_OPCODE(ip) @ jump to next instruction 5638 /* 10-13 instructions */ 5639 5640 5641/* ------------------------------ */ 5642 .balign 64 5643.L_OP_USHR_INT_2ADDR: /* 0xba */ 5644/* File: armv6t2/OP_USHR_INT_2ADDR.S */ 5645/* File: armv6t2/binop2addr.S */ 5646 /* 5647 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5648 * that specifies an instruction that performs "result = r0 op r1". 5649 * This could be an ARM instruction or a function call. (If the result 5650 * comes back in a register other than r0, you can override "result".) 5651 * 5652 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5653 * vCC (r1). Useful for integer division and modulus. 5654 * 5655 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5656 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5657 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5658 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5659 */ 5660 /* binop/2addr vA, vB */ 5661 mov r3, rINST, lsr #12 @ r3<- B 5662 ubfx r9, rINST, #8, #4 @ r9<- A 5663 GET_VREG(r1, r3) @ r1<- vB 5664 GET_VREG(r0, r9) @ r0<- vA 5665 .if 0 5666 cmp r1, #0 @ is second operand zero? 5667 beq common_errDivideByZero 5668 .endif 5669 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5670 5671 and r1, r1, #31 @ optional op; may set condition codes 5672 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5673 GET_INST_OPCODE(ip) @ extract opcode from rINST 5674 SET_VREG(r0, r9) @ vAA<- r0 5675 GOTO_OPCODE(ip) @ jump to next instruction 5676 /* 10-13 instructions */ 5677 5678 5679/* ------------------------------ */ 5680 .balign 64 5681.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5682/* File: armv6t2/OP_ADD_LONG_2ADDR.S */ 5683/* File: armv6t2/binopWide2addr.S */ 5684 /* 5685 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5686 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5687 * This could be an ARM instruction or a function call. (If the result 5688 * comes back in a register other than r0, you can override "result".) 5689 * 5690 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5691 * vCC (r1). Useful for integer division and modulus. 5692 * 5693 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5694 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5695 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5696 * rem-double/2addr 5697 */ 5698 /* binop/2addr vA, vB */ 5699 mov r1, rINST, lsr #12 @ r1<- B 5700 ubfx r9, rINST, #8, #4 @ r9<- A 5701 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5702 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5703 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5704 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5705 .if 0 5706 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5707 beq common_errDivideByZero 5708 .endif 5709 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5710 5711 adds r0, r0, r2 @ optional op; may set condition codes 5712 adc r1, r1, r3 @ result<- op, r0-r3 changed 5713 GET_INST_OPCODE(ip) @ extract opcode from rINST 5714 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5715 GOTO_OPCODE(ip) @ jump to next instruction 5716 /* 12-15 instructions */ 5717 5718 5719/* ------------------------------ */ 5720 .balign 64 5721.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5722/* File: armv6t2/OP_SUB_LONG_2ADDR.S */ 5723/* File: armv6t2/binopWide2addr.S */ 5724 /* 5725 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5726 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5727 * This could be an ARM instruction or a function call. (If the result 5728 * comes back in a register other than r0, you can override "result".) 5729 * 5730 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5731 * vCC (r1). Useful for integer division and modulus. 5732 * 5733 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5734 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5735 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5736 * rem-double/2addr 5737 */ 5738 /* binop/2addr vA, vB */ 5739 mov r1, rINST, lsr #12 @ r1<- B 5740 ubfx r9, rINST, #8, #4 @ r9<- A 5741 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5742 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5743 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5744 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5745 .if 0 5746 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5747 beq common_errDivideByZero 5748 .endif 5749 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5750 5751 subs r0, r0, r2 @ optional op; may set condition codes 5752 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5753 GET_INST_OPCODE(ip) @ extract opcode from rINST 5754 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5755 GOTO_OPCODE(ip) @ jump to next instruction 5756 /* 12-15 instructions */ 5757 5758 5759/* ------------------------------ */ 5760 .balign 64 5761.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 5762/* File: armv6t2/OP_MUL_LONG_2ADDR.S */ 5763 /* 5764 * Signed 64-bit integer multiply, "/2addr" version. 5765 * 5766 * See OP_MUL_LONG for an explanation. 5767 * 5768 * We get a little tight on registers, so to avoid looking up &fp[A] 5769 * again we stuff it into rINST. 5770 */ 5771 /* mul-long/2addr vA, vB */ 5772 mov r1, rINST, lsr #12 @ r1<- B 5773 ubfx r9, rINST, #8, #4 @ r9<- A 5774 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5775 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 5776 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5777 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 5778 mul ip, r2, r1 @ ip<- ZxW 5779 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 5780 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 5781 mov r0, rINST @ r0<- &fp[A] (free up rINST) 5782 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5783 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 5784 GET_INST_OPCODE(ip) @ extract opcode from rINST 5785 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 5786 GOTO_OPCODE(ip) @ jump to next instruction 5787 5788/* ------------------------------ */ 5789 .balign 64 5790.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 5791/* File: armv6t2/OP_DIV_LONG_2ADDR.S */ 5792/* File: armv6t2/binopWide2addr.S */ 5793 /* 5794 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5795 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5796 * This could be an ARM instruction or a function call. (If the result 5797 * comes back in a register other than r0, you can override "result".) 5798 * 5799 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5800 * vCC (r1). Useful for integer division and modulus. 5801 * 5802 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5803 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5804 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5805 * rem-double/2addr 5806 */ 5807 /* binop/2addr vA, vB */ 5808 mov r1, rINST, lsr #12 @ r1<- B 5809 ubfx r9, rINST, #8, #4 @ r9<- A 5810 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5811 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5812 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5813 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5814 .if 1 5815 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5816 beq common_errDivideByZero 5817 .endif 5818 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5819 5820 @ optional op; may set condition codes 5821 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5822 GET_INST_OPCODE(ip) @ extract opcode from rINST 5823 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5824 GOTO_OPCODE(ip) @ jump to next instruction 5825 /* 12-15 instructions */ 5826 5827 5828/* ------------------------------ */ 5829 .balign 64 5830.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5831/* File: armv6t2/OP_REM_LONG_2ADDR.S */ 5832/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 5833/* File: armv6t2/binopWide2addr.S */ 5834 /* 5835 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5836 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5837 * This could be an ARM instruction or a function call. (If the result 5838 * comes back in a register other than r0, you can override "result".) 5839 * 5840 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5841 * vCC (r1). Useful for integer division and modulus. 5842 * 5843 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5844 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5845 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5846 * rem-double/2addr 5847 */ 5848 /* binop/2addr vA, vB */ 5849 mov r1, rINST, lsr #12 @ r1<- B 5850 ubfx r9, rINST, #8, #4 @ r9<- A 5851 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5852 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5853 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5854 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5855 .if 1 5856 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5857 beq common_errDivideByZero 5858 .endif 5859 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5860 5861 @ optional op; may set condition codes 5862 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5863 GET_INST_OPCODE(ip) @ extract opcode from rINST 5864 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 5865 GOTO_OPCODE(ip) @ jump to next instruction 5866 /* 12-15 instructions */ 5867 5868 5869/* ------------------------------ */ 5870 .balign 64 5871.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 5872/* File: armv6t2/OP_AND_LONG_2ADDR.S */ 5873/* File: armv6t2/binopWide2addr.S */ 5874 /* 5875 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5876 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5877 * This could be an ARM instruction or a function call. (If the result 5878 * comes back in a register other than r0, you can override "result".) 5879 * 5880 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5881 * vCC (r1). Useful for integer division and modulus. 5882 * 5883 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5884 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5885 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5886 * rem-double/2addr 5887 */ 5888 /* binop/2addr vA, vB */ 5889 mov r1, rINST, lsr #12 @ r1<- B 5890 ubfx r9, rINST, #8, #4 @ r9<- A 5891 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5892 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5893 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5894 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5895 .if 0 5896 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5897 beq common_errDivideByZero 5898 .endif 5899 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5900 5901 and r0, r0, r2 @ optional op; may set condition codes 5902 and r1, r1, r3 @ result<- op, r0-r3 changed 5903 GET_INST_OPCODE(ip) @ extract opcode from rINST 5904 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5905 GOTO_OPCODE(ip) @ jump to next instruction 5906 /* 12-15 instructions */ 5907 5908 5909/* ------------------------------ */ 5910 .balign 64 5911.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 5912/* File: armv6t2/OP_OR_LONG_2ADDR.S */ 5913/* File: armv6t2/binopWide2addr.S */ 5914 /* 5915 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5916 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5917 * This could be an ARM instruction or a function call. (If the result 5918 * comes back in a register other than r0, you can override "result".) 5919 * 5920 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5921 * vCC (r1). Useful for integer division and modulus. 5922 * 5923 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5924 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5925 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5926 * rem-double/2addr 5927 */ 5928 /* binop/2addr vA, vB */ 5929 mov r1, rINST, lsr #12 @ r1<- B 5930 ubfx r9, rINST, #8, #4 @ r9<- A 5931 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5932 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5933 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5934 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5935 .if 0 5936 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5937 beq common_errDivideByZero 5938 .endif 5939 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5940 5941 orr r0, r0, r2 @ optional op; may set condition codes 5942 orr r1, r1, r3 @ result<- op, r0-r3 changed 5943 GET_INST_OPCODE(ip) @ extract opcode from rINST 5944 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5945 GOTO_OPCODE(ip) @ jump to next instruction 5946 /* 12-15 instructions */ 5947 5948 5949/* ------------------------------ */ 5950 .balign 64 5951.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 5952/* File: armv6t2/OP_XOR_LONG_2ADDR.S */ 5953/* File: armv6t2/binopWide2addr.S */ 5954 /* 5955 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5956 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5957 * This could be an ARM instruction or a function call. (If the result 5958 * comes back in a register other than r0, you can override "result".) 5959 * 5960 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5961 * vCC (r1). Useful for integer division and modulus. 5962 * 5963 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5964 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5965 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5966 * rem-double/2addr 5967 */ 5968 /* binop/2addr vA, vB */ 5969 mov r1, rINST, lsr #12 @ r1<- B 5970 ubfx r9, rINST, #8, #4 @ r9<- A 5971 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5972 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5973 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5974 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5975 .if 0 5976 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5977 beq common_errDivideByZero 5978 .endif 5979 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5980 5981 eor r0, r0, r2 @ optional op; may set condition codes 5982 eor r1, r1, r3 @ result<- op, r0-r3 changed 5983 GET_INST_OPCODE(ip) @ extract opcode from rINST 5984 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5985 GOTO_OPCODE(ip) @ jump to next instruction 5986 /* 12-15 instructions */ 5987 5988 5989/* ------------------------------ */ 5990 .balign 64 5991.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 5992/* File: armv6t2/OP_SHL_LONG_2ADDR.S */ 5993 /* 5994 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 5995 * 32-bit shift distance. 5996 */ 5997 /* shl-long/2addr vA, vB */ 5998 mov r3, rINST, lsr #12 @ r3<- B 5999 ubfx r9, rINST, #8, #4 @ r9<- A 6000 GET_VREG(r2, r3) @ r2<- vB 6001 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6002 and r2, r2, #63 @ r2<- r2 & 0x3f 6003 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6004 6005 mov r1, r1, asl r2 @ r1<- r1 << r2 6006 rsb r3, r2, #32 @ r3<- 32 - r2 6007 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 6008 subs ip, r2, #32 @ ip<- r2 - 32 6009 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6010 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 6011 mov r0, r0, asl r2 @ r0<- r0 << r2 6012 b .LOP_SHL_LONG_2ADDR_finish 6013 6014/* ------------------------------ */ 6015 .balign 64 6016.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 6017/* File: armv6t2/OP_SHR_LONG_2ADDR.S */ 6018 /* 6019 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6020 * 32-bit shift distance. 6021 */ 6022 /* shr-long/2addr vA, vB */ 6023 mov r3, rINST, lsr #12 @ r3<- B 6024 ubfx r9, rINST, #8, #4 @ r9<- A 6025 GET_VREG(r2, r3) @ r2<- vB 6026 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6027 and r2, r2, #63 @ r2<- r2 & 0x3f 6028 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6029 6030 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6031 rsb r3, r2, #32 @ r3<- 32 - r2 6032 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6033 subs ip, r2, #32 @ ip<- r2 - 32 6034 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6035 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6036 mov r1, r1, asr r2 @ r1<- r1 >> r2 6037 b .LOP_SHR_LONG_2ADDR_finish 6038 6039/* ------------------------------ */ 6040 .balign 64 6041.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6042/* File: armv6t2/OP_USHR_LONG_2ADDR.S */ 6043 /* 6044 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6045 * 32-bit shift distance. 6046 */ 6047 /* ushr-long/2addr vA, vB */ 6048 mov r3, rINST, lsr #12 @ r3<- B 6049 ubfx r9, rINST, #8, #4 @ r9<- A 6050 GET_VREG(r2, r3) @ r2<- vB 6051 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6052 and r2, r2, #63 @ r2<- r2 & 0x3f 6053 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6054 6055 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6056 rsb r3, r2, #32 @ r3<- 32 - r2 6057 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6058 subs ip, r2, #32 @ ip<- r2 - 32 6059 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6060 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6061 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6062 b .LOP_USHR_LONG_2ADDR_finish 6063 6064/* ------------------------------ */ 6065 .balign 64 6066.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6067/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */ 6068/* File: arm-vfp/fbinop2addr.S */ 6069 /* 6070 * Generic 32-bit floating point "/2addr" binary operation. Provide 6071 * an "instr" line that specifies an instruction that performs 6072 * "s2 = s0 op s1". 6073 * 6074 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6075 */ 6076 /* binop/2addr vA, vB */ 6077 mov r3, rINST, lsr #12 @ r3<- B 6078 mov r9, rINST, lsr #8 @ r9<- A+ 6079 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6080 and r9, r9, #15 @ r9<- A 6081 flds s1, [r3] @ s1<- vB 6082 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6083 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6084 flds s0, [r9] @ s0<- vA 6085 6086 fadds s2, s0, s1 @ s2<- op 6087 GET_INST_OPCODE(ip) @ extract opcode from rINST 6088 fsts s2, [r9] @ vAA<- s2 6089 GOTO_OPCODE(ip) @ jump to next instruction 6090 6091 6092/* ------------------------------ */ 6093 .balign 64 6094.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6095/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */ 6096/* File: arm-vfp/fbinop2addr.S */ 6097 /* 6098 * Generic 32-bit floating point "/2addr" binary operation. Provide 6099 * an "instr" line that specifies an instruction that performs 6100 * "s2 = s0 op s1". 6101 * 6102 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6103 */ 6104 /* binop/2addr vA, vB */ 6105 mov r3, rINST, lsr #12 @ r3<- B 6106 mov r9, rINST, lsr #8 @ r9<- A+ 6107 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6108 and r9, r9, #15 @ r9<- A 6109 flds s1, [r3] @ s1<- vB 6110 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6111 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6112 flds s0, [r9] @ s0<- vA 6113 6114 fsubs s2, s0, s1 @ s2<- op 6115 GET_INST_OPCODE(ip) @ extract opcode from rINST 6116 fsts s2, [r9] @ vAA<- s2 6117 GOTO_OPCODE(ip) @ jump to next instruction 6118 6119 6120/* ------------------------------ */ 6121 .balign 64 6122.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6123/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */ 6124/* File: arm-vfp/fbinop2addr.S */ 6125 /* 6126 * Generic 32-bit floating point "/2addr" binary operation. Provide 6127 * an "instr" line that specifies an instruction that performs 6128 * "s2 = s0 op s1". 6129 * 6130 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6131 */ 6132 /* binop/2addr vA, vB */ 6133 mov r3, rINST, lsr #12 @ r3<- B 6134 mov r9, rINST, lsr #8 @ r9<- A+ 6135 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6136 and r9, r9, #15 @ r9<- A 6137 flds s1, [r3] @ s1<- vB 6138 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6139 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6140 flds s0, [r9] @ s0<- vA 6141 6142 fmuls s2, s0, s1 @ s2<- op 6143 GET_INST_OPCODE(ip) @ extract opcode from rINST 6144 fsts s2, [r9] @ vAA<- s2 6145 GOTO_OPCODE(ip) @ jump to next instruction 6146 6147 6148/* ------------------------------ */ 6149 .balign 64 6150.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6151/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */ 6152/* File: arm-vfp/fbinop2addr.S */ 6153 /* 6154 * Generic 32-bit floating point "/2addr" binary operation. Provide 6155 * an "instr" line that specifies an instruction that performs 6156 * "s2 = s0 op s1". 6157 * 6158 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6159 */ 6160 /* binop/2addr vA, vB */ 6161 mov r3, rINST, lsr #12 @ r3<- B 6162 mov r9, rINST, lsr #8 @ r9<- A+ 6163 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6164 and r9, r9, #15 @ r9<- A 6165 flds s1, [r3] @ s1<- vB 6166 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6167 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6168 flds s0, [r9] @ s0<- vA 6169 6170 fdivs s2, s0, s1 @ s2<- op 6171 GET_INST_OPCODE(ip) @ extract opcode from rINST 6172 fsts s2, [r9] @ vAA<- s2 6173 GOTO_OPCODE(ip) @ jump to next instruction 6174 6175 6176/* ------------------------------ */ 6177 .balign 64 6178.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6179/* File: armv6t2/OP_REM_FLOAT_2ADDR.S */ 6180/* EABI doesn't define a float remainder function, but libm does */ 6181/* File: armv6t2/binop2addr.S */ 6182 /* 6183 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6184 * that specifies an instruction that performs "result = r0 op r1". 6185 * This could be an ARM instruction or a function call. (If the result 6186 * comes back in a register other than r0, you can override "result".) 6187 * 6188 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6189 * vCC (r1). Useful for integer division and modulus. 6190 * 6191 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6192 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6193 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6194 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6195 */ 6196 /* binop/2addr vA, vB */ 6197 mov r3, rINST, lsr #12 @ r3<- B 6198 ubfx r9, rINST, #8, #4 @ r9<- A 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: armv6t2/OP_REM_DOUBLE_2ADDR.S */ 6335/* EABI doesn't define a double remainder function, but libm does */ 6336/* File: armv6t2/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 r1, rINST, lsr #12 @ r1<- B 6353 ubfx r9, rINST, #8, #4 @ r9<- A 6354 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6355 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6356 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6357 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6358 .if 0 6359 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6360 beq common_errDivideByZero 6361 .endif 6362 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6363 6364 @ optional op; may set condition codes 6365 bl fmod @ result<- op, r0-r3 changed 6366 GET_INST_OPCODE(ip) @ extract opcode from rINST 6367 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6368 GOTO_OPCODE(ip) @ jump to next instruction 6369 /* 12-15 instructions */ 6370 6371 6372/* ------------------------------ */ 6373 .balign 64 6374.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6375/* File: armv6t2/OP_ADD_INT_LIT16.S */ 6376/* File: armv6t2/binopLit16.S */ 6377 /* 6378 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6379 * that specifies an instruction that performs "result = r0 op r1". 6380 * This could be an ARM instruction or a function call. (If the result 6381 * comes back in a register other than r0, you can override "result".) 6382 * 6383 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6384 * vCC (r1). Useful for integer division and modulus. 6385 * 6386 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6387 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6388 */ 6389 /* binop/lit16 vA, vB, #+CCCC */ 6390 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6391 mov r2, rINST, lsr #12 @ r2<- B 6392 ubfx r9, rINST, #8, #4 @ r9<- A 6393 GET_VREG(r0, r2) @ r0<- vB 6394 .if 0 6395 cmp r1, #0 @ is second operand zero? 6396 beq common_errDivideByZero 6397 .endif 6398 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6399 6400 add r0, r0, r1 @ r0<- op, r0-r3 changed 6401 GET_INST_OPCODE(ip) @ extract opcode from rINST 6402 SET_VREG(r0, r9) @ vAA<- r0 6403 GOTO_OPCODE(ip) @ jump to next instruction 6404 /* 10-13 instructions */ 6405 6406 6407/* ------------------------------ */ 6408 .balign 64 6409.L_OP_RSUB_INT: /* 0xd1 */ 6410/* File: armv6t2/OP_RSUB_INT.S */ 6411/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6412/* File: armv6t2/binopLit16.S */ 6413 /* 6414 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6415 * that specifies an instruction that performs "result = r0 op r1". 6416 * This could be an ARM instruction or a function call. (If the result 6417 * comes back in a register other than r0, you can override "result".) 6418 * 6419 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6420 * vCC (r1). Useful for integer division and modulus. 6421 * 6422 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6423 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6424 */ 6425 /* binop/lit16 vA, vB, #+CCCC */ 6426 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6427 mov r2, rINST, lsr #12 @ r2<- B 6428 ubfx r9, rINST, #8, #4 @ r9<- A 6429 GET_VREG(r0, r2) @ r0<- vB 6430 .if 0 6431 cmp r1, #0 @ is second operand zero? 6432 beq common_errDivideByZero 6433 .endif 6434 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6435 6436 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6437 GET_INST_OPCODE(ip) @ extract opcode from rINST 6438 SET_VREG(r0, r9) @ vAA<- r0 6439 GOTO_OPCODE(ip) @ jump to next instruction 6440 /* 10-13 instructions */ 6441 6442 6443/* ------------------------------ */ 6444 .balign 64 6445.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6446/* File: armv6t2/OP_MUL_INT_LIT16.S */ 6447/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6448/* File: armv6t2/binopLit16.S */ 6449 /* 6450 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6451 * that specifies an instruction that performs "result = r0 op r1". 6452 * This could be an ARM instruction or a function call. (If the result 6453 * comes back in a register other than r0, you can override "result".) 6454 * 6455 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6456 * vCC (r1). Useful for integer division and modulus. 6457 * 6458 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6459 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6460 */ 6461 /* binop/lit16 vA, vB, #+CCCC */ 6462 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6463 mov r2, rINST, lsr #12 @ r2<- B 6464 ubfx r9, rINST, #8, #4 @ r9<- A 6465 GET_VREG(r0, r2) @ r0<- vB 6466 .if 0 6467 cmp r1, #0 @ is second operand zero? 6468 beq common_errDivideByZero 6469 .endif 6470 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6471 6472 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6473 GET_INST_OPCODE(ip) @ extract opcode from rINST 6474 SET_VREG(r0, r9) @ vAA<- r0 6475 GOTO_OPCODE(ip) @ jump to next instruction 6476 /* 10-13 instructions */ 6477 6478 6479/* ------------------------------ */ 6480 .balign 64 6481.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6482/* File: armv6t2/OP_DIV_INT_LIT16.S */ 6483/* File: armv6t2/binopLit16.S */ 6484 /* 6485 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6486 * that specifies an instruction that performs "result = r0 op r1". 6487 * This could be an ARM instruction or a function call. (If the result 6488 * comes back in a register other than r0, you can override "result".) 6489 * 6490 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6491 * vCC (r1). Useful for integer division and modulus. 6492 * 6493 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6494 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6495 */ 6496 /* binop/lit16 vA, vB, #+CCCC */ 6497 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6498 mov r2, rINST, lsr #12 @ r2<- B 6499 ubfx r9, rINST, #8, #4 @ r9<- A 6500 GET_VREG(r0, r2) @ r0<- vB 6501 .if 1 6502 cmp r1, #0 @ is second operand zero? 6503 beq common_errDivideByZero 6504 .endif 6505 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6506 6507 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6508 GET_INST_OPCODE(ip) @ extract opcode from rINST 6509 SET_VREG(r0, r9) @ vAA<- r0 6510 GOTO_OPCODE(ip) @ jump to next instruction 6511 /* 10-13 instructions */ 6512 6513 6514/* ------------------------------ */ 6515 .balign 64 6516.L_OP_REM_INT_LIT16: /* 0xd4 */ 6517/* File: armv6t2/OP_REM_INT_LIT16.S */ 6518/* idivmod returns quotient in r0 and remainder in r1 */ 6519/* File: armv6t2/binopLit16.S */ 6520 /* 6521 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6522 * that specifies an instruction that performs "result = r0 op r1". 6523 * This could be an ARM instruction or a function call. (If the result 6524 * comes back in a register other than r0, you can override "result".) 6525 * 6526 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6527 * vCC (r1). Useful for integer division and modulus. 6528 * 6529 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6530 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6531 */ 6532 /* binop/lit16 vA, vB, #+CCCC */ 6533 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6534 mov r2, rINST, lsr #12 @ r2<- B 6535 ubfx r9, rINST, #8, #4 @ r9<- A 6536 GET_VREG(r0, r2) @ r0<- vB 6537 .if 1 6538 cmp r1, #0 @ is second operand zero? 6539 beq common_errDivideByZero 6540 .endif 6541 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6542 6543 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6544 GET_INST_OPCODE(ip) @ extract opcode from rINST 6545 SET_VREG(r1, r9) @ vAA<- r1 6546 GOTO_OPCODE(ip) @ jump to next instruction 6547 /* 10-13 instructions */ 6548 6549 6550/* ------------------------------ */ 6551 .balign 64 6552.L_OP_AND_INT_LIT16: /* 0xd5 */ 6553/* File: armv6t2/OP_AND_INT_LIT16.S */ 6554/* File: armv6t2/binopLit16.S */ 6555 /* 6556 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6557 * that specifies an instruction that performs "result = r0 op r1". 6558 * This could be an ARM instruction or a function call. (If the result 6559 * comes back in a register other than r0, you can override "result".) 6560 * 6561 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6562 * vCC (r1). Useful for integer division and modulus. 6563 * 6564 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6565 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6566 */ 6567 /* binop/lit16 vA, vB, #+CCCC */ 6568 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6569 mov r2, rINST, lsr #12 @ r2<- B 6570 ubfx r9, rINST, #8, #4 @ r9<- A 6571 GET_VREG(r0, r2) @ r0<- vB 6572 .if 0 6573 cmp r1, #0 @ is second operand zero? 6574 beq common_errDivideByZero 6575 .endif 6576 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6577 6578 and r0, r0, r1 @ r0<- op, r0-r3 changed 6579 GET_INST_OPCODE(ip) @ extract opcode from rINST 6580 SET_VREG(r0, r9) @ vAA<- r0 6581 GOTO_OPCODE(ip) @ jump to next instruction 6582 /* 10-13 instructions */ 6583 6584 6585/* ------------------------------ */ 6586 .balign 64 6587.L_OP_OR_INT_LIT16: /* 0xd6 */ 6588/* File: armv6t2/OP_OR_INT_LIT16.S */ 6589/* File: armv6t2/binopLit16.S */ 6590 /* 6591 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6592 * that specifies an instruction that performs "result = r0 op r1". 6593 * This could be an ARM instruction or a function call. (If the result 6594 * comes back in a register other than r0, you can override "result".) 6595 * 6596 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6597 * vCC (r1). Useful for integer division and modulus. 6598 * 6599 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6600 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6601 */ 6602 /* binop/lit16 vA, vB, #+CCCC */ 6603 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6604 mov r2, rINST, lsr #12 @ r2<- B 6605 ubfx r9, rINST, #8, #4 @ r9<- A 6606 GET_VREG(r0, r2) @ r0<- vB 6607 .if 0 6608 cmp r1, #0 @ is second operand zero? 6609 beq common_errDivideByZero 6610 .endif 6611 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6612 6613 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6614 GET_INST_OPCODE(ip) @ extract opcode from rINST 6615 SET_VREG(r0, r9) @ vAA<- r0 6616 GOTO_OPCODE(ip) @ jump to next instruction 6617 /* 10-13 instructions */ 6618 6619 6620/* ------------------------------ */ 6621 .balign 64 6622.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6623/* File: armv6t2/OP_XOR_INT_LIT16.S */ 6624/* File: armv6t2/binopLit16.S */ 6625 /* 6626 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6627 * that specifies an instruction that performs "result = r0 op r1". 6628 * This could be an ARM instruction or a function call. (If the result 6629 * comes back in a register other than r0, you can override "result".) 6630 * 6631 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6632 * vCC (r1). Useful for integer division and modulus. 6633 * 6634 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6635 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6636 */ 6637 /* binop/lit16 vA, vB, #+CCCC */ 6638 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6639 mov r2, rINST, lsr #12 @ r2<- B 6640 ubfx r9, rINST, #8, #4 @ r9<- A 6641 GET_VREG(r0, r2) @ r0<- vB 6642 .if 0 6643 cmp r1, #0 @ is second operand zero? 6644 beq common_errDivideByZero 6645 .endif 6646 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6647 6648 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6649 GET_INST_OPCODE(ip) @ extract opcode from rINST 6650 SET_VREG(r0, r9) @ vAA<- r0 6651 GOTO_OPCODE(ip) @ jump to next instruction 6652 /* 10-13 instructions */ 6653 6654 6655/* ------------------------------ */ 6656 .balign 64 6657.L_OP_ADD_INT_LIT8: /* 0xd8 */ 6658/* File: armv5te/OP_ADD_INT_LIT8.S */ 6659/* File: armv5te/binopLit8.S */ 6660 /* 6661 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6662 * that specifies an instruction that performs "result = r0 op r1". 6663 * This could be an ARM instruction or a function call. (If the result 6664 * comes back in a register other than r0, you can override "result".) 6665 * 6666 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6667 * vCC (r1). Useful for integer division and modulus. 6668 * 6669 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6670 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6671 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6672 */ 6673 /* binop/lit8 vAA, vBB, #+CC */ 6674 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6675 mov r9, rINST, lsr #8 @ r9<- AA 6676 and r2, r3, #255 @ r2<- BB 6677 GET_VREG(r0, r2) @ r0<- vBB 6678 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6679 .if 0 6680 @cmp r1, #0 @ is second operand zero? 6681 beq common_errDivideByZero 6682 .endif 6683 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6684 6685 @ optional op; may set condition codes 6686 add r0, r0, r1 @ r0<- op, r0-r3 changed 6687 GET_INST_OPCODE(ip) @ extract opcode from rINST 6688 SET_VREG(r0, r9) @ vAA<- r0 6689 GOTO_OPCODE(ip) @ jump to next instruction 6690 /* 10-12 instructions */ 6691 6692 6693/* ------------------------------ */ 6694 .balign 64 6695.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 6696/* File: armv5te/OP_RSUB_INT_LIT8.S */ 6697/* File: armv5te/binopLit8.S */ 6698 /* 6699 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6700 * that specifies an instruction that performs "result = r0 op r1". 6701 * This could be an ARM instruction or a function call. (If the result 6702 * comes back in a register other than r0, you can override "result".) 6703 * 6704 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6705 * vCC (r1). Useful for integer division and modulus. 6706 * 6707 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6708 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6709 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6710 */ 6711 /* binop/lit8 vAA, vBB, #+CC */ 6712 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6713 mov r9, rINST, lsr #8 @ r9<- AA 6714 and r2, r3, #255 @ r2<- BB 6715 GET_VREG(r0, r2) @ r0<- vBB 6716 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6717 .if 0 6718 @cmp r1, #0 @ is second operand zero? 6719 beq common_errDivideByZero 6720 .endif 6721 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6722 6723 @ optional op; may set condition codes 6724 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6725 GET_INST_OPCODE(ip) @ extract opcode from rINST 6726 SET_VREG(r0, r9) @ vAA<- r0 6727 GOTO_OPCODE(ip) @ jump to next instruction 6728 /* 10-12 instructions */ 6729 6730 6731/* ------------------------------ */ 6732 .balign 64 6733.L_OP_MUL_INT_LIT8: /* 0xda */ 6734/* File: armv5te/OP_MUL_INT_LIT8.S */ 6735/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6736/* File: armv5te/binopLit8.S */ 6737 /* 6738 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6739 * that specifies an instruction that performs "result = r0 op r1". 6740 * This could be an ARM instruction or a function call. (If the result 6741 * comes back in a register other than r0, you can override "result".) 6742 * 6743 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6744 * vCC (r1). Useful for integer division and modulus. 6745 * 6746 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6747 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6748 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6749 */ 6750 /* binop/lit8 vAA, vBB, #+CC */ 6751 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6752 mov r9, rINST, lsr #8 @ r9<- AA 6753 and r2, r3, #255 @ r2<- BB 6754 GET_VREG(r0, r2) @ r0<- vBB 6755 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6756 .if 0 6757 @cmp r1, #0 @ is second operand zero? 6758 beq common_errDivideByZero 6759 .endif 6760 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6761 6762 @ optional op; may set condition codes 6763 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6764 GET_INST_OPCODE(ip) @ extract opcode from rINST 6765 SET_VREG(r0, r9) @ vAA<- r0 6766 GOTO_OPCODE(ip) @ jump to next instruction 6767 /* 10-12 instructions */ 6768 6769 6770/* ------------------------------ */ 6771 .balign 64 6772.L_OP_DIV_INT_LIT8: /* 0xdb */ 6773/* File: armv5te/OP_DIV_INT_LIT8.S */ 6774/* File: armv5te/binopLit8.S */ 6775 /* 6776 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6777 * that specifies an instruction that performs "result = r0 op r1". 6778 * This could be an ARM instruction or a function call. (If the result 6779 * comes back in a register other than r0, you can override "result".) 6780 * 6781 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6782 * vCC (r1). Useful for integer division and modulus. 6783 * 6784 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6785 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6786 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6787 */ 6788 /* binop/lit8 vAA, vBB, #+CC */ 6789 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6790 mov r9, rINST, lsr #8 @ r9<- AA 6791 and r2, r3, #255 @ r2<- BB 6792 GET_VREG(r0, r2) @ r0<- vBB 6793 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6794 .if 1 6795 @cmp r1, #0 @ is second operand zero? 6796 beq common_errDivideByZero 6797 .endif 6798 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6799 6800 @ optional op; may set condition codes 6801 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6802 GET_INST_OPCODE(ip) @ extract opcode from rINST 6803 SET_VREG(r0, r9) @ vAA<- r0 6804 GOTO_OPCODE(ip) @ jump to next instruction 6805 /* 10-12 instructions */ 6806 6807 6808/* ------------------------------ */ 6809 .balign 64 6810.L_OP_REM_INT_LIT8: /* 0xdc */ 6811/* File: armv5te/OP_REM_INT_LIT8.S */ 6812/* idivmod returns quotient in r0 and remainder in r1 */ 6813/* File: armv5te/binopLit8.S */ 6814 /* 6815 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6816 * that specifies an instruction that performs "result = r0 op r1". 6817 * This could be an ARM instruction or a function call. (If the result 6818 * comes back in a register other than r0, you can override "result".) 6819 * 6820 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6821 * vCC (r1). Useful for integer division and modulus. 6822 * 6823 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6824 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6825 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6826 */ 6827 /* binop/lit8 vAA, vBB, #+CC */ 6828 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6829 mov r9, rINST, lsr #8 @ r9<- AA 6830 and r2, r3, #255 @ r2<- BB 6831 GET_VREG(r0, r2) @ r0<- vBB 6832 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6833 .if 1 6834 @cmp r1, #0 @ is second operand zero? 6835 beq common_errDivideByZero 6836 .endif 6837 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6838 6839 @ optional op; may set condition codes 6840 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6841 GET_INST_OPCODE(ip) @ extract opcode from rINST 6842 SET_VREG(r1, r9) @ vAA<- r1 6843 GOTO_OPCODE(ip) @ jump to next instruction 6844 /* 10-12 instructions */ 6845 6846 6847/* ------------------------------ */ 6848 .balign 64 6849.L_OP_AND_INT_LIT8: /* 0xdd */ 6850/* File: armv5te/OP_AND_INT_LIT8.S */ 6851/* File: armv5te/binopLit8.S */ 6852 /* 6853 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6854 * that specifies an instruction that performs "result = r0 op r1". 6855 * This could be an ARM instruction or a function call. (If the result 6856 * comes back in a register other than r0, you can override "result".) 6857 * 6858 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6859 * vCC (r1). Useful for integer division and modulus. 6860 * 6861 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6862 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6863 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6864 */ 6865 /* binop/lit8 vAA, vBB, #+CC */ 6866 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6867 mov r9, rINST, lsr #8 @ r9<- AA 6868 and r2, r3, #255 @ r2<- BB 6869 GET_VREG(r0, r2) @ r0<- vBB 6870 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6871 .if 0 6872 @cmp r1, #0 @ is second operand zero? 6873 beq common_errDivideByZero 6874 .endif 6875 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6876 6877 @ optional op; may set condition codes 6878 and r0, r0, r1 @ r0<- op, r0-r3 changed 6879 GET_INST_OPCODE(ip) @ extract opcode from rINST 6880 SET_VREG(r0, r9) @ vAA<- r0 6881 GOTO_OPCODE(ip) @ jump to next instruction 6882 /* 10-12 instructions */ 6883 6884 6885/* ------------------------------ */ 6886 .balign 64 6887.L_OP_OR_INT_LIT8: /* 0xde */ 6888/* File: armv5te/OP_OR_INT_LIT8.S */ 6889/* File: armv5te/binopLit8.S */ 6890 /* 6891 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6892 * that specifies an instruction that performs "result = r0 op r1". 6893 * This could be an ARM instruction or a function call. (If the result 6894 * comes back in a register other than r0, you can override "result".) 6895 * 6896 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6897 * vCC (r1). Useful for integer division and modulus. 6898 * 6899 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6900 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6901 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6902 */ 6903 /* binop/lit8 vAA, vBB, #+CC */ 6904 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6905 mov r9, rINST, lsr #8 @ r9<- AA 6906 and r2, r3, #255 @ r2<- BB 6907 GET_VREG(r0, r2) @ r0<- vBB 6908 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6909 .if 0 6910 @cmp r1, #0 @ is second operand zero? 6911 beq common_errDivideByZero 6912 .endif 6913 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6914 6915 @ optional op; may set condition codes 6916 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6917 GET_INST_OPCODE(ip) @ extract opcode from rINST 6918 SET_VREG(r0, r9) @ vAA<- r0 6919 GOTO_OPCODE(ip) @ jump to next instruction 6920 /* 10-12 instructions */ 6921 6922 6923/* ------------------------------ */ 6924 .balign 64 6925.L_OP_XOR_INT_LIT8: /* 0xdf */ 6926/* File: armv5te/OP_XOR_INT_LIT8.S */ 6927/* File: armv5te/binopLit8.S */ 6928 /* 6929 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6930 * that specifies an instruction that performs "result = r0 op r1". 6931 * This could be an ARM instruction or a function call. (If the result 6932 * comes back in a register other than r0, you can override "result".) 6933 * 6934 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6935 * vCC (r1). Useful for integer division and modulus. 6936 * 6937 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6938 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6939 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6940 */ 6941 /* binop/lit8 vAA, vBB, #+CC */ 6942 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6943 mov r9, rINST, lsr #8 @ r9<- AA 6944 and r2, r3, #255 @ r2<- BB 6945 GET_VREG(r0, r2) @ r0<- vBB 6946 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6947 .if 0 6948 @cmp r1, #0 @ is second operand zero? 6949 beq common_errDivideByZero 6950 .endif 6951 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6952 6953 @ optional op; may set condition codes 6954 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6955 GET_INST_OPCODE(ip) @ extract opcode from rINST 6956 SET_VREG(r0, r9) @ vAA<- r0 6957 GOTO_OPCODE(ip) @ jump to next instruction 6958 /* 10-12 instructions */ 6959 6960 6961/* ------------------------------ */ 6962 .balign 64 6963.L_OP_SHL_INT_LIT8: /* 0xe0 */ 6964/* File: armv5te/OP_SHL_INT_LIT8.S */ 6965/* File: armv5te/binopLit8.S */ 6966 /* 6967 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6968 * that specifies an instruction that performs "result = r0 op r1". 6969 * This could be an ARM instruction or a function call. (If the result 6970 * comes back in a register other than r0, you can override "result".) 6971 * 6972 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6973 * vCC (r1). Useful for integer division and modulus. 6974 * 6975 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6976 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6977 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6978 */ 6979 /* binop/lit8 vAA, vBB, #+CC */ 6980 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6981 mov r9, rINST, lsr #8 @ r9<- AA 6982 and r2, r3, #255 @ r2<- BB 6983 GET_VREG(r0, r2) @ r0<- vBB 6984 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6985 .if 0 6986 @cmp r1, #0 @ is second operand zero? 6987 beq common_errDivideByZero 6988 .endif 6989 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6990 6991 and r1, r1, #31 @ optional op; may set condition codes 6992 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 6993 GET_INST_OPCODE(ip) @ extract opcode from rINST 6994 SET_VREG(r0, r9) @ vAA<- r0 6995 GOTO_OPCODE(ip) @ jump to next instruction 6996 /* 10-12 instructions */ 6997 6998 6999/* ------------------------------ */ 7000 .balign 64 7001.L_OP_SHR_INT_LIT8: /* 0xe1 */ 7002/* File: armv5te/OP_SHR_INT_LIT8.S */ 7003/* File: armv5te/binopLit8.S */ 7004 /* 7005 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7006 * that specifies an instruction that performs "result = r0 op r1". 7007 * This could be an ARM instruction or a function call. (If the result 7008 * comes back in a register other than r0, you can override "result".) 7009 * 7010 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7011 * vCC (r1). Useful for integer division and modulus. 7012 * 7013 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7014 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7015 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7016 */ 7017 /* binop/lit8 vAA, vBB, #+CC */ 7018 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7019 mov r9, rINST, lsr #8 @ r9<- AA 7020 and r2, r3, #255 @ r2<- BB 7021 GET_VREG(r0, r2) @ r0<- vBB 7022 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7023 .if 0 7024 @cmp r1, #0 @ is second operand zero? 7025 beq common_errDivideByZero 7026 .endif 7027 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7028 7029 and r1, r1, #31 @ optional op; may set condition codes 7030 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7031 GET_INST_OPCODE(ip) @ extract opcode from rINST 7032 SET_VREG(r0, r9) @ vAA<- r0 7033 GOTO_OPCODE(ip) @ jump to next instruction 7034 /* 10-12 instructions */ 7035 7036 7037/* ------------------------------ */ 7038 .balign 64 7039.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7040/* File: armv5te/OP_USHR_INT_LIT8.S */ 7041/* File: armv5te/binopLit8.S */ 7042 /* 7043 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7044 * that specifies an instruction that performs "result = r0 op r1". 7045 * This could be an ARM instruction or a function call. (If the result 7046 * comes back in a register other than r0, you can override "result".) 7047 * 7048 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7049 * vCC (r1). Useful for integer division and modulus. 7050 * 7051 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7052 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7053 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7054 */ 7055 /* binop/lit8 vAA, vBB, #+CC */ 7056 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7057 mov r9, rINST, lsr #8 @ r9<- AA 7058 and r2, r3, #255 @ r2<- BB 7059 GET_VREG(r0, r2) @ r0<- vBB 7060 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7061 .if 0 7062 @cmp r1, #0 @ is second operand zero? 7063 beq common_errDivideByZero 7064 .endif 7065 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7066 7067 and r1, r1, #31 @ optional op; may set condition codes 7068 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7069 GET_INST_OPCODE(ip) @ extract opcode from rINST 7070 SET_VREG(r0, r9) @ vAA<- r0 7071 GOTO_OPCODE(ip) @ jump to next instruction 7072 /* 10-12 instructions */ 7073 7074 7075/* ------------------------------ */ 7076 .balign 64 7077.L_OP_IGET_VOLATILE: /* 0xe3 */ 7078/* File: armv5te/OP_IGET_VOLATILE.S */ 7079/* File: armv5te/OP_IGET.S */ 7080 /* 7081 * General 32-bit instance field get. 7082 * 7083 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7084 */ 7085 /* op vA, vB, field@CCCC */ 7086 mov r0, rINST, lsr #12 @ r0<- B 7087 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7088 FETCH(r1, 1) @ r1<- field ref CCCC 7089 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7090 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7091 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7092 cmp r0, #0 @ is resolved entry null? 7093 bne .LOP_IGET_VOLATILE_finish @ no, already resolved 70948: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7095 EXPORT_PC() @ resolve() could throw 7096 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7097 bl dvmResolveInstField @ r0<- resolved InstField ptr 7098 cmp r0, #0 7099 bne .LOP_IGET_VOLATILE_finish 7100 b common_exceptionThrown 7101 7102 7103/* ------------------------------ */ 7104 .balign 64 7105.L_OP_IPUT_VOLATILE: /* 0xe4 */ 7106/* File: armv5te/OP_IPUT_VOLATILE.S */ 7107/* File: armv5te/OP_IPUT.S */ 7108 /* 7109 * General 32-bit instance field put. 7110 * 7111 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 7112 */ 7113 /* op vA, vB, field@CCCC */ 7114 mov r0, rINST, lsr #12 @ r0<- B 7115 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7116 FETCH(r1, 1) @ r1<- field ref CCCC 7117 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7118 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7119 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7120 cmp r0, #0 @ is resolved entry null? 7121 bne .LOP_IPUT_VOLATILE_finish @ no, already resolved 71228: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7123 EXPORT_PC() @ resolve() could throw 7124 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7125 bl dvmResolveInstField @ r0<- resolved InstField ptr 7126 cmp r0, #0 @ success? 7127 bne .LOP_IPUT_VOLATILE_finish @ yes, finish up 7128 b common_exceptionThrown 7129 7130 7131/* ------------------------------ */ 7132 .balign 64 7133.L_OP_SGET_VOLATILE: /* 0xe5 */ 7134/* File: armv5te/OP_SGET_VOLATILE.S */ 7135/* File: armv5te/OP_SGET.S */ 7136 /* 7137 * General 32-bit SGET handler. 7138 * 7139 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7140 */ 7141 /* op vAA, field@BBBB */ 7142 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7143 FETCH(r1, 1) @ r1<- field ref BBBB 7144 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7145 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7146 cmp r0, #0 @ is resolved entry null? 7147 beq .LOP_SGET_VOLATILE_resolve @ yes, do resolve 7148.LOP_SGET_VOLATILE_finish: @ field ptr in r0 7149 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7150 SMP_DMB @ acquiring load 7151 mov r2, rINST, lsr #8 @ r2<- AA 7152 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7153 SET_VREG(r1, r2) @ fp[AA]<- r1 7154 GET_INST_OPCODE(ip) @ extract opcode from rINST 7155 GOTO_OPCODE(ip) @ jump to next instruction 7156 7157 7158/* ------------------------------ */ 7159 .balign 64 7160.L_OP_SPUT_VOLATILE: /* 0xe6 */ 7161/* File: armv5te/OP_SPUT_VOLATILE.S */ 7162/* File: armv5te/OP_SPUT.S */ 7163 /* 7164 * General 32-bit SPUT handler. 7165 * 7166 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 7167 */ 7168 /* op vAA, field@BBBB */ 7169 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7170 FETCH(r1, 1) @ r1<- field ref BBBB 7171 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7172 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7173 cmp r0, #0 @ is resolved entry null? 7174 beq .LOP_SPUT_VOLATILE_resolve @ yes, do resolve 7175.LOP_SPUT_VOLATILE_finish: @ field ptr in r0 7176 mov r2, rINST, lsr #8 @ r2<- AA 7177 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7178 GET_VREG(r1, r2) @ r1<- fp[AA] 7179 GET_INST_OPCODE(ip) @ extract opcode from rINST 7180 SMP_DMB @ releasing store 7181 str r1, [r0, #offStaticField_value] @ field<- vAA 7182 GOTO_OPCODE(ip) @ jump to next instruction 7183 7184 7185/* ------------------------------ */ 7186 .balign 64 7187.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ 7188/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */ 7189/* File: armv5te/OP_IGET.S */ 7190 /* 7191 * General 32-bit instance field get. 7192 * 7193 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7194 */ 7195 /* op vA, vB, field@CCCC */ 7196 mov r0, rINST, lsr #12 @ r0<- B 7197 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7198 FETCH(r1, 1) @ r1<- field ref CCCC 7199 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7200 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7201 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7202 cmp r0, #0 @ is resolved entry null? 7203 bne .LOP_IGET_OBJECT_VOLATILE_finish @ no, already resolved 72048: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7205 EXPORT_PC() @ resolve() could throw 7206 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7207 bl dvmResolveInstField @ r0<- resolved InstField ptr 7208 cmp r0, #0 7209 bne .LOP_IGET_OBJECT_VOLATILE_finish 7210 b common_exceptionThrown 7211 7212 7213/* ------------------------------ */ 7214 .balign 64 7215.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */ 7216/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */ 7217/* File: armv5te/OP_IGET_WIDE.S */ 7218 /* 7219 * Wide 32-bit instance field get. 7220 */ 7221 /* iget-wide vA, vB, field@CCCC */ 7222 mov r0, rINST, lsr #12 @ r0<- B 7223 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7224 FETCH(r1, 1) @ r1<- field ref CCCC 7225 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7226 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7227 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7228 cmp r0, #0 @ is resolved entry null? 7229 bne .LOP_IGET_WIDE_VOLATILE_finish @ no, already resolved 72308: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7231 EXPORT_PC() @ resolve() could throw 7232 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7233 bl dvmResolveInstField @ r0<- resolved InstField ptr 7234 cmp r0, #0 7235 bne .LOP_IGET_WIDE_VOLATILE_finish 7236 b common_exceptionThrown 7237 7238 7239/* ------------------------------ */ 7240 .balign 64 7241.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */ 7242/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */ 7243/* File: armv5te/OP_IPUT_WIDE.S */ 7244 /* iput-wide vA, vB, field@CCCC */ 7245 mov r0, rINST, lsr #12 @ r0<- B 7246 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7247 FETCH(r1, 1) @ r1<- field ref CCCC 7248 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7249 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7250 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7251 cmp r0, #0 @ is resolved entry null? 7252 bne .LOP_IPUT_WIDE_VOLATILE_finish @ no, already resolved 72538: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7254 EXPORT_PC() @ resolve() could throw 7255 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7256 bl dvmResolveInstField @ r0<- resolved InstField ptr 7257 cmp r0, #0 @ success? 7258 bne .LOP_IPUT_WIDE_VOLATILE_finish @ yes, finish up 7259 b common_exceptionThrown 7260 7261 7262/* ------------------------------ */ 7263 .balign 64 7264.L_OP_SGET_WIDE_VOLATILE: /* 0xea */ 7265/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */ 7266/* File: armv5te/OP_SGET_WIDE.S */ 7267 /* 7268 * 64-bit SGET handler. 7269 */ 7270 /* sget-wide vAA, field@BBBB */ 7271 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7272 FETCH(r1, 1) @ r1<- field ref BBBB 7273 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7274 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7275 cmp r0, #0 @ is resolved entry null? 7276 beq .LOP_SGET_WIDE_VOLATILE_resolve @ yes, do resolve 7277.LOP_SGET_WIDE_VOLATILE_finish: 7278 mov r9, rINST, lsr #8 @ r9<- AA 7279 .if 1 7280 add r0, r0, #offStaticField_value @ r0<- pointer to data 7281 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 7282 .else 7283 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 7284 .endif 7285 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7286 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7287 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 7288 GET_INST_OPCODE(ip) @ extract opcode from rINST 7289 GOTO_OPCODE(ip) @ jump to next instruction 7290 7291 7292/* ------------------------------ */ 7293 .balign 64 7294.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */ 7295/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */ 7296/* File: armv5te/OP_SPUT_WIDE.S */ 7297 /* 7298 * 64-bit SPUT handler. 7299 */ 7300 /* sput-wide vAA, field@BBBB */ 7301 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 7302 FETCH(r1, 1) @ r1<- field ref BBBB 7303 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 7304 mov r9, rINST, lsr #8 @ r9<- AA 7305 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 7306 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7307 cmp r2, #0 @ is resolved entry null? 7308 beq .LOP_SPUT_WIDE_VOLATILE_resolve @ yes, do resolve 7309.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9 7310 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7311 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 7312 GET_INST_OPCODE(r10) @ extract opcode from rINST 7313 .if 1 7314 add r2, r2, #offStaticField_value @ r2<- pointer to data 7315 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 7316 .else 7317 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 7318 .endif 7319 GOTO_OPCODE(r10) @ jump to next instruction 7320 7321 7322/* ------------------------------ */ 7323 .balign 64 7324.L_OP_BREAKPOINT: /* 0xec */ 7325/* File: armv5te/OP_BREAKPOINT.S */ 7326/* File: armv5te/unused.S */ 7327 bl common_abort 7328 7329 7330/* ------------------------------ */ 7331 .balign 64 7332.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7333/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7334 /* 7335 * Handle a throw-verification-error instruction. This throws an 7336 * exception for an error discovered during verification. The 7337 * exception is indicated by AA, with some detail provided by BBBB. 7338 */ 7339 /* op AA, ref@BBBB */ 7340 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7341 FETCH(r2, 1) @ r2<- BBBB 7342 EXPORT_PC() @ export the PC 7343 mov r1, rINST, lsr #8 @ r1<- AA 7344 bl dvmThrowVerificationError @ always throws 7345 b common_exceptionThrown @ handle exception 7346 7347/* ------------------------------ */ 7348 .balign 64 7349.L_OP_EXECUTE_INLINE: /* 0xee */ 7350/* File: armv5te/OP_EXECUTE_INLINE.S */ 7351 /* 7352 * Execute a "native inline" instruction. 7353 * 7354 * We need to call an InlineOp4Func: 7355 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7356 * 7357 * The first four args are in r0-r3, pointer to return value storage 7358 * is on the stack. The function's return value is a flag that tells 7359 * us if an exception was thrown. 7360 */ 7361 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7362 FETCH(r10, 1) @ r10<- BBBB 7363 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7364 EXPORT_PC() @ can throw 7365 sub sp, sp, #8 @ make room for arg, +64 bit align 7366 mov r0, rINST, lsr #12 @ r0<- B 7367 str r1, [sp] @ push &glue->retval 7368 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7369 add sp, sp, #8 @ pop stack 7370 cmp r0, #0 @ test boolean result of inline 7371 beq common_exceptionThrown @ returned false, handle exception 7372 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7373 GET_INST_OPCODE(ip) @ extract opcode from rINST 7374 GOTO_OPCODE(ip) @ jump to next instruction 7375 7376/* ------------------------------ */ 7377 .balign 64 7378.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ 7379/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */ 7380 /* 7381 * Execute a "native inline" instruction, using "/range" semantics. 7382 * Same idea as execute-inline, but we get the args differently. 7383 * 7384 * We need to call an InlineOp4Func: 7385 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7386 * 7387 * The first four args are in r0-r3, pointer to return value storage 7388 * is on the stack. The function's return value is a flag that tells 7389 * us if an exception was thrown. 7390 */ 7391 /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */ 7392 FETCH(r10, 1) @ r10<- BBBB 7393 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7394 EXPORT_PC() @ can throw 7395 sub sp, sp, #8 @ make room for arg, +64 bit align 7396 mov r0, rINST, lsr #8 @ r0<- AA 7397 str r1, [sp] @ push &glue->retval 7398 bl .LOP_EXECUTE_INLINE_RANGE_continue @ make call; will return after 7399 add sp, sp, #8 @ pop stack 7400 cmp r0, #0 @ test boolean result of inline 7401 beq common_exceptionThrown @ returned false, handle exception 7402 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7403 GET_INST_OPCODE(ip) @ extract opcode from rINST 7404 GOTO_OPCODE(ip) @ jump to next instruction 7405 7406/* ------------------------------ */ 7407 .balign 64 7408.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7409/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7410 /* 7411 * invoke-direct-empty is a no-op in a "standard" interpreter. 7412 */ 7413 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7414 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7415 GOTO_OPCODE(ip) @ execute it 7416 7417/* ------------------------------ */ 7418 .balign 64 7419.L_OP_RETURN_VOID_BARRIER: /* 0xf1 */ 7420/* File: armv5te/OP_RETURN_VOID_BARRIER.S */ 7421 SMP_DMB_ST 7422 b common_returnFromMethod 7423 7424/* ------------------------------ */ 7425 .balign 64 7426.L_OP_IGET_QUICK: /* 0xf2 */ 7427/* File: armv6t2/OP_IGET_QUICK.S */ 7428 /* For: iget-quick, iget-object-quick */ 7429 /* op vA, vB, offset@CCCC */ 7430 mov r2, rINST, lsr #12 @ r2<- B 7431 FETCH(r1, 1) @ r1<- field byte offset 7432 GET_VREG(r3, r2) @ r3<- object we're operating on 7433 ubfx r2, rINST, #8, #4 @ r2<- A 7434 cmp r3, #0 @ check object for null 7435 beq common_errNullObject @ object was null 7436 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7437 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7438 GET_INST_OPCODE(ip) @ extract opcode from rINST 7439 SET_VREG(r0, r2) @ fp[A]<- r0 7440 GOTO_OPCODE(ip) @ jump to next instruction 7441 7442/* ------------------------------ */ 7443 .balign 64 7444.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7445/* File: armv6t2/OP_IGET_WIDE_QUICK.S */ 7446 /* iget-wide-quick vA, vB, offset@CCCC */ 7447 mov r2, rINST, lsr #12 @ r2<- B 7448 FETCH(ip, 1) @ ip<- field byte offset 7449 GET_VREG(r3, r2) @ r3<- object we're operating on 7450 ubfx r2, rINST, #8, #4 @ r2<- A 7451 cmp r3, #0 @ check object for null 7452 beq common_errNullObject @ object was null 7453 ldrd r0, [r3, ip] @ r0<- obj.field (64 bits, aligned) 7454 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7455 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7456 GET_INST_OPCODE(ip) @ extract opcode from rINST 7457 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7458 GOTO_OPCODE(ip) @ jump to next instruction 7459 7460/* ------------------------------ */ 7461 .balign 64 7462.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7463/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7464/* File: armv5te/OP_IGET_QUICK.S */ 7465 /* For: iget-quick, iget-object-quick */ 7466 /* op vA, vB, offset@CCCC */ 7467 mov r2, rINST, lsr #12 @ r2<- B 7468 GET_VREG(r3, r2) @ r3<- object we're operating on 7469 FETCH(r1, 1) @ r1<- field byte offset 7470 cmp r3, #0 @ check object for null 7471 mov r2, rINST, lsr #8 @ r2<- A(+) 7472 beq common_errNullObject @ object was null 7473 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7474 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7475 and r2, r2, #15 7476 GET_INST_OPCODE(ip) @ extract opcode from rINST 7477 SET_VREG(r0, r2) @ fp[A]<- r0 7478 GOTO_OPCODE(ip) @ jump to next instruction 7479 7480 7481/* ------------------------------ */ 7482 .balign 64 7483.L_OP_IPUT_QUICK: /* 0xf5 */ 7484/* File: armv6t2/OP_IPUT_QUICK.S */ 7485 /* For: iput-quick, iput-object-quick */ 7486 /* op vA, vB, offset@CCCC */ 7487 mov r2, rINST, lsr #12 @ r2<- B 7488 FETCH(r1, 1) @ r1<- field byte offset 7489 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7490 ubfx r2, rINST, #8, #4 @ r2<- A 7491 cmp r3, #0 @ check object for null 7492 beq common_errNullObject @ object was null 7493 GET_VREG(r0, r2) @ r0<- fp[A] 7494 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7495 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7496 GET_INST_OPCODE(ip) @ extract opcode from rINST 7497 GOTO_OPCODE(ip) @ jump to next instruction 7498 7499/* ------------------------------ */ 7500 .balign 64 7501.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7502/* File: armv6t2/OP_IPUT_WIDE_QUICK.S */ 7503 /* iput-wide-quick vA, vB, offset@CCCC */ 7504 mov r1, rINST, lsr #12 @ r1<- B 7505 ubfx r0, rINST, #8, #4 @ r0<- A 7506 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7507 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7508 cmp r2, #0 @ check object for null 7509 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7510 beq common_errNullObject @ object was null 7511 FETCH(r3, 1) @ r3<- field byte offset 7512 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7513 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7514 GET_INST_OPCODE(ip) @ extract opcode from rINST 7515 GOTO_OPCODE(ip) @ jump to next instruction 7516 7517/* ------------------------------ */ 7518 .balign 64 7519.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7520/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7521 /* For: iput-object-quick */ 7522 /* op vA, vB, offset@CCCC */ 7523 mov r2, rINST, lsr #12 @ r2<- B 7524 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7525 FETCH(r1, 1) @ r1<- field byte offset 7526 cmp r3, #0 @ check object for null 7527 mov r2, rINST, lsr #8 @ r2<- A(+) 7528 beq common_errNullObject @ object was null 7529 and r2, r2, #15 7530 GET_VREG(r0, r2) @ r0<- fp[A] 7531 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 7532 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7533 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7534 cmp r0, #0 7535 strneb r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head 7536 GET_INST_OPCODE(ip) @ extract opcode from rINST 7537 GOTO_OPCODE(ip) @ jump to next instruction 7538 7539/* ------------------------------ */ 7540 .balign 64 7541.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7542/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7543 /* 7544 * Handle an optimized virtual method call. 7545 * 7546 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7547 */ 7548 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7549 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7550 FETCH(r3, 2) @ r3<- FEDC or CCCC 7551 FETCH(r1, 1) @ r1<- BBBB 7552 .if (!0) 7553 and r3, r3, #15 @ r3<- C (or stays CCCC) 7554 .endif 7555 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7556 cmp r2, #0 @ is "this" null? 7557 beq common_errNullObject @ null "this", throw exception 7558 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7559 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7560 EXPORT_PC() @ invoke must export 7561 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7562 bl common_invokeMethodNoRange @ continue on 7563 7564/* ------------------------------ */ 7565 .balign 64 7566.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7567/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7568/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7569 /* 7570 * Handle an optimized virtual method call. 7571 * 7572 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7573 */ 7574 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7575 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7576 FETCH(r3, 2) @ r3<- FEDC or CCCC 7577 FETCH(r1, 1) @ r1<- BBBB 7578 .if (!1) 7579 and r3, r3, #15 @ r3<- C (or stays CCCC) 7580 .endif 7581 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7582 cmp r2, #0 @ is "this" null? 7583 beq common_errNullObject @ null "this", throw exception 7584 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7585 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7586 EXPORT_PC() @ invoke must export 7587 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7588 bl common_invokeMethodRange @ continue on 7589 7590 7591/* ------------------------------ */ 7592 .balign 64 7593.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7594/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7595 /* 7596 * Handle an optimized "super" method call. 7597 * 7598 * for: [opt] invoke-super-quick, invoke-super-quick/range 7599 */ 7600 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7601 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7602 FETCH(r10, 2) @ r10<- GFED or CCCC 7603 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7604 .if (!0) 7605 and r10, r10, #15 @ r10<- D (or stays CCCC) 7606 .endif 7607 FETCH(r1, 1) @ r1<- BBBB 7608 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7609 EXPORT_PC() @ must export for invoke 7610 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7611 GET_VREG(r3, r10) @ r3<- "this" 7612 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7613 cmp r3, #0 @ null "this" ref? 7614 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7615 beq common_errNullObject @ "this" is null, throw exception 7616 bl common_invokeMethodNoRange @ continue on 7617 7618/* ------------------------------ */ 7619 .balign 64 7620.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7621/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7622/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7623 /* 7624 * Handle an optimized "super" method call. 7625 * 7626 * for: [opt] invoke-super-quick, invoke-super-quick/range 7627 */ 7628 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7629 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7630 FETCH(r10, 2) @ r10<- GFED or CCCC 7631 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7632 .if (!1) 7633 and r10, r10, #15 @ r10<- D (or stays CCCC) 7634 .endif 7635 FETCH(r1, 1) @ r1<- BBBB 7636 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7637 EXPORT_PC() @ must export for invoke 7638 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7639 GET_VREG(r3, r10) @ r3<- "this" 7640 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7641 cmp r3, #0 @ null "this" ref? 7642 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7643 beq common_errNullObject @ "this" is null, throw exception 7644 bl common_invokeMethodRange @ continue on 7645 7646 7647/* ------------------------------ */ 7648 .balign 64 7649.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ 7650/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */ 7651/* File: armv5te/OP_IPUT_OBJECT.S */ 7652 /* 7653 * 32-bit instance field put. 7654 * 7655 * for: iput-object, iput-object-volatile 7656 */ 7657 /* op vA, vB, field@CCCC */ 7658 mov r0, rINST, lsr #12 @ r0<- B 7659 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7660 FETCH(r1, 1) @ r1<- field ref CCCC 7661 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7662 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7663 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7664 cmp r0, #0 @ is resolved entry null? 7665 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ no, already resolved 76668: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7667 EXPORT_PC() @ resolve() could throw 7668 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7669 bl dvmResolveInstField @ r0<- resolved InstField ptr 7670 cmp r0, #0 @ success? 7671 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ yes, finish up 7672 b common_exceptionThrown 7673 7674 7675/* ------------------------------ */ 7676 .balign 64 7677.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ 7678/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */ 7679/* File: armv5te/OP_SGET.S */ 7680 /* 7681 * General 32-bit SGET handler. 7682 * 7683 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7684 */ 7685 /* op vAA, field@BBBB */ 7686 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7687 FETCH(r1, 1) @ r1<- field ref BBBB 7688 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7689 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7690 cmp r0, #0 @ is resolved entry null? 7691 beq .LOP_SGET_OBJECT_VOLATILE_resolve @ yes, do resolve 7692.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0 7693 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7694 SMP_DMB @ acquiring load 7695 mov r2, rINST, lsr #8 @ r2<- AA 7696 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7697 SET_VREG(r1, r2) @ fp[AA]<- r1 7698 GET_INST_OPCODE(ip) @ extract opcode from rINST 7699 GOTO_OPCODE(ip) @ jump to next instruction 7700 7701 7702/* ------------------------------ */ 7703 .balign 64 7704.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ 7705/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */ 7706/* File: armv5te/OP_SPUT_OBJECT.S */ 7707 /* 7708 * 32-bit SPUT handler for objects 7709 * 7710 * for: sput-object, sput-object-volatile 7711 */ 7712 /* op vAA, field@BBBB */ 7713 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7714 FETCH(r1, 1) @ r1<- field ref BBBB 7715 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7716 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7717 cmp r0, #0 @ is resolved entry null? 7718 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 7719 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ no, continue 7720 EXPORT_PC() @ resolve() could throw, so export now 7721 ldr r0, [r9, #offMethod_clazz] @ r0<- method->clazz 7722 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 7723 cmp r0, #0 @ success? 7724 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish 7725 b common_exceptionThrown @ no, handle exception 7726 7727 7728 7729/* ------------------------------ */ 7730 .balign 64 7731.L_OP_UNUSED_FF: /* 0xff */ 7732/* File: armv5te/OP_UNUSED_FF.S */ 7733/* File: armv5te/unused.S */ 7734 bl common_abort 7735 7736 7737 7738 .balign 64 7739 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7740 .global dvmAsmInstructionEnd 7741dvmAsmInstructionEnd: 7742 7743/* 7744 * =========================================================================== 7745 * Sister implementations 7746 * =========================================================================== 7747 */ 7748 .global dvmAsmSisterStart 7749 .type dvmAsmSisterStart, %function 7750 .text 7751 .balign 4 7752dvmAsmSisterStart: 7753 7754/* continuation for OP_CONST_STRING */ 7755 7756 /* 7757 * Continuation if the String has not yet been resolved. 7758 * r1: BBBB (String ref) 7759 * r9: target register 7760 */ 7761.LOP_CONST_STRING_resolve: 7762 EXPORT_PC() 7763 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7764 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7765 bl dvmResolveString @ r0<- String reference 7766 cmp r0, #0 @ failed? 7767 beq common_exceptionThrown @ yup, handle the exception 7768 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7769 GET_INST_OPCODE(ip) @ extract opcode from rINST 7770 SET_VREG(r0, r9) @ vAA<- r0 7771 GOTO_OPCODE(ip) @ jump to next instruction 7772 7773/* continuation for OP_CONST_STRING_JUMBO */ 7774 7775 /* 7776 * Continuation if the String has not yet been resolved. 7777 * r1: BBBBBBBB (String ref) 7778 * r9: target register 7779 */ 7780.LOP_CONST_STRING_JUMBO_resolve: 7781 EXPORT_PC() 7782 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7783 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7784 bl dvmResolveString @ r0<- String reference 7785 cmp r0, #0 @ failed? 7786 beq common_exceptionThrown @ yup, handle the exception 7787 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7788 GET_INST_OPCODE(ip) @ extract opcode from rINST 7789 SET_VREG(r0, r9) @ vAA<- r0 7790 GOTO_OPCODE(ip) @ jump to next instruction 7791 7792/* continuation for OP_CONST_CLASS */ 7793 7794 /* 7795 * Continuation if the Class has not yet been resolved. 7796 * r1: BBBB (Class ref) 7797 * r9: target register 7798 */ 7799.LOP_CONST_CLASS_resolve: 7800 EXPORT_PC() 7801 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7802 mov r2, #1 @ r2<- true 7803 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7804 bl dvmResolveClass @ r0<- Class reference 7805 cmp r0, #0 @ failed? 7806 beq common_exceptionThrown @ yup, handle the exception 7807 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7808 GET_INST_OPCODE(ip) @ extract opcode from rINST 7809 SET_VREG(r0, r9) @ vAA<- r0 7810 GOTO_OPCODE(ip) @ jump to next instruction 7811 7812/* continuation for OP_CHECK_CAST */ 7813 7814 /* 7815 * Trivial test failed, need to perform full check. This is common. 7816 * r0 holds obj->clazz 7817 * r1 holds class resolved from BBBB 7818 * r9 holds object 7819 */ 7820.LOP_CHECK_CAST_fullcheck: 7821 bl dvmInstanceofNonTrivial @ r0<- boolean result 7822 cmp r0, #0 @ failed? 7823 bne .LOP_CHECK_CAST_okay @ no, success 7824 7825 @ A cast has failed. We need to throw a ClassCastException with the 7826 @ class of the object that failed to be cast. 7827 EXPORT_PC() @ about to throw 7828 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 7829 ldr r0, .LstrClassCastExceptionPtr 7830 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 7831 bl dvmThrowExceptionWithClassMessage 7832 b common_exceptionThrown 7833 7834 /* 7835 * Resolution required. This is the least-likely path. 7836 * 7837 * r2 holds BBBB 7838 * r9 holds object 7839 */ 7840.LOP_CHECK_CAST_resolve: 7841 EXPORT_PC() @ resolve() could throw 7842 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7843 mov r1, r2 @ r1<- BBBB 7844 mov r2, #0 @ r2<- false 7845 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7846 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7847 cmp r0, #0 @ got null? 7848 beq common_exceptionThrown @ yes, handle exception 7849 mov r1, r0 @ r1<- class resolved from BBB 7850 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7851 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7852 7853.LstrClassCastExceptionPtr: 7854 .word .LstrClassCastException 7855 7856/* continuation for OP_INSTANCE_OF */ 7857 7858 /* 7859 * Trivial test failed, need to perform full check. This is common. 7860 * r0 holds obj->clazz 7861 * r1 holds class resolved from BBBB 7862 * r9 holds A 7863 */ 7864.LOP_INSTANCE_OF_fullcheck: 7865 bl dvmInstanceofNonTrivial @ r0<- boolean result 7866 @ fall through to OP_INSTANCE_OF_store 7867 7868 /* 7869 * r0 holds boolean result 7870 * r9 holds A 7871 */ 7872.LOP_INSTANCE_OF_store: 7873 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7874 SET_VREG(r0, r9) @ vA<- r0 7875 GET_INST_OPCODE(ip) @ extract opcode from rINST 7876 GOTO_OPCODE(ip) @ jump to next instruction 7877 7878 /* 7879 * Trivial test succeeded, save and bail. 7880 * r9 holds A 7881 */ 7882.LOP_INSTANCE_OF_trivial: 7883 mov r0, #1 @ indicate success 7884 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7885 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7886 SET_VREG(r0, r9) @ vA<- r0 7887 GET_INST_OPCODE(ip) @ extract opcode from rINST 7888 GOTO_OPCODE(ip) @ jump to next instruction 7889 7890 /* 7891 * Resolution required. This is the least-likely path. 7892 * 7893 * r3 holds BBBB 7894 * r9 holds A 7895 */ 7896.LOP_INSTANCE_OF_resolve: 7897 EXPORT_PC() @ resolve() could throw 7898 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7899 mov r1, r3 @ r1<- BBBB 7900 mov r2, #1 @ r2<- true 7901 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7902 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7903 cmp r0, #0 @ got null? 7904 beq common_exceptionThrown @ yes, handle exception 7905 mov r1, r0 @ r1<- class resolved from BBB 7906 mov r3, rINST, lsr #12 @ r3<- B 7907 GET_VREG(r0, r3) @ r0<- vB (object) 7908 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7909 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7910 7911/* continuation for OP_NEW_INSTANCE */ 7912 7913 .balign 32 @ minimize cache lines 7914.LOP_NEW_INSTANCE_finish: @ r0=new object 7915 mov r3, rINST, lsr #8 @ r3<- AA 7916 cmp r0, #0 @ failed? 7917 beq common_exceptionThrown @ yes, handle the exception 7918 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7919 GET_INST_OPCODE(ip) @ extract opcode from rINST 7920 SET_VREG(r0, r3) @ vAA<- r0 7921 GOTO_OPCODE(ip) @ jump to next instruction 7922 7923 /* 7924 * Class initialization required. 7925 * 7926 * r0 holds class object 7927 */ 7928.LOP_NEW_INSTANCE_needinit: 7929 mov r9, r0 @ save r0 7930 bl dvmInitClass @ initialize class 7931 cmp r0, #0 @ check boolean result 7932 mov r0, r9 @ restore r0 7933 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7934 b common_exceptionThrown @ failed, deal with init exception 7935 7936 /* 7937 * Resolution required. This is the least-likely path. 7938 * 7939 * r1 holds BBBB 7940 */ 7941.LOP_NEW_INSTANCE_resolve: 7942 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7943 mov r2, #0 @ r2<- false 7944 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7945 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7946 cmp r0, #0 @ got null? 7947 bne .LOP_NEW_INSTANCE_resolved @ no, continue 7948 b common_exceptionThrown @ yes, handle exception 7949 7950.LstrInstantiationErrorPtr: 7951 .word .LstrInstantiationError 7952 7953/* continuation for OP_NEW_ARRAY */ 7954 7955 7956 /* 7957 * Resolve class. (This is an uncommon case.) 7958 * 7959 * r1 holds array length 7960 * r2 holds class ref CCCC 7961 */ 7962.LOP_NEW_ARRAY_resolve: 7963 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7964 mov r9, r1 @ r9<- length (save) 7965 mov r1, r2 @ r1<- CCCC 7966 mov r2, #0 @ r2<- false 7967 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7968 bl dvmResolveClass @ r0<- call(clazz, ref) 7969 cmp r0, #0 @ got null? 7970 mov r1, r9 @ r1<- length (restore) 7971 beq common_exceptionThrown @ yes, handle exception 7972 @ fall through to OP_NEW_ARRAY_finish 7973 7974 /* 7975 * Finish allocation. 7976 * 7977 * r0 holds class 7978 * r1 holds array length 7979 */ 7980.LOP_NEW_ARRAY_finish: 7981 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 7982 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 7983 cmp r0, #0 @ failed? 7984 mov r2, rINST, lsr #8 @ r2<- A+ 7985 beq common_exceptionThrown @ yes, handle the exception 7986 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7987 and r2, r2, #15 @ r2<- A 7988 GET_INST_OPCODE(ip) @ extract opcode from rINST 7989 SET_VREG(r0, r2) @ vA<- r0 7990 GOTO_OPCODE(ip) @ jump to next instruction 7991 7992/* continuation for OP_FILLED_NEW_ARRAY */ 7993 7994 /* 7995 * On entry: 7996 * r0 holds array class 7997 * r10 holds AA or BA 7998 */ 7999.LOP_FILLED_NEW_ARRAY_continue: 8000 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8001 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8002 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 8003 .if 0 8004 mov r1, r10 @ r1<- AA (length) 8005 .else 8006 mov r1, r10, lsr #4 @ r1<- B (length) 8007 .endif 8008 cmp rINST, #'I' @ array of ints? 8009 cmpne rINST, #'L' @ array of objects? 8010 cmpne rINST, #'[' @ array of arrays? 8011 mov r9, r1 @ save length in r9 8012 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 8013 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8014 cmp r0, #0 @ null return? 8015 beq common_exceptionThrown @ alloc failed, handle exception 8016 8017 FETCH(r1, 2) @ r1<- FEDC or CCCC 8018 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8019 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 8020 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8021 subs r9, r9, #1 @ length--, check for neg 8022 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8023 bmi 2f @ was zero, bail 8024 8025 @ copy values from registers into the array 8026 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8027 .if 0 8028 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 80291: ldr r3, [r2], #4 @ r3<- *r2++ 8030 subs r9, r9, #1 @ count-- 8031 str r3, [r0], #4 @ *contents++ = vX 8032 bpl 1b 8033 @ continue at 2 8034 .else 8035 cmp r9, #4 @ length was initially 5? 8036 and r2, r10, #15 @ r2<- A 8037 bne 1f @ <= 4 args, branch 8038 GET_VREG(r3, r2) @ r3<- vA 8039 sub r9, r9, #1 @ count-- 8040 str r3, [r0, #16] @ contents[4] = vA 80411: and r2, r1, #15 @ r2<- F/E/D/C 8042 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8043 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8044 subs r9, r9, #1 @ count-- 8045 str r3, [r0], #4 @ *contents++ = vX 8046 bpl 1b 8047 @ continue at 2 8048 .endif 8049 80502: 8051 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 8052 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 8053 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8054 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8055 cmp r1, #'I' @ Is int array? 8056 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 8057 GOTO_OPCODE(ip) @ execute it 8058 8059 /* 8060 * Throw an exception indicating that we have not implemented this 8061 * mode of filled-new-array. 8062 */ 8063.LOP_FILLED_NEW_ARRAY_notimpl: 8064 ldr r0, .L_strInternalError 8065 ldr r1, .L_strFilledNewArrayNotImpl 8066 bl dvmThrowException 8067 b common_exceptionThrown 8068 8069 .if (!0) @ define in one or the other, not both 8070.L_strFilledNewArrayNotImpl: 8071 .word .LstrFilledNewArrayNotImpl 8072.L_strInternalError: 8073 .word .LstrInternalError 8074 .endif 8075 8076/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 8077 8078 /* 8079 * On entry: 8080 * r0 holds array class 8081 * r10 holds AA or BA 8082 */ 8083.LOP_FILLED_NEW_ARRAY_RANGE_continue: 8084 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8085 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8086 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 8087 .if 1 8088 mov r1, r10 @ r1<- AA (length) 8089 .else 8090 mov r1, r10, lsr #4 @ r1<- B (length) 8091 .endif 8092 cmp rINST, #'I' @ array of ints? 8093 cmpne rINST, #'L' @ array of objects? 8094 cmpne rINST, #'[' @ array of arrays? 8095 mov r9, r1 @ save length in r9 8096 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 8097 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8098 cmp r0, #0 @ null return? 8099 beq common_exceptionThrown @ alloc failed, handle exception 8100 8101 FETCH(r1, 2) @ r1<- FEDC or CCCC 8102 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8103 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 8104 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8105 subs r9, r9, #1 @ length--, check for neg 8106 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8107 bmi 2f @ was zero, bail 8108 8109 @ copy values from registers into the array 8110 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8111 .if 1 8112 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 81131: ldr r3, [r2], #4 @ r3<- *r2++ 8114 subs r9, r9, #1 @ count-- 8115 str r3, [r0], #4 @ *contents++ = vX 8116 bpl 1b 8117 @ continue at 2 8118 .else 8119 cmp r9, #4 @ length was initially 5? 8120 and r2, r10, #15 @ r2<- A 8121 bne 1f @ <= 4 args, branch 8122 GET_VREG(r3, r2) @ r3<- vA 8123 sub r9, r9, #1 @ count-- 8124 str r3, [r0, #16] @ contents[4] = vA 81251: and r2, r1, #15 @ r2<- F/E/D/C 8126 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8127 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8128 subs r9, r9, #1 @ count-- 8129 str r3, [r0], #4 @ *contents++ = vX 8130 bpl 1b 8131 @ continue at 2 8132 .endif 8133 81342: 8135 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 8136 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 8137 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8138 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8139 cmp r1, #'I' @ Is int array? 8140 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 8141 GOTO_OPCODE(ip) @ execute it 8142 8143 /* 8144 * Throw an exception indicating that we have not implemented this 8145 * mode of filled-new-array. 8146 */ 8147.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8148 ldr r0, .L_strInternalError 8149 ldr r1, .L_strFilledNewArrayNotImpl 8150 bl dvmThrowException 8151 b common_exceptionThrown 8152 8153 .if (!1) @ define in one or the other, not both 8154.L_strFilledNewArrayNotImpl: 8155 .word .LstrFilledNewArrayNotImpl 8156.L_strInternalError: 8157 .word .LstrInternalError 8158 .endif 8159 8160/* continuation for OP_CMPL_FLOAT */ 8161.LOP_CMPL_FLOAT_finish: 8162 SET_VREG(r0, r9) @ vAA<- r0 8163 GOTO_OPCODE(ip) @ jump to next instruction 8164 8165/* continuation for OP_CMPG_FLOAT */ 8166.LOP_CMPG_FLOAT_finish: 8167 SET_VREG(r0, r9) @ vAA<- r0 8168 GOTO_OPCODE(ip) @ jump to next instruction 8169 8170/* continuation for OP_CMPL_DOUBLE */ 8171.LOP_CMPL_DOUBLE_finish: 8172 SET_VREG(r0, r9) @ vAA<- r0 8173 GOTO_OPCODE(ip) @ jump to next instruction 8174 8175/* continuation for OP_CMPG_DOUBLE */ 8176.LOP_CMPG_DOUBLE_finish: 8177 SET_VREG(r0, r9) @ vAA<- r0 8178 GOTO_OPCODE(ip) @ jump to next instruction 8179 8180/* continuation for OP_CMP_LONG */ 8181 8182.LOP_CMP_LONG_less: 8183 mvn r1, #0 @ r1<- -1 8184 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8185 @ instead, we just replicate the tail end. 8186 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8187 SET_VREG(r1, r9) @ vAA<- r1 8188 GET_INST_OPCODE(ip) @ extract opcode from rINST 8189 GOTO_OPCODE(ip) @ jump to next instruction 8190 8191.LOP_CMP_LONG_greater: 8192 mov r1, #1 @ r1<- 1 8193 @ fall through to _finish 8194 8195.LOP_CMP_LONG_finish: 8196 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8197 SET_VREG(r1, r9) @ vAA<- r1 8198 GET_INST_OPCODE(ip) @ extract opcode from rINST 8199 GOTO_OPCODE(ip) @ jump to next instruction 8200 8201/* continuation for OP_AGET_WIDE */ 8202 8203.LOP_AGET_WIDE_finish: 8204 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8205 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8206 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8207 GET_INST_OPCODE(ip) @ extract opcode from rINST 8208 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8209 GOTO_OPCODE(ip) @ jump to next instruction 8210 8211/* continuation for OP_APUT_WIDE */ 8212 8213.LOP_APUT_WIDE_finish: 8214 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8215 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8216 GET_INST_OPCODE(ip) @ extract opcode from rINST 8217 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8218 GOTO_OPCODE(ip) @ jump to next instruction 8219 8220/* continuation for OP_APUT_OBJECT */ 8221 /* 8222 * On entry: 8223 * rINST = vBB (arrayObj) 8224 * r9 = vAA (obj) 8225 * r10 = offset into array (vBB + vCC * width) 8226 */ 8227.LOP_APUT_OBJECT_finish: 8228 cmp r9, #0 @ storing null reference? 8229 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8230 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8231 ldr r1, [rINST, #offObject_clazz] @ r1<- arrayObj->clazz 8232 bl dvmCanPutArrayElement @ test object type vs. array type 8233 cmp r0, #0 @ okay? 8234 beq common_errArrayStore @ no 8235 mov r1, rINST @ r1<- arrayObj 8236 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8237 ldr r2, [rGLUE, #offGlue_cardTable] @ get biased CT base 8238 add r10, #offArrayObject_contents @ r0<- pointer to slot 8239 GET_INST_OPCODE(ip) @ extract opcode from rINST 8240 str r9, [r10] @ vBB[vCC]<- vAA 8241 strb r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head 8242 GOTO_OPCODE(ip) @ jump to next instruction 8243.LOP_APUT_OBJECT_skip_check: 8244 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8245 GET_INST_OPCODE(ip) @ extract opcode from rINST 8246 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8247 GOTO_OPCODE(ip) @ jump to next instruction 8248 8249/* continuation for OP_IGET */ 8250 8251 /* 8252 * Currently: 8253 * r0 holds resolved field 8254 * r9 holds object 8255 */ 8256.LOP_IGET_finish: 8257 @bl common_squeak0 8258 cmp r9, #0 @ check object for null 8259 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8260 beq common_errNullObject @ object was null 8261 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8262 ubfx r2, rINST, #8, #4 @ r2<- A 8263 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8264 GET_INST_OPCODE(ip) @ extract opcode from rINST 8265 SET_VREG(r0, r2) @ fp[A]<- r0 8266 GOTO_OPCODE(ip) @ jump to next instruction 8267 8268/* continuation for OP_IGET_WIDE */ 8269 8270 /* 8271 * Currently: 8272 * r0 holds resolved field 8273 * r9 holds object 8274 */ 8275.LOP_IGET_WIDE_finish: 8276 cmp r9, #0 @ check object for null 8277 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8278 beq common_errNullObject @ object was null 8279 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8280 ubfx r2, rINST, #8, #4 @ r2<- A 8281 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8282 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8283 GET_INST_OPCODE(ip) @ extract opcode from rINST 8284 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8285 GOTO_OPCODE(ip) @ jump to next instruction 8286 8287/* continuation for OP_IGET_OBJECT */ 8288 8289 /* 8290 * Currently: 8291 * r0 holds resolved field 8292 * r9 holds object 8293 */ 8294.LOP_IGET_OBJECT_finish: 8295 @bl common_squeak0 8296 cmp r9, #0 @ check object for null 8297 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8298 beq common_errNullObject @ object was null 8299 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8300 @ no-op @ acquiring load 8301 mov r2, rINST, lsr #8 @ r2<- A+ 8302 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8303 and r2, r2, #15 @ r2<- A 8304 GET_INST_OPCODE(ip) @ extract opcode from rINST 8305 SET_VREG(r0, r2) @ fp[A]<- r0 8306 GOTO_OPCODE(ip) @ jump to next instruction 8307 8308/* continuation for OP_IGET_BOOLEAN */ 8309 8310 /* 8311 * Currently: 8312 * r0 holds resolved field 8313 * r9 holds object 8314 */ 8315.LOP_IGET_BOOLEAN_finish: 8316 @bl common_squeak1 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_BYTE */ 8330 8331 /* 8332 * Currently: 8333 * r0 holds resolved field 8334 * r9 holds object 8335 */ 8336.LOP_IGET_BYTE_finish: 8337 @bl common_squeak2 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_CHAR */ 8351 8352 /* 8353 * Currently: 8354 * r0 holds resolved field 8355 * r9 holds object 8356 */ 8357.LOP_IGET_CHAR_finish: 8358 @bl common_squeak3 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_SHORT */ 8372 8373 /* 8374 * Currently: 8375 * r0 holds resolved field 8376 * r9 holds object 8377 */ 8378.LOP_IGET_SHORT_finish: 8379 @bl common_squeak4 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_IPUT */ 8393 8394 /* 8395 * Currently: 8396 * r0 holds resolved field 8397 * r9 holds object 8398 */ 8399.LOP_IPUT_finish: 8400 @bl common_squeak0 8401 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8402 ubfx r1, rINST, #8, #4 @ r1<- A 8403 cmp r9, #0 @ check object for null 8404 GET_VREG(r0, r1) @ r0<- fp[A] 8405 beq common_errNullObject @ object was null 8406 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8407 GET_INST_OPCODE(ip) @ extract opcode from rINST 8408 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8409 GOTO_OPCODE(ip) @ jump to next instruction 8410 8411/* continuation for OP_IPUT_WIDE */ 8412 8413 /* 8414 * Currently: 8415 * r0 holds resolved field 8416 * r9 holds object 8417 */ 8418.LOP_IPUT_WIDE_finish: 8419 ubfx r2, rINST, #8, #4 @ r2<- A 8420 cmp r9, #0 @ check object for null 8421 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8422 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8423 beq common_errNullObject @ object was null 8424 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8425 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8426 GET_INST_OPCODE(ip) @ extract opcode from rINST 8427 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0 8428 GOTO_OPCODE(ip) @ jump to next instruction 8429 8430/* continuation for OP_IPUT_OBJECT */ 8431 8432 /* 8433 * Currently: 8434 * r0 holds resolved field 8435 * r9 holds object 8436 */ 8437.LOP_IPUT_OBJECT_finish: 8438 @bl common_squeak0 8439 mov r1, rINST, lsr #8 @ r1<- A+ 8440 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8441 and r1, r1, #15 @ r1<- A 8442 cmp r9, #0 @ check object for null 8443 GET_VREG(r0, r1) @ r0<- fp[A] 8444 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8445 beq common_errNullObject @ object was null 8446 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8447 GET_INST_OPCODE(ip) @ extract opcode from rINST 8448 @ no-op @ releasing store 8449 str r0, [r9,r3] @ obj.field (32 bits)<- r0 8450 cmp r0, #0 @ stored a null reference? 8451 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 8452 GOTO_OPCODE(ip) @ jump to next instruction 8453 8454/* continuation for OP_IPUT_BOOLEAN */ 8455 8456 /* 8457 * Currently: 8458 * r0 holds resolved field 8459 * r9 holds object 8460 */ 8461.LOP_IPUT_BOOLEAN_finish: 8462 @bl common_squeak1 8463 mov r1, rINST, lsr #8 @ r1<- A+ 8464 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8465 and r1, r1, #15 @ r1<- A 8466 cmp r9, #0 @ check object for null 8467 GET_VREG(r0, r1) @ r0<- fp[A] 8468 beq common_errNullObject @ object was null 8469 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8470 GET_INST_OPCODE(ip) @ extract opcode from rINST 8471 @ no-op @ releasing store 8472 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8473 GOTO_OPCODE(ip) @ jump to next instruction 8474 8475/* continuation for OP_IPUT_BYTE */ 8476 8477 /* 8478 * Currently: 8479 * r0 holds resolved field 8480 * r9 holds object 8481 */ 8482.LOP_IPUT_BYTE_finish: 8483 @bl common_squeak2 8484 mov r1, rINST, lsr #8 @ r1<- A+ 8485 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8486 and r1, r1, #15 @ r1<- A 8487 cmp r9, #0 @ check object for null 8488 GET_VREG(r0, r1) @ r0<- fp[A] 8489 beq common_errNullObject @ object was null 8490 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8491 GET_INST_OPCODE(ip) @ extract opcode from rINST 8492 @ no-op @ releasing store 8493 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8494 GOTO_OPCODE(ip) @ jump to next instruction 8495 8496/* continuation for OP_IPUT_CHAR */ 8497 8498 /* 8499 * Currently: 8500 * r0 holds resolved field 8501 * r9 holds object 8502 */ 8503.LOP_IPUT_CHAR_finish: 8504 @bl common_squeak3 8505 mov r1, rINST, lsr #8 @ r1<- A+ 8506 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8507 and r1, r1, #15 @ r1<- A 8508 cmp r9, #0 @ check object for null 8509 GET_VREG(r0, r1) @ r0<- fp[A] 8510 beq common_errNullObject @ object was null 8511 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8512 GET_INST_OPCODE(ip) @ extract opcode from rINST 8513 @ no-op @ releasing store 8514 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8515 GOTO_OPCODE(ip) @ jump to next instruction 8516 8517/* continuation for OP_IPUT_SHORT */ 8518 8519 /* 8520 * Currently: 8521 * r0 holds resolved field 8522 * r9 holds object 8523 */ 8524.LOP_IPUT_SHORT_finish: 8525 @bl common_squeak4 8526 mov r1, rINST, lsr #8 @ r1<- A+ 8527 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8528 and r1, r1, #15 @ r1<- A 8529 cmp r9, #0 @ check object for null 8530 GET_VREG(r0, r1) @ r0<- fp[A] 8531 beq common_errNullObject @ object was null 8532 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8533 GET_INST_OPCODE(ip) @ extract opcode from rINST 8534 @ no-op @ releasing store 8535 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8536 GOTO_OPCODE(ip) @ jump to next instruction 8537 8538/* continuation for OP_SGET */ 8539 8540 /* 8541 * Continuation if the field has not yet been resolved. 8542 * r1: BBBB field ref 8543 */ 8544.LOP_SGET_resolve: 8545 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8546 EXPORT_PC() @ resolve() could throw, so export now 8547 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8548 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8549 cmp r0, #0 @ success? 8550 bne .LOP_SGET_finish @ yes, finish 8551 b common_exceptionThrown @ no, handle exception 8552 8553/* continuation for OP_SGET_WIDE */ 8554 8555 /* 8556 * Continuation if the field has not yet been resolved. 8557 * r1: BBBB field ref 8558 * 8559 * Returns StaticField pointer in r0. 8560 */ 8561.LOP_SGET_WIDE_resolve: 8562 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8563 EXPORT_PC() @ resolve() could throw, so export now 8564 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8565 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8566 cmp r0, #0 @ success? 8567 bne .LOP_SGET_WIDE_finish @ yes, finish 8568 b common_exceptionThrown @ no, handle exception 8569 8570/* continuation for OP_SGET_OBJECT */ 8571 8572 /* 8573 * Continuation if the field has not yet been resolved. 8574 * r1: BBBB field ref 8575 */ 8576.LOP_SGET_OBJECT_resolve: 8577 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8578 EXPORT_PC() @ resolve() could throw, so export now 8579 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8580 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8581 cmp r0, #0 @ success? 8582 bne .LOP_SGET_OBJECT_finish @ yes, finish 8583 b common_exceptionThrown @ no, handle exception 8584 8585/* continuation for OP_SGET_BOOLEAN */ 8586 8587 /* 8588 * Continuation if the field has not yet been resolved. 8589 * r1: BBBB field ref 8590 */ 8591.LOP_SGET_BOOLEAN_resolve: 8592 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8593 EXPORT_PC() @ resolve() could throw, so export now 8594 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8595 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8596 cmp r0, #0 @ success? 8597 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8598 b common_exceptionThrown @ no, handle exception 8599 8600/* continuation for OP_SGET_BYTE */ 8601 8602 /* 8603 * Continuation if the field has not yet been resolved. 8604 * r1: BBBB field ref 8605 */ 8606.LOP_SGET_BYTE_resolve: 8607 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8608 EXPORT_PC() @ resolve() could throw, so export now 8609 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8610 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8611 cmp r0, #0 @ success? 8612 bne .LOP_SGET_BYTE_finish @ yes, finish 8613 b common_exceptionThrown @ no, handle exception 8614 8615/* continuation for OP_SGET_CHAR */ 8616 8617 /* 8618 * Continuation if the field has not yet been resolved. 8619 * r1: BBBB field ref 8620 */ 8621.LOP_SGET_CHAR_resolve: 8622 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8623 EXPORT_PC() @ resolve() could throw, so export now 8624 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8625 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8626 cmp r0, #0 @ success? 8627 bne .LOP_SGET_CHAR_finish @ yes, finish 8628 b common_exceptionThrown @ no, handle exception 8629 8630/* continuation for OP_SGET_SHORT */ 8631 8632 /* 8633 * Continuation if the field has not yet been resolved. 8634 * r1: BBBB field ref 8635 */ 8636.LOP_SGET_SHORT_resolve: 8637 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8638 EXPORT_PC() @ resolve() could throw, so export now 8639 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8640 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8641 cmp r0, #0 @ success? 8642 bne .LOP_SGET_SHORT_finish @ yes, finish 8643 b common_exceptionThrown @ no, handle exception 8644 8645/* continuation for OP_SPUT */ 8646 8647 /* 8648 * Continuation if the field has not yet been resolved. 8649 * r1: BBBB field ref 8650 */ 8651.LOP_SPUT_resolve: 8652 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8653 EXPORT_PC() @ resolve() could throw, so export now 8654 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8655 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8656 cmp r0, #0 @ success? 8657 bne .LOP_SPUT_finish @ yes, finish 8658 b common_exceptionThrown @ no, handle exception 8659 8660/* continuation for OP_SPUT_WIDE */ 8661 8662 /* 8663 * Continuation if the field has not yet been resolved. 8664 * r1: BBBB field ref 8665 * r9: &fp[AA] 8666 * 8667 * Returns StaticField pointer in r2. 8668 */ 8669.LOP_SPUT_WIDE_resolve: 8670 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8671 EXPORT_PC() @ resolve() could throw, so export now 8672 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8673 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8674 cmp r0, #0 @ success? 8675 mov r2, r0 @ copy to r2 8676 bne .LOP_SPUT_WIDE_finish @ yes, finish 8677 b common_exceptionThrown @ no, handle exception 8678 8679/* continuation for OP_SPUT_OBJECT */ 8680.LOP_SPUT_OBJECT_finish: @ field ptr in r0, method in r9 8681 mov r2, rINST, lsr #8 @ r2<- AA 8682 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8683 GET_VREG(r1, r2) @ r1<- fp[AA] 8684 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8685 ldr r9, [r9, #offMethod_clazz] @ r9<- obj head 8686 GET_INST_OPCODE(ip) @ extract opcode from rINST 8687 add r0, #offStaticField_value @ r0<- pointer to store target 8688 @ no-op @ releasing store 8689 str r1, [r0] @ field<- vAA 8690 cmp r1, #0 @ stored a null object? 8691 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 8692 GOTO_OPCODE(ip) @ jump to next instruction 8693 8694/* continuation for OP_SPUT_BOOLEAN */ 8695 8696 /* 8697 * Continuation if the field has not yet been resolved. 8698 * r1: BBBB field ref 8699 */ 8700.LOP_SPUT_BOOLEAN_resolve: 8701 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8702 EXPORT_PC() @ resolve() could throw, so export now 8703 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8704 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8705 cmp r0, #0 @ success? 8706 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 8707 b common_exceptionThrown @ no, handle exception 8708 8709/* continuation for OP_SPUT_BYTE */ 8710 8711 /* 8712 * Continuation if the field has not yet been resolved. 8713 * r1: BBBB field ref 8714 */ 8715.LOP_SPUT_BYTE_resolve: 8716 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8717 EXPORT_PC() @ resolve() could throw, so export now 8718 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8719 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8720 cmp r0, #0 @ success? 8721 bne .LOP_SPUT_BYTE_finish @ yes, finish 8722 b common_exceptionThrown @ no, handle exception 8723 8724/* continuation for OP_SPUT_CHAR */ 8725 8726 /* 8727 * Continuation if the field has not yet been resolved. 8728 * r1: BBBB field ref 8729 */ 8730.LOP_SPUT_CHAR_resolve: 8731 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8732 EXPORT_PC() @ resolve() could throw, so export now 8733 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8734 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8735 cmp r0, #0 @ success? 8736 bne .LOP_SPUT_CHAR_finish @ yes, finish 8737 b common_exceptionThrown @ no, handle exception 8738 8739/* continuation for OP_SPUT_SHORT */ 8740 8741 /* 8742 * Continuation if the field has not yet been resolved. 8743 * r1: BBBB field ref 8744 */ 8745.LOP_SPUT_SHORT_resolve: 8746 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8747 EXPORT_PC() @ resolve() could throw, so export now 8748 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8749 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8750 cmp r0, #0 @ success? 8751 bne .LOP_SPUT_SHORT_finish @ yes, finish 8752 b common_exceptionThrown @ no, handle exception 8753 8754/* continuation for OP_INVOKE_VIRTUAL */ 8755 8756 /* 8757 * At this point: 8758 * r0 = resolved base method 8759 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8760 */ 8761.LOP_INVOKE_VIRTUAL_continue: 8762 GET_VREG(r1, r10) @ r1<- "this" ptr 8763 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8764 cmp r1, #0 @ is "this" null? 8765 beq common_errNullObject @ null "this", throw exception 8766 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8767 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8768 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8769 bl common_invokeMethodNoRange @ continue on 8770 8771/* continuation for OP_INVOKE_SUPER */ 8772 8773 /* 8774 * At this point: 8775 * r0 = resolved base method 8776 * r9 = method->clazz 8777 */ 8778.LOP_INVOKE_SUPER_continue: 8779 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8780 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8781 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8782 EXPORT_PC() @ must export for invoke 8783 cmp r2, r3 @ compare (methodIndex, vtableCount) 8784 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 8785 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8786 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8787 bl common_invokeMethodNoRange @ continue on 8788 8789.LOP_INVOKE_SUPER_resolve: 8790 mov r0, r9 @ r0<- method->clazz 8791 mov r2, #METHOD_VIRTUAL @ resolver method type 8792 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8793 cmp r0, #0 @ got null? 8794 bne .LOP_INVOKE_SUPER_continue @ no, continue 8795 b common_exceptionThrown @ yes, handle exception 8796 8797 /* 8798 * Throw a NoSuchMethodError with the method name as the message. 8799 * r0 = resolved base method 8800 */ 8801.LOP_INVOKE_SUPER_nsm: 8802 ldr r1, [r0, #offMethod_name] @ r1<- method name 8803 b common_errNoSuchMethod 8804 8805/* continuation for OP_INVOKE_DIRECT */ 8806 8807 /* 8808 * On entry: 8809 * r1 = reference (BBBB or CCCC) 8810 * r10 = "this" register 8811 */ 8812.LOP_INVOKE_DIRECT_resolve: 8813 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8814 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8815 mov r2, #METHOD_DIRECT @ resolver method type 8816 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8817 cmp r0, #0 @ got null? 8818 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8819 bne .LOP_INVOKE_DIRECT_finish @ no, continue 8820 b common_exceptionThrown @ yes, handle exception 8821 8822/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 8823 8824 /* 8825 * At this point: 8826 * r0 = resolved base method 8827 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8828 */ 8829.LOP_INVOKE_VIRTUAL_RANGE_continue: 8830 GET_VREG(r1, r10) @ r1<- "this" ptr 8831 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8832 cmp r1, #0 @ is "this" null? 8833 beq common_errNullObject @ null "this", throw exception 8834 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8835 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8836 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8837 bl common_invokeMethodRange @ continue on 8838 8839/* continuation for OP_INVOKE_SUPER_RANGE */ 8840 8841 /* 8842 * At this point: 8843 * r0 = resolved base method 8844 * r9 = method->clazz 8845 */ 8846.LOP_INVOKE_SUPER_RANGE_continue: 8847 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8848 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8849 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8850 EXPORT_PC() @ must export for invoke 8851 cmp r2, r3 @ compare (methodIndex, vtableCount) 8852 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 8853 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8854 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8855 bl common_invokeMethodRange @ continue on 8856 8857.LOP_INVOKE_SUPER_RANGE_resolve: 8858 mov r0, r9 @ r0<- method->clazz 8859 mov r2, #METHOD_VIRTUAL @ resolver method type 8860 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8861 cmp r0, #0 @ got null? 8862 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 8863 b common_exceptionThrown @ yes, handle exception 8864 8865 /* 8866 * Throw a NoSuchMethodError with the method name as the message. 8867 * r0 = resolved base method 8868 */ 8869.LOP_INVOKE_SUPER_RANGE_nsm: 8870 ldr r1, [r0, #offMethod_name] @ r1<- method name 8871 b common_errNoSuchMethod 8872 8873/* continuation for OP_INVOKE_DIRECT_RANGE */ 8874 8875 /* 8876 * On entry: 8877 * r1 = reference (BBBB or CCCC) 8878 * r10 = "this" register 8879 */ 8880.LOP_INVOKE_DIRECT_RANGE_resolve: 8881 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8882 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8883 mov r2, #METHOD_DIRECT @ resolver method type 8884 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8885 cmp r0, #0 @ got null? 8886 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8887 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 8888 b common_exceptionThrown @ yes, handle exception 8889 8890/* continuation for OP_FLOAT_TO_LONG */ 8891/* 8892 * Convert the float in r0 to a long in r0/r1. 8893 * 8894 * We have to clip values to long min/max per the specification. The 8895 * expected common case is a "reasonable" value that converts directly 8896 * to modest integer. The EABI convert function isn't doing this for us. 8897 */ 8898f2l_doconv: 8899 stmfd sp!, {r4, lr} 8900 mov r1, #0x5f000000 @ (float)maxlong 8901 mov r4, r0 8902 bl __aeabi_fcmpge @ is arg >= maxlong? 8903 cmp r0, #0 @ nonzero == yes 8904 mvnne r0, #0 @ return maxlong (7fffffff) 8905 mvnne r1, #0x80000000 8906 ldmnefd sp!, {r4, pc} 8907 8908 mov r0, r4 @ recover arg 8909 mov r1, #0xdf000000 @ (float)minlong 8910 bl __aeabi_fcmple @ is arg <= minlong? 8911 cmp r0, #0 @ nonzero == yes 8912 movne r0, #0 @ return minlong (80000000) 8913 movne r1, #0x80000000 8914 ldmnefd sp!, {r4, pc} 8915 8916 mov r0, r4 @ recover arg 8917 mov r1, r4 8918 bl __aeabi_fcmpeq @ is arg == self? 8919 cmp r0, #0 @ zero == no 8920 moveq r1, #0 @ return zero for NaN 8921 ldmeqfd sp!, {r4, pc} 8922 8923 mov r0, r4 @ recover arg 8924 bl __aeabi_f2lz @ convert float to long 8925 ldmfd sp!, {r4, pc} 8926 8927/* continuation for OP_DOUBLE_TO_LONG */ 8928/* 8929 * Convert the double in r0/r1 to a long in r0/r1. 8930 * 8931 * We have to clip values to long min/max per the specification. The 8932 * expected common case is a "reasonable" value that converts directly 8933 * to modest integer. The EABI convert function isn't doing this for us. 8934 */ 8935d2l_doconv: 8936 stmfd sp!, {r4, r5, lr} @ save regs 8937 mov r3, #0x43000000 @ maxlong, as a double (high word) 8938 add r3, #0x00e00000 @ 0x43e00000 8939 mov r2, #0 @ maxlong, as a double (low word) 8940 sub sp, sp, #4 @ align for EABI 8941 mov r4, r0 @ save a copy of r0 8942 mov r5, r1 @ and r1 8943 bl __aeabi_dcmpge @ is arg >= maxlong? 8944 cmp r0, #0 @ nonzero == yes 8945 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 8946 mvnne r1, #0x80000000 8947 bne 1f 8948 8949 mov r0, r4 @ recover arg 8950 mov r1, r5 8951 mov r3, #0xc3000000 @ minlong, as a double (high word) 8952 add r3, #0x00e00000 @ 0xc3e00000 8953 mov r2, #0 @ minlong, as a double (low word) 8954 bl __aeabi_dcmple @ is arg <= minlong? 8955 cmp r0, #0 @ nonzero == yes 8956 movne r0, #0 @ return minlong (8000000000000000) 8957 movne r1, #0x80000000 8958 bne 1f 8959 8960 mov r0, r4 @ recover arg 8961 mov r1, r5 8962 mov r2, r4 @ compare against self 8963 mov r3, r5 8964 bl __aeabi_dcmpeq @ is arg == self? 8965 cmp r0, #0 @ zero == no 8966 moveq r1, #0 @ return zero for NaN 8967 beq 1f 8968 8969 mov r0, r4 @ recover arg 8970 mov r1, r5 8971 bl __aeabi_d2lz @ convert double to long 8972 89731: 8974 add sp, sp, #4 8975 ldmfd sp!, {r4, r5, pc} 8976 8977/* continuation for OP_MUL_LONG */ 8978 8979.LOP_MUL_LONG_finish: 8980 GET_INST_OPCODE(ip) @ extract opcode from rINST 8981 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 8982 GOTO_OPCODE(ip) @ jump to next instruction 8983 8984/* continuation for OP_SHL_LONG */ 8985 8986.LOP_SHL_LONG_finish: 8987 mov r0, r0, asl r2 @ r0<- r0 << r2 8988 GET_INST_OPCODE(ip) @ extract opcode from rINST 8989 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8990 GOTO_OPCODE(ip) @ jump to next instruction 8991 8992/* continuation for OP_SHR_LONG */ 8993 8994.LOP_SHR_LONG_finish: 8995 mov r1, r1, asr r2 @ r1<- r1 >> r2 8996 GET_INST_OPCODE(ip) @ extract opcode from rINST 8997 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8998 GOTO_OPCODE(ip) @ jump to next instruction 8999 9000/* continuation for OP_USHR_LONG */ 9001 9002.LOP_USHR_LONG_finish: 9003 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 9004 GET_INST_OPCODE(ip) @ extract opcode from rINST 9005 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9006 GOTO_OPCODE(ip) @ jump to next instruction 9007 9008/* continuation for OP_SHL_LONG_2ADDR */ 9009 9010.LOP_SHL_LONG_2ADDR_finish: 9011 GET_INST_OPCODE(ip) @ extract opcode from rINST 9012 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9013 GOTO_OPCODE(ip) @ jump to next instruction 9014 9015/* continuation for OP_SHR_LONG_2ADDR */ 9016 9017.LOP_SHR_LONG_2ADDR_finish: 9018 GET_INST_OPCODE(ip) @ extract opcode from rINST 9019 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9020 GOTO_OPCODE(ip) @ jump to next instruction 9021 9022/* continuation for OP_USHR_LONG_2ADDR */ 9023 9024.LOP_USHR_LONG_2ADDR_finish: 9025 GET_INST_OPCODE(ip) @ extract opcode from rINST 9026 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9027 GOTO_OPCODE(ip) @ jump to next instruction 9028 9029/* continuation for OP_IGET_VOLATILE */ 9030 9031 /* 9032 * Currently: 9033 * r0 holds resolved field 9034 * r9 holds object 9035 */ 9036.LOP_IGET_VOLATILE_finish: 9037 @bl common_squeak0 9038 cmp r9, #0 @ check object for null 9039 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9040 beq common_errNullObject @ object was null 9041 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9042 SMP_DMB @ acquiring load 9043 mov r2, rINST, lsr #8 @ r2<- A+ 9044 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9045 and r2, r2, #15 @ r2<- A 9046 GET_INST_OPCODE(ip) @ extract opcode from rINST 9047 SET_VREG(r0, r2) @ fp[A]<- r0 9048 GOTO_OPCODE(ip) @ jump to next instruction 9049 9050/* continuation for OP_IPUT_VOLATILE */ 9051 9052 /* 9053 * Currently: 9054 * r0 holds resolved field 9055 * r9 holds object 9056 */ 9057.LOP_IPUT_VOLATILE_finish: 9058 @bl common_squeak0 9059 mov r1, rINST, lsr #8 @ r1<- A+ 9060 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9061 and r1, r1, #15 @ r1<- A 9062 cmp r9, #0 @ check object for null 9063 GET_VREG(r0, r1) @ r0<- fp[A] 9064 beq common_errNullObject @ object was null 9065 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9066 GET_INST_OPCODE(ip) @ extract opcode from rINST 9067 SMP_DMB @ releasing store 9068 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 9069 GOTO_OPCODE(ip) @ jump to next instruction 9070 9071/* continuation for OP_SGET_VOLATILE */ 9072 9073 /* 9074 * Continuation if the field has not yet been resolved. 9075 * r1: BBBB field ref 9076 */ 9077.LOP_SGET_VOLATILE_resolve: 9078 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9079 EXPORT_PC() @ resolve() could throw, so export now 9080 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9081 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9082 cmp r0, #0 @ success? 9083 bne .LOP_SGET_VOLATILE_finish @ yes, finish 9084 b common_exceptionThrown @ no, handle exception 9085 9086/* continuation for OP_SPUT_VOLATILE */ 9087 9088 /* 9089 * Continuation if the field has not yet been resolved. 9090 * r1: BBBB field ref 9091 */ 9092.LOP_SPUT_VOLATILE_resolve: 9093 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9094 EXPORT_PC() @ resolve() could throw, so export now 9095 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9096 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9097 cmp r0, #0 @ success? 9098 bne .LOP_SPUT_VOLATILE_finish @ yes, finish 9099 b common_exceptionThrown @ no, handle exception 9100 9101/* continuation for OP_IGET_OBJECT_VOLATILE */ 9102 9103 /* 9104 * Currently: 9105 * r0 holds resolved field 9106 * r9 holds object 9107 */ 9108.LOP_IGET_OBJECT_VOLATILE_finish: 9109 @bl common_squeak0 9110 cmp r9, #0 @ check object for null 9111 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9112 beq common_errNullObject @ object was null 9113 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9114 SMP_DMB @ acquiring load 9115 mov r2, rINST, lsr #8 @ r2<- A+ 9116 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9117 and r2, r2, #15 @ r2<- A 9118 GET_INST_OPCODE(ip) @ extract opcode from rINST 9119 SET_VREG(r0, r2) @ fp[A]<- r0 9120 GOTO_OPCODE(ip) @ jump to next instruction 9121 9122/* continuation for OP_IGET_WIDE_VOLATILE */ 9123 9124 /* 9125 * Currently: 9126 * r0 holds resolved field 9127 * r9 holds object 9128 */ 9129.LOP_IGET_WIDE_VOLATILE_finish: 9130 cmp r9, #0 @ check object for null 9131 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9132 beq common_errNullObject @ object was null 9133 .if 1 9134 add r0, r9, r3 @ r0<- address of field 9135 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 9136 .else 9137 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 9138 .endif 9139 mov r2, rINST, lsr #8 @ r2<- A+ 9140 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9141 and r2, r2, #15 @ r2<- A 9142 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 9143 GET_INST_OPCODE(ip) @ extract opcode from rINST 9144 stmia r3, {r0-r1} @ fp[A]<- r0/r1 9145 GOTO_OPCODE(ip) @ jump to next instruction 9146 9147/* continuation for OP_IPUT_WIDE_VOLATILE */ 9148 9149 /* 9150 * Currently: 9151 * r0 holds resolved field 9152 * r9 holds object 9153 */ 9154.LOP_IPUT_WIDE_VOLATILE_finish: 9155 mov r2, rINST, lsr #8 @ r2<- A+ 9156 cmp r9, #0 @ check object for null 9157 and r2, r2, #15 @ r2<- A 9158 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9159 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 9160 beq common_errNullObject @ object was null 9161 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9162 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 9163 GET_INST_OPCODE(r10) @ extract opcode from rINST 9164 .if 1 9165 add r2, r9, r3 @ r2<- target address 9166 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 9167 .else 9168 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 9169 .endif 9170 GOTO_OPCODE(r10) @ jump to next instruction 9171 9172/* continuation for OP_SGET_WIDE_VOLATILE */ 9173 9174 /* 9175 * Continuation if the field has not yet been resolved. 9176 * r1: BBBB field ref 9177 * 9178 * Returns StaticField pointer in r0. 9179 */ 9180.LOP_SGET_WIDE_VOLATILE_resolve: 9181 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9182 EXPORT_PC() @ resolve() could throw, so export now 9183 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9184 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9185 cmp r0, #0 @ success? 9186 bne .LOP_SGET_WIDE_VOLATILE_finish @ yes, finish 9187 b common_exceptionThrown @ no, handle exception 9188 9189/* continuation for OP_SPUT_WIDE_VOLATILE */ 9190 9191 /* 9192 * Continuation if the field has not yet been resolved. 9193 * r1: BBBB field ref 9194 * r9: &fp[AA] 9195 * 9196 * Returns StaticField pointer in r2. 9197 */ 9198.LOP_SPUT_WIDE_VOLATILE_resolve: 9199 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9200 EXPORT_PC() @ resolve() could throw, so export now 9201 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9202 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9203 cmp r0, #0 @ success? 9204 mov r2, r0 @ copy to r2 9205 bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish 9206 b common_exceptionThrown @ no, handle exception 9207 9208/* continuation for OP_EXECUTE_INLINE */ 9209 9210 /* 9211 * Extract args, call function. 9212 * r0 = #of args (0-4) 9213 * r10 = call index 9214 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9215 * 9216 * Other ideas: 9217 * - Use a jump table from the main piece to jump directly into the 9218 * AND/LDR pairs. Costs a data load, saves a branch. 9219 * - Have five separate pieces that do the loading, so we can work the 9220 * interleave a little better. Increases code size. 9221 */ 9222.LOP_EXECUTE_INLINE_continue: 9223 rsb r0, r0, #4 @ r0<- 4-r0 9224 FETCH(r9, 2) @ r9<- FEDC 9225 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9226 bl common_abort @ (skipped due to ARM prefetch) 92274: and ip, r9, #0xf000 @ isolate F 9228 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 92293: and ip, r9, #0x0f00 @ isolate E 9230 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 92312: and ip, r9, #0x00f0 @ isolate D 9232 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 92331: and ip, r9, #0x000f @ isolate C 9234 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 92350: 9236 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 9237 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9238 @ (not reached) 9239 9240.LOP_EXECUTE_INLINE_table: 9241 .word gDvmInlineOpsTable 9242 9243/* continuation for OP_EXECUTE_INLINE_RANGE */ 9244 9245 /* 9246 * Extract args, call function. 9247 * r0 = #of args (0-4) 9248 * r10 = call index 9249 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9250 */ 9251.LOP_EXECUTE_INLINE_RANGE_continue: 9252 rsb r0, r0, #4 @ r0<- 4-r0 9253 FETCH(r9, 2) @ r9<- CCCC 9254 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9255 bl common_abort @ (skipped due to ARM prefetch) 92564: add ip, r9, #3 @ base+3 9257 GET_VREG(r3, ip) @ r3<- vBase[3] 92583: add ip, r9, #2 @ base+2 9259 GET_VREG(r2, ip) @ r2<- vBase[2] 92602: add ip, r9, #1 @ base+1 9261 GET_VREG(r1, ip) @ r1<- vBase[1] 92621: add ip, r9, #0 @ (nop) 9263 GET_VREG(r0, ip) @ r0<- vBase[0] 92640: 9265 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation 9266 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9267 @ (not reached) 9268 9269.LOP_EXECUTE_INLINE_RANGE_table: 9270 .word gDvmInlineOpsTable 9271 9272/* continuation for OP_IPUT_OBJECT_VOLATILE */ 9273 9274 /* 9275 * Currently: 9276 * r0 holds resolved field 9277 * r9 holds object 9278 */ 9279.LOP_IPUT_OBJECT_VOLATILE_finish: 9280 @bl common_squeak0 9281 mov r1, rINST, lsr #8 @ r1<- A+ 9282 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9283 and r1, r1, #15 @ r1<- A 9284 cmp r9, #0 @ check object for null 9285 GET_VREG(r0, r1) @ r0<- fp[A] 9286 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 9287 beq common_errNullObject @ object was null 9288 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9289 GET_INST_OPCODE(ip) @ extract opcode from rINST 9290 SMP_DMB @ releasing store 9291 str r0, [r9,r3] @ obj.field (32 bits)<- r0 9292 cmp r0, #0 @ stored a null reference? 9293 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 9294 GOTO_OPCODE(ip) @ jump to next instruction 9295 9296/* continuation for OP_SGET_OBJECT_VOLATILE */ 9297 9298 /* 9299 * Continuation if the field has not yet been resolved. 9300 * r1: BBBB field ref 9301 */ 9302.LOP_SGET_OBJECT_VOLATILE_resolve: 9303 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9304 EXPORT_PC() @ resolve() could throw, so export now 9305 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9306 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9307 cmp r0, #0 @ success? 9308 bne .LOP_SGET_OBJECT_VOLATILE_finish @ yes, finish 9309 b common_exceptionThrown @ no, handle exception 9310 9311/* continuation for OP_SPUT_OBJECT_VOLATILE */ 9312.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0, method in r9 9313 mov r2, rINST, lsr #8 @ r2<- AA 9314 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9315 GET_VREG(r1, r2) @ r1<- fp[AA] 9316 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 9317 ldr r9, [r9, #offMethod_clazz] @ r9<- obj head 9318 GET_INST_OPCODE(ip) @ extract opcode from rINST 9319 add r0, #offStaticField_value @ r0<- pointer to store target 9320 SMP_DMB @ releasing store 9321 str r1, [r0] @ field<- vAA 9322 cmp r1, #0 @ stored a null object? 9323 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 9324 GOTO_OPCODE(ip) @ jump to next instruction 9325 9326 .size dvmAsmSisterStart, .-dvmAsmSisterStart 9327 .global dvmAsmSisterEnd 9328dvmAsmSisterEnd: 9329 9330/* File: armv5te/footer.S */ 9331 9332/* 9333 * =========================================================================== 9334 * Common subroutines and data 9335 * =========================================================================== 9336 */ 9337 9338 9339 9340 .text 9341 .align 2 9342 9343#if defined(WITH_JIT) 9344#if defined(WITH_SELF_VERIFICATION) 9345 .global dvmJitToInterpPunt 9346dvmJitToInterpPunt: 9347 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9348 mov r2,#kSVSPunt @ r2<- interpreter entry point 9349 mov r3, #0 9350 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9351 b jitSVShadowRunEnd @ doesn't return 9352 9353 .global dvmJitToInterpSingleStep 9354dvmJitToInterpSingleStep: 9355 str lr,[rGLUE,#offGlue_jitResumeNPC] 9356 str r1,[rGLUE,#offGlue_jitResumeDPC] 9357 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 9358 b jitSVShadowRunEnd @ doesn't return 9359 9360 .global dvmJitToInterpNoChainNoProfile 9361dvmJitToInterpNoChainNoProfile: 9362 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9363 mov r0,rPC @ pass our target PC 9364 mov r2,#kSVSNoProfile @ r2<- interpreter entry point 9365 mov r3, #0 @ 0 means !inJitCodeCache 9366 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land 9367 b jitSVShadowRunEnd @ doesn't return 9368 9369 .global dvmJitToInterpTraceSelectNoChain 9370dvmJitToInterpTraceSelectNoChain: 9371 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9372 mov r0,rPC @ pass our target PC 9373 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9374 mov r3, #0 @ 0 means !inJitCodeCache 9375 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9376 b jitSVShadowRunEnd @ doesn't return 9377 9378 .global dvmJitToInterpTraceSelect 9379dvmJitToInterpTraceSelect: 9380 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9381 ldr r0,[lr, #-1] @ pass our target PC 9382 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9383 mov r3, #0 @ 0 means !inJitCodeCache 9384 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9385 b jitSVShadowRunEnd @ doesn't return 9386 9387 .global dvmJitToInterpBackwardBranch 9388dvmJitToInterpBackwardBranch: 9389 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9390 ldr r0,[lr, #-1] @ pass our target PC 9391 mov r2,#kSVSBackwardBranch @ 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 dvmJitToInterpNormal 9397dvmJitToInterpNormal: 9398 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9399 ldr r0,[lr, #-1] @ pass our target PC 9400 mov r2,#kSVSNormal @ 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 dvmJitToInterpNoChain 9406dvmJitToInterpNoChain: 9407 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9408 mov r0,rPC @ pass our target PC 9409 mov r2,#kSVSNoChain @ 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#else 9414/* 9415 * Return from the translation cache to the interpreter when the compiler is 9416 * having issues translating/executing a Dalvik instruction. We have to skip 9417 * the code cache lookup otherwise it is possible to indefinitely bouce 9418 * between the interpreter and the code cache if the instruction that fails 9419 * to be compiled happens to be at a trace start. 9420 */ 9421 .global dvmJitToInterpPunt 9422dvmJitToInterpPunt: 9423 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9424 mov rPC, r0 9425#if defined(WITH_JIT_TUNING) 9426 mov r0,lr 9427 bl dvmBumpPunt; 9428#endif 9429 EXPORT_PC() 9430 mov r0, #0 9431 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9432 adrl rIBASE, dvmAsmInstructionStart 9433 FETCH_INST() 9434 GET_INST_OPCODE(ip) 9435 GOTO_OPCODE(ip) 9436 9437/* 9438 * Return to the interpreter to handle a single instruction. 9439 * On entry: 9440 * r0 <= PC 9441 * r1 <= PC of resume instruction 9442 * lr <= resume point in translation 9443 */ 9444 .global dvmJitToInterpSingleStep 9445dvmJitToInterpSingleStep: 9446 str lr,[rGLUE,#offGlue_jitResumeNPC] 9447 str r1,[rGLUE,#offGlue_jitResumeDPC] 9448 mov r1,#kInterpEntryInstr 9449 @ enum is 4 byte in aapcs-EABI 9450 str r1, [rGLUE, #offGlue_entryPoint] 9451 mov rPC,r0 9452 EXPORT_PC() 9453 9454 adrl rIBASE, dvmAsmInstructionStart 9455 mov r2,#kJitSingleStep @ Ask for single step and then revert 9456 str r2,[rGLUE,#offGlue_jitState] 9457 mov r1,#1 @ set changeInterp to bail to debug interp 9458 b common_gotoBail 9459 9460/* 9461 * Return from the translation cache and immediately request 9462 * a translation for the exit target. Commonly used for callees. 9463 */ 9464 .global dvmJitToInterpTraceSelectNoChain 9465dvmJitToInterpTraceSelectNoChain: 9466#if defined(WITH_JIT_TUNING) 9467 bl dvmBumpNoChain 9468#endif 9469 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9470 mov r0,rPC 9471 bl dvmJitGetCodeAddr @ Is there a translation? 9472 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9473 mov r1, rPC @ arg1 of translation may need this 9474 mov lr, #0 @ in case target is HANDLER_INTERPRET 9475 cmp r0,#0 @ !0 means translation exists 9476 bxne r0 @ continue native execution if so 9477 b 2f @ branch over to use the interpreter 9478 9479/* 9480 * Return from the translation cache and immediately request 9481 * a translation for the exit target. Commonly used following 9482 * invokes. 9483 */ 9484 .global dvmJitToInterpTraceSelect 9485dvmJitToInterpTraceSelect: 9486 ldr rPC,[lr, #-1] @ get our target PC 9487 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9488 add rINST,lr,#-5 @ save start of chain branch 9489 add rINST, #-4 @ .. which is 9 bytes back 9490 mov r0,rPC 9491 bl dvmJitGetCodeAddr @ Is there a translation? 9492 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9493 cmp r0,#0 9494 beq 2f 9495 mov r1,rINST 9496 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9497 mov r1, rPC @ arg1 of translation may need this 9498 mov lr, #0 @ in case target is HANDLER_INTERPRET 9499 cmp r0,#0 @ successful chain? 9500 bxne r0 @ continue native execution 9501 b toInterpreter @ didn't chain - resume with interpreter 9502 9503/* No translation, so request one if profiling isn't disabled*/ 95042: 9505 adrl rIBASE, dvmAsmInstructionStart 9506 GET_JIT_PROF_TABLE(r0) 9507 FETCH_INST() 9508 cmp r0, #0 9509 movne r2,#kJitTSelectRequestHot @ ask for trace selection 9510 bne common_selectTrace 9511 GET_INST_OPCODE(ip) 9512 GOTO_OPCODE(ip) 9513 9514/* 9515 * Return from the translation cache to the interpreter. 9516 * The return was done with a BLX from thumb mode, and 9517 * the following 32-bit word contains the target rPC value. 9518 * Note that lr (r14) will have its low-order bit set to denote 9519 * its thumb-mode origin. 9520 * 9521 * We'll need to stash our lr origin away, recover the new 9522 * target and then check to see if there is a translation available 9523 * for our new target. If so, we do a translation chain and 9524 * go back to native execution. Otherwise, it's back to the 9525 * interpreter (after treating this entry as a potential 9526 * trace start). 9527 */ 9528 .global dvmJitToInterpNormal 9529dvmJitToInterpNormal: 9530 ldr rPC,[lr, #-1] @ get our target PC 9531 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9532 add rINST,lr,#-5 @ save start of chain branch 9533 add rINST,#-4 @ .. which is 9 bytes back 9534#if defined(WITH_JIT_TUNING) 9535 bl dvmBumpNormal 9536#endif 9537 mov r0,rPC 9538 bl dvmJitGetCodeAddr @ Is there a translation? 9539 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9540 cmp r0,#0 9541 beq toInterpreter @ go if not, otherwise do chain 9542 mov r1,rINST 9543 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9544 mov r1, rPC @ arg1 of translation may need this 9545 mov lr, #0 @ in case target is HANDLER_INTERPRET 9546 cmp r0,#0 @ successful chain? 9547 bxne r0 @ continue native execution 9548 b toInterpreter @ didn't chain - resume with interpreter 9549 9550/* 9551 * Return from the translation cache to the interpreter to do method invocation. 9552 * Check if translation exists for the callee, but don't chain to it. 9553 */ 9554 .global dvmJitToInterpNoChainNoProfile 9555dvmJitToInterpNoChainNoProfile: 9556#if defined(WITH_JIT_TUNING) 9557 bl dvmBumpNoChain 9558#endif 9559 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9560 mov r0,rPC 9561 bl dvmJitGetCodeAddr @ Is there a translation? 9562 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9563 mov r1, rPC @ arg1 of translation may need this 9564 mov lr, #0 @ in case target is HANDLER_INTERPRET 9565 cmp r0,#0 9566 bxne r0 @ continue native execution if so 9567 EXPORT_PC() 9568 adrl rIBASE, dvmAsmInstructionStart 9569 FETCH_INST() 9570 GET_INST_OPCODE(ip) @ extract opcode from rINST 9571 GOTO_OPCODE(ip) @ jump to next instruction 9572 9573/* 9574 * Return from the translation cache to the interpreter to do method invocation. 9575 * Check if translation exists for the callee, but don't chain to it. 9576 */ 9577 .global dvmJitToInterpNoChain 9578dvmJitToInterpNoChain: 9579#if defined(WITH_JIT_TUNING) 9580 bl dvmBumpNoChain 9581#endif 9582 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9583 mov r0,rPC 9584 bl dvmJitGetCodeAddr @ Is there a translation? 9585 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9586 mov r1, rPC @ arg1 of translation may need this 9587 mov lr, #0 @ in case target is HANDLER_INTERPRET 9588 cmp r0,#0 9589 bxne r0 @ continue native execution if so 9590#endif 9591 9592/* 9593 * No translation, restore interpreter regs and start interpreting. 9594 * rGLUE & rFP were preserved in the translated code, and rPC has 9595 * already been restored by the time we get here. We'll need to set 9596 * up rIBASE & rINST, and load the address of the JitTable into r0. 9597 */ 9598toInterpreter: 9599 EXPORT_PC() 9600 adrl rIBASE, dvmAsmInstructionStart 9601 FETCH_INST() 9602 GET_JIT_PROF_TABLE(r0) 9603 @ NOTE: intended fallthrough 9604 9605/* 9606 * Common code to update potential trace start counter, and initiate 9607 * a trace-build if appropriate. On entry, rPC should point to the 9608 * next instruction to execute, and rINST should be already loaded with 9609 * the next opcode word, and r0 holds a pointer to the jit profile 9610 * table (pJitProfTable). 9611 */ 9612common_testUpdateProfile: 9613 cmp r0,#0 9614 GET_INST_OPCODE(ip) 9615 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 9616 9617common_updateProfile: 9618 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 9619 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits 9620 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter 9621 GET_INST_OPCODE(ip) 9622 subs r1,r1,#1 @ decrement counter 9623 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it 9624 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 9625 9626/* 9627 * Here, we switch to the debug interpreter to request 9628 * trace selection. First, though, check to see if there 9629 * is already a native translation in place (and, if so, 9630 * jump to it now). 9631 */ 9632 GET_JIT_THRESHOLD(r1) 9633 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9634 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter 9635 EXPORT_PC() 9636 mov r0,rPC 9637 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC) 9638 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9639 mov r1, rPC @ arg1 of translation may need this 9640 mov lr, #0 @ in case target is HANDLER_INTERPRET 9641 cmp r0,#0 9642#if !defined(WITH_SELF_VERIFICATION) 9643 bxne r0 @ jump to the translation 9644 mov r2,#kJitTSelectRequest @ ask for trace selection 9645 @ fall-through to common_selectTrace 9646#else 9647 moveq r2,#kJitTSelectRequest @ ask for trace selection 9648 beq common_selectTrace 9649 /* 9650 * At this point, we have a target translation. However, if 9651 * that translation is actually the interpret-only pseudo-translation 9652 * we want to treat it the same as no translation. 9653 */ 9654 mov r10, r0 @ save target 9655 bl dvmCompilerGetInterpretTemplate 9656 cmp r0, r10 @ special case? 9657 bne jitSVShadowRunStart @ set up self verification shadow space 9658 @ Need to clear the inJitCodeCache flag 9659 ldr r10, [rGLUE, #offGlue_self] @ r10 <- glue->self 9660 mov r3, #0 @ 0 means not in the JIT code cache 9661 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land 9662 GET_INST_OPCODE(ip) 9663 GOTO_OPCODE(ip) 9664 /* no return */ 9665#endif 9666 9667/* 9668 * On entry: 9669 * r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot 9670 */ 9671common_selectTrace: 9672 str r2,[rGLUE,#offGlue_jitState] 9673 mov r2,#kInterpEntryInstr @ normal entry reason 9674 str r2,[rGLUE,#offGlue_entryPoint] 9675 mov r1,#1 @ set changeInterp 9676 b common_gotoBail 9677 9678#if defined(WITH_SELF_VERIFICATION) 9679/* 9680 * Save PC and registers to shadow memory for self verification mode 9681 * before jumping to native translation. 9682 * On entry: 9683 * rPC, rFP, rGLUE: the values that they should contain 9684 * r10: the address of the target translation. 9685 */ 9686jitSVShadowRunStart: 9687 mov r0,rPC @ r0<- program counter 9688 mov r1,rFP @ r1<- frame pointer 9689 mov r2,rGLUE @ r2<- InterpState pointer 9690 mov r3,r10 @ r3<- target translation 9691 bl dvmSelfVerificationSaveState @ save registers to shadow space 9692 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 9693 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 9694 bx r10 @ jump to the translation 9695 9696/* 9697 * Restore PC, registers, and interpState to original values 9698 * before jumping back to the interpreter. 9699 */ 9700jitSVShadowRunEnd: 9701 mov r1,rFP @ pass ending fp 9702 bl dvmSelfVerificationRestoreState @ restore pc and fp values 9703 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 9704 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 9705 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 9706 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 9707 cmp r1,#0 @ check for punt condition 9708 beq 1f 9709 mov r2,#kJitSelfVerification @ ask for self verification 9710 str r2,[rGLUE,#offGlue_jitState] 9711 mov r2,#kInterpEntryInstr @ normal entry reason 9712 str r2,[rGLUE,#offGlue_entryPoint] 9713 mov r1,#1 @ set changeInterp 9714 b common_gotoBail 9715 97161: @ exit to interpreter without check 9717 EXPORT_PC() 9718 adrl rIBASE, dvmAsmInstructionStart 9719 FETCH_INST() 9720 GET_INST_OPCODE(ip) 9721 GOTO_OPCODE(ip) 9722#endif 9723 9724#endif 9725 9726/* 9727 * Common code when a backward branch is taken. 9728 * 9729 * TODO: we could avoid a branch by just setting r0 and falling through 9730 * into the common_periodicChecks code, and having a test on r0 at the 9731 * end determine if we should return to the caller or update & branch to 9732 * the next instr. 9733 * 9734 * On entry: 9735 * r9 is PC adjustment *in bytes* 9736 */ 9737common_backwardBranch: 9738 mov r0, #kInterpEntryInstr 9739 bl common_periodicChecks 9740#if defined(WITH_JIT) 9741 GET_JIT_PROF_TABLE(r0) 9742 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9743 cmp r0,#0 9744 bne common_updateProfile 9745 GET_INST_OPCODE(ip) 9746 GOTO_OPCODE(ip) 9747#else 9748 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9749 GET_INST_OPCODE(ip) @ extract opcode from rINST 9750 GOTO_OPCODE(ip) @ jump to next instruction 9751#endif 9752 9753 9754/* 9755 * Need to see if the thread needs to be suspended or debugger/profiler 9756 * activity has begun. If so, we suspend the thread or side-exit to 9757 * the debug interpreter as appropriate. 9758 * 9759 * The common case is no activity on any of these, so we want to figure 9760 * that out quickly. If something is up, we can then sort out what. 9761 * 9762 * We want to be fast if the VM was built without debugger or profiler 9763 * support, but we also need to recognize that the system is usually 9764 * shipped with both of these enabled. 9765 * 9766 * TODO: reduce this so we're just checking a single location. 9767 * 9768 * On entry: 9769 * r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling) 9770 * r9 is trampoline PC adjustment *in bytes* 9771 */ 9772common_periodicChecks: 9773 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9774 9775 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9776 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9777 9778 ldr ip, [r3] @ ip<- suspendCount (int) 9779 9780 cmp r1, #0 @ debugger enabled? 9781 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9782 ldr r2, [r2] @ r2<- activeProfilers (int) 9783 orrnes ip, ip, r1 @ ip<- suspendCount | debuggerActive 9784 /* 9785 * Don't switch the interpreter in the libdvm_traceview build even if the 9786 * profiler is active. 9787 * The code here is opted for less intrusion instead of performance. 9788 * That is, *pActiveProfilers is still loaded into r2 even though it is not 9789 * used when WITH_INLINE_PROFILING is defined. 9790 */ 9791#if !defined(WITH_INLINE_PROFILING) 9792 orrs ip, ip, r2 @ ip<- suspend|debugger|profiler; set Z 9793#endif 9794 9795 9796 bxeq lr @ all zero, return 9797 9798 /* 9799 * One or more interesting events have happened. Figure out what. 9800 * 9801 * If debugging or profiling are compiled in, we need to disambiguate. 9802 * 9803 * r0 still holds the reentry type. 9804 */ 9805 ldr ip, [r3] @ ip<- suspendCount (int) 9806 cmp ip, #0 @ want suspend? 9807 beq 1f @ no, must be debugger/profiler 9808 9809 stmfd sp!, {r0, lr} @ preserve r0 and lr 9810#if defined(WITH_JIT) 9811 /* 9812 * Refresh the Jit's cached copy of profile table pointer. This pointer 9813 * doubles as the Jit's on/off switch. 9814 */ 9815 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable 9816 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9817 ldr r3, [r3] @ r3 <- pJitProfTable 9818 EXPORT_PC() @ need for precise GC 9819 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch 9820#else 9821 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9822 EXPORT_PC() @ need for precise GC 9823#endif 9824 bl dvmCheckSuspendPending @ do full check, suspend if necessary 9825 ldmfd sp!, {r0, lr} @ restore r0 and lr 9826 9827 /* 9828 * Reload the debugger/profiler enable flags. We're checking to see 9829 * if either of these got set while we were suspended. 9830 * 9831 * If WITH_INLINE_PROFILING is configured, don't check whether the profiler 9832 * is enabled or not as the profiling will be done inline. 9833 */ 9834 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9835 cmp r1, #0 @ debugger enabled? 9836 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9837 9838#if !defined(WITH_INLINE_PROFILING) 9839 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9840 ldr r2, [r2] @ r2<- activeProfilers (int) 9841 orrs r1, r1, r2 9842#else 9843 cmp r1, #0 @ only consult the debuggerActive flag 9844#endif 9845 9846 beq 2f 9847 98481: @ debugger/profiler enabled, bail out; glue->entryPoint was set above 9849 str r0, [rGLUE, #offGlue_entryPoint] @ store r0, need for debug/prof 9850 add rPC, rPC, r9 @ update rPC 9851 mov r1, #1 @ "want switch" = true 9852 b common_gotoBail @ side exit 9853 98542: 9855 bx lr @ nothing to do, return 9856 9857 9858/* 9859 * The equivalent of "goto bail", this calls through the "bail handler". 9860 * 9861 * State registers will be saved to the "glue" area before bailing. 9862 * 9863 * On entry: 9864 * r1 is "bool changeInterp", indicating if we want to switch to the 9865 * other interpreter or just bail all the way out 9866 */ 9867common_gotoBail: 9868 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9869 mov r0, rGLUE @ r0<- glue ptr 9870 b dvmMterpStdBail @ call(glue, changeInterp) 9871 9872 @add r1, r1, #1 @ using (boolean+1) 9873 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9874 @bl _longjmp @ does not return 9875 @bl common_abort 9876 9877 9878/* 9879 * Common code for method invocation with range. 9880 * 9881 * On entry: 9882 * r0 is "Method* methodToCall", the method we're trying to call 9883 */ 9884common_invokeMethodRange: 9885.LinvokeNewRange: 9886 @ prepare to copy args to "outs" area of current frame 9887 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9888 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9889 beq .LinvokeArgsDone @ if no args, skip the rest 9890 FETCH(r1, 2) @ r1<- CCCC 9891 9892 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9893 @ (very few methods have > 10 args; could unroll for common cases) 9894 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9895 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9896 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 98971: ldr r1, [r3], #4 @ val = *fp++ 9898 subs r2, r2, #1 @ count-- 9899 str r1, [r10], #4 @ *outs++ = val 9900 bne 1b @ ...while count != 0 9901 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9902 b .LinvokeArgsDone 9903 9904/* 9905 * Common code for method invocation without range. 9906 * 9907 * On entry: 9908 * r0 is "Method* methodToCall", the method we're trying to call 9909 */ 9910common_invokeMethodNoRange: 9911.LinvokeNewNoRange: 9912 @ prepare to copy args to "outs" area of current frame 9913 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9914 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9915 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9916 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9917 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9918 beq .LinvokeArgsDone 9919 9920 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9921.LinvokeNonRange: 9922 rsb r2, r2, #5 @ r2<- 5-r2 9923 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9924 bl common_abort @ (skipped due to ARM prefetch) 99255: and ip, rINST, #0x0f00 @ isolate A 9926 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 9927 mov r0, r0 @ nop 9928 str r2, [r10, #-4]! @ *--outs = vA 99294: and ip, r1, #0xf000 @ isolate G 9930 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 9931 mov r0, r0 @ nop 9932 str r2, [r10, #-4]! @ *--outs = vG 99333: and ip, r1, #0x0f00 @ isolate F 9934 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 9935 mov r0, r0 @ nop 9936 str r2, [r10, #-4]! @ *--outs = vF 99372: and ip, r1, #0x00f0 @ isolate E 9938 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 9939 mov r0, r0 @ nop 9940 str r2, [r10, #-4]! @ *--outs = vE 99411: and ip, r1, #0x000f @ isolate D 9942 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 9943 mov r0, r0 @ nop 9944 str r2, [r10, #-4]! @ *--outs = vD 99450: @ fall through to .LinvokeArgsDone 9946 9947.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 9948 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 9949 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 9950 @ find space for the new stack frame, check for overflow 9951 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 9952 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 9953 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 9954@ bl common_dumpRegs 9955 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 9956 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 9957 cmp r3, r9 @ bottom < interpStackEnd? 9958 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 9959 blo .LstackOverflow @ yes, this frame will overflow stack 9960 9961 @ set up newSaveArea 9962#ifdef EASY_GDB 9963 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 9964 str ip, [r10, #offStackSaveArea_prevSave] 9965#endif 9966 str rFP, [r10, #offStackSaveArea_prevFrame] 9967 str rPC, [r10, #offStackSaveArea_savedPc] 9968#if defined(WITH_JIT) 9969 mov r9, #0 9970 str r9, [r10, #offStackSaveArea_returnAddr] 9971#endif 9972#if defined(WITH_INLINE_PROFILING) 9973 stmfd sp!, {r0-r3} @ preserve r0-r3 9974 mov r1, r6 9975 @ r0=methodToCall, r1=rGlue 9976 bl dvmFastMethodTraceEnter 9977 ldmfd sp!, {r0-r3} @ restore r0-r3 9978#endif 9979 str r0, [r10, #offStackSaveArea_method] 9980 tst r3, #ACC_NATIVE 9981 bne .LinvokeNative 9982 9983 /* 9984 stmfd sp!, {r0-r3} 9985 bl common_printNewline 9986 mov r0, rFP 9987 mov r1, #0 9988 bl dvmDumpFp 9989 ldmfd sp!, {r0-r3} 9990 stmfd sp!, {r0-r3} 9991 mov r0, r1 9992 mov r1, r10 9993 bl dvmDumpFp 9994 bl common_printNewline 9995 ldmfd sp!, {r0-r3} 9996 */ 9997 9998 ldrh r9, [r2] @ r9 <- load INST from new PC 9999 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 10000 mov rPC, r2 @ publish new rPC 10001 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 10002 10003 @ Update "glue" values for the new method 10004 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 10005 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 10006 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 10007#if defined(WITH_JIT) 10008 GET_JIT_PROF_TABLE(r0) 10009 mov rFP, r1 @ fp = newFp 10010 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 10011 mov rINST, r9 @ publish new rINST 10012 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 10013 cmp r0,#0 10014 bne common_updateProfile 10015 GOTO_OPCODE(ip) @ jump to next instruction 10016#else 10017 mov rFP, r1 @ fp = newFp 10018 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 10019 mov rINST, r9 @ publish new rINST 10020 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 10021 GOTO_OPCODE(ip) @ jump to next instruction 10022#endif 10023 10024.LinvokeNative: 10025 @ Prep for the native call 10026 @ r0=methodToCall, r1=newFp, r10=newSaveArea 10027 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10028 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 10029 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 10030 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 10031 mov r9, r3 @ r9<- glue->self (preserve) 10032 10033 mov r2, r0 @ r2<- methodToCall 10034 mov r0, r1 @ r0<- newFp (points to args) 10035 add r1, rGLUE, #offGlue_retval @ r1<- &retval 10036 10037#ifdef ASSIST_DEBUGGER 10038 /* insert fake function header to help gdb find the stack frame */ 10039 b .Lskip 10040 .type dalvik_mterp, %function 10041dalvik_mterp: 10042 .fnstart 10043 MTERP_ENTRY1 10044 MTERP_ENTRY2 10045.Lskip: 10046#endif 10047 10048#if defined(WITH_INLINE_PROFILING) 10049 @ r2=JNIMethod, r6=rGLUE 10050 stmfd sp!, {r2,r6} 10051#endif 10052 10053 @mov lr, pc @ set return addr 10054 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 10055 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 10056 10057#if defined(WITH_INLINE_PROFILING) 10058 @ r0=JNIMethod, r1=rGLUE 10059 ldmfd sp!, {r0-r1} 10060 bl dvmFastNativeMethodTraceExit 10061#endif 10062 10063#if defined(WITH_JIT) 10064 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status 10065#endif 10066 10067 @ native return; r9=self, r10=newSaveArea 10068 @ equivalent to dvmPopJniLocals 10069 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 10070 ldr r1, [r9, #offThread_exception] @ check for exception 10071#if defined(WITH_JIT) 10072 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable 10073#endif 10074 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 10075 cmp r1, #0 @ null? 10076 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 10077#if defined(WITH_JIT) 10078 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch 10079#endif 10080 bne common_exceptionThrown @ no, handle exception 10081 10082 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 10083 GET_INST_OPCODE(ip) @ extract opcode from rINST 10084 GOTO_OPCODE(ip) @ jump to next instruction 10085 10086.LstackOverflow: @ r0=methodToCall 10087 mov r1, r0 @ r1<- methodToCall 10088 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 10089 bl dvmHandleStackOverflow 10090 b common_exceptionThrown 10091#ifdef ASSIST_DEBUGGER 10092 .fnend 10093#endif 10094 10095 10096 /* 10097 * Common code for method invocation, calling through "glue code". 10098 * 10099 * TODO: now that we have range and non-range invoke handlers, this 10100 * needs to be split into two. Maybe just create entry points 10101 * that set r9 and jump here? 10102 * 10103 * On entry: 10104 * r0 is "Method* methodToCall", the method we're trying to call 10105 * r9 is "bool methodCallRange", indicating if this is a /range variant 10106 */ 10107 .if 0 10108.LinvokeOld: 10109 sub sp, sp, #8 @ space for args + pad 10110 FETCH(ip, 2) @ ip<- FEDC or CCCC 10111 mov r2, r0 @ A2<- methodToCall 10112 mov r0, rGLUE @ A0<- glue 10113 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 10114 mov r1, r9 @ A1<- methodCallRange 10115 mov r3, rINST, lsr #8 @ A3<- AA 10116 str ip, [sp, #0] @ A4<- ip 10117 bl dvmMterp_invokeMethod @ call the C invokeMethod 10118 add sp, sp, #8 @ remove arg area 10119 b common_resumeAfterGlueCall @ continue to next instruction 10120 .endif 10121 10122 10123 10124/* 10125 * Common code for handling a return instruction. 10126 * 10127 * This does not return. 10128 */ 10129common_returnFromMethod: 10130.LreturnNew: 10131 mov r0, #kInterpEntryReturn 10132 mov r9, #0 10133 bl common_periodicChecks 10134 10135#if defined(WITH_INLINE_PROFILING) 10136 stmfd sp!, {r0-r3} @ preserve r0-r3 10137 mov r0, r6 10138 @ r0=rGlue 10139 bl dvmFastJavaMethodTraceExit 10140 ldmfd sp!, {r0-r3} @ restore r0-r3 10141#endif 10142 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 10143 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 10144 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 10145 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 10146 @ r2<- method we're returning to 10147 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10148 cmp r2, #0 @ is this a break frame? 10149 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 10150 mov r1, #0 @ "want switch" = false 10151 beq common_gotoBail @ break frame, bail out completely 10152 10153 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 10154 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 10155 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 10156 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 10157#if defined(WITH_JIT) 10158 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr 10159 mov rPC, r9 @ publish new rPC 10160 str r1, [rGLUE, #offGlue_methodClassDex] 10161 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land 10162 cmp r10, #0 @ caller is compiled code 10163 blxne r10 10164 GET_INST_OPCODE(ip) @ extract opcode from rINST 10165 GOTO_OPCODE(ip) @ jump to next instruction 10166#else 10167 GET_INST_OPCODE(ip) @ extract opcode from rINST 10168 mov rPC, r9 @ publish new rPC 10169 str r1, [rGLUE, #offGlue_methodClassDex] 10170 GOTO_OPCODE(ip) @ jump to next instruction 10171#endif 10172 10173 /* 10174 * Return handling, calls through "glue code". 10175 */ 10176 .if 0 10177.LreturnOld: 10178 SAVE_PC_FP_TO_GLUE() @ export state 10179 mov r0, rGLUE @ arg to function 10180 bl dvmMterp_returnFromMethod 10181 b common_resumeAfterGlueCall 10182 .endif 10183 10184 10185/* 10186 * Somebody has thrown an exception. Handle it. 10187 * 10188 * If the exception processing code returns to us (instead of falling 10189 * out of the interpreter), continue with whatever the next instruction 10190 * now happens to be. 10191 * 10192 * This does not return. 10193 */ 10194 .global dvmMterpCommonExceptionThrown 10195dvmMterpCommonExceptionThrown: 10196common_exceptionThrown: 10197.LexceptionNew: 10198 mov r0, #kInterpEntryThrow 10199 mov r9, #0 10200 bl common_periodicChecks 10201 10202 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 10203 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 10204 mov r1, r10 @ r1<- self 10205 mov r0, r9 @ r0<- exception 10206 bl dvmAddTrackedAlloc @ don't let the exception be GCed 10207 mov r3, #0 @ r3<- NULL 10208 str r3, [r10, #offThread_exception] @ self->exception = NULL 10209 10210 /* set up args and a local for "&fp" */ 10211 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 10212 str rFP, [sp, #-4]! @ *--sp = fp 10213 mov ip, sp @ ip<- &fp 10214 mov r3, #0 @ r3<- false 10215 str ip, [sp, #-4]! @ *--sp = &fp 10216 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 10217 mov r0, r10 @ r0<- self 10218 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 10219 mov r2, r9 @ r2<- exception 10220 sub r1, rPC, r1 @ r1<- pc - method->insns 10221 mov r1, r1, asr #1 @ r1<- offset in code units 10222 10223 /* call, r0 gets catchRelPc (a code-unit offset) */ 10224 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 10225 10226 /* fix earlier stack overflow if necessary; may trash rFP */ 10227 ldrb r1, [r10, #offThread_stackOverflowed] 10228 cmp r1, #0 @ did we overflow earlier? 10229 beq 1f @ no, skip ahead 10230 mov rFP, r0 @ save relPc result in rFP 10231 mov r0, r10 @ r0<- self 10232 mov r1, r9 @ r1<- exception 10233 bl dvmCleanupStackOverflow @ call(self) 10234 mov r0, rFP @ restore result 102351: 10236 10237 /* update frame pointer and check result from dvmFindCatchBlock */ 10238 ldr rFP, [sp, #4] @ retrieve the updated rFP 10239 cmp r0, #0 @ is catchRelPc < 0? 10240 add sp, sp, #8 @ restore stack 10241 bmi .LnotCaughtLocally 10242 10243 /* adjust locals to match self->curFrame and updated PC */ 10244 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 10245 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 10246 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 10247 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 10248 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 10249 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 10250 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 10251 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 10252 10253 /* release the tracked alloc on the exception */ 10254 mov r0, r9 @ r0<- exception 10255 mov r1, r10 @ r1<- self 10256 bl dvmReleaseTrackedAlloc @ release the exception 10257 10258 /* restore the exception if the handler wants it */ 10259 FETCH_INST() @ load rINST from rPC 10260 GET_INST_OPCODE(ip) @ extract opcode from rINST 10261 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 10262 streq r9, [r10, #offThread_exception] @ yes, restore the exception 10263 GOTO_OPCODE(ip) @ jump to next instruction 10264 10265.LnotCaughtLocally: @ r9=exception, r10=self 10266 /* fix stack overflow if necessary */ 10267 ldrb r1, [r10, #offThread_stackOverflowed] 10268 cmp r1, #0 @ did we overflow earlier? 10269 movne r0, r10 @ if yes: r0<- self 10270 movne r1, r9 @ if yes: r1<- exception 10271 blne dvmCleanupStackOverflow @ if yes: call(self) 10272 10273 @ may want to show "not caught locally" debug messages here 10274#if DVM_SHOW_EXCEPTION >= 2 10275 /* call __android_log_print(prio, tag, format, ...) */ 10276 /* "Exception %s from %s:%d not caught locally" */ 10277 @ dvmLineNumFromPC(method, pc - method->insns) 10278 ldr r0, [rGLUE, #offGlue_method] 10279 ldr r1, [r0, #offMethod_insns] 10280 sub r1, rPC, r1 10281 asr r1, r1, #1 10282 bl dvmLineNumFromPC 10283 str r0, [sp, #-4]! 10284 @ dvmGetMethodSourceFile(method) 10285 ldr r0, [rGLUE, #offGlue_method] 10286 bl dvmGetMethodSourceFile 10287 str r0, [sp, #-4]! 10288 @ exception->clazz->descriptor 10289 ldr r3, [r9, #offObject_clazz] 10290 ldr r3, [r3, #offClassObject_descriptor] 10291 @ 10292 ldr r2, strExceptionNotCaughtLocally 10293 ldr r1, strLogTag 10294 mov r0, #3 @ LOG_DEBUG 10295 bl __android_log_print 10296#endif 10297 str r9, [r10, #offThread_exception] @ restore exception 10298 mov r0, r9 @ r0<- exception 10299 mov r1, r10 @ r1<- self 10300 bl dvmReleaseTrackedAlloc @ release the exception 10301 mov r1, #0 @ "want switch" = false 10302 b common_gotoBail @ bail out 10303 10304 10305 /* 10306 * Exception handling, calls through "glue code". 10307 */ 10308 .if 0 10309.LexceptionOld: 10310 SAVE_PC_FP_TO_GLUE() @ export state 10311 mov r0, rGLUE @ arg to function 10312 bl dvmMterp_exceptionThrown 10313 b common_resumeAfterGlueCall 10314 .endif 10315 10316 10317/* 10318 * After returning from a "glued" function, pull out the updated 10319 * values and start executing at the next instruction. 10320 */ 10321common_resumeAfterGlueCall: 10322 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 10323 FETCH_INST() @ load rINST from rPC 10324 GET_INST_OPCODE(ip) @ extract opcode from rINST 10325 GOTO_OPCODE(ip) @ jump to next instruction 10326 10327/* 10328 * Invalid array index. 10329 */ 10330common_errArrayIndex: 10331 EXPORT_PC() 10332 ldr r0, strArrayIndexException 10333 mov r1, #0 10334 bl dvmThrowException 10335 b common_exceptionThrown 10336 10337/* 10338 * Invalid array value. 10339 */ 10340common_errArrayStore: 10341 EXPORT_PC() 10342 ldr r0, strArrayStoreException 10343 mov r1, #0 10344 bl dvmThrowException 10345 b common_exceptionThrown 10346 10347/* 10348 * Integer divide or mod by zero. 10349 */ 10350common_errDivideByZero: 10351 EXPORT_PC() 10352 ldr r0, strArithmeticException 10353 ldr r1, strDivideByZero 10354 bl dvmThrowException 10355 b common_exceptionThrown 10356 10357/* 10358 * Attempt to allocate an array with a negative size. 10359 */ 10360common_errNegativeArraySize: 10361 EXPORT_PC() 10362 ldr r0, strNegativeArraySizeException 10363 mov r1, #0 10364 bl dvmThrowException 10365 b common_exceptionThrown 10366 10367/* 10368 * Invocation of a non-existent method. 10369 */ 10370common_errNoSuchMethod: 10371 EXPORT_PC() 10372 ldr r0, strNoSuchMethodError 10373 mov r1, #0 10374 bl dvmThrowException 10375 b common_exceptionThrown 10376 10377/* 10378 * We encountered a null object when we weren't expecting one. We 10379 * export the PC, throw a NullPointerException, and goto the exception 10380 * processing code. 10381 */ 10382common_errNullObject: 10383 EXPORT_PC() 10384 ldr r0, strNullPointerException 10385 mov r1, #0 10386 bl dvmThrowException 10387 b common_exceptionThrown 10388 10389/* 10390 * For debugging, cause an immediate fault. The source address will 10391 * be in lr (use a bl instruction to jump here). 10392 */ 10393common_abort: 10394 ldr pc, .LdeadFood 10395.LdeadFood: 10396 .word 0xdeadf00d 10397 10398/* 10399 * Spit out a "we were here", preserving all registers. (The attempt 10400 * to save ip won't work, but we need to save an even number of 10401 * registers for EABI 64-bit stack alignment.) 10402 */ 10403 .macro SQUEAK num 10404common_squeak\num: 10405 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10406 ldr r0, strSqueak 10407 mov r1, #\num 10408 bl printf 10409 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10410 bx lr 10411 .endm 10412 10413 SQUEAK 0 10414 SQUEAK 1 10415 SQUEAK 2 10416 SQUEAK 3 10417 SQUEAK 4 10418 SQUEAK 5 10419 10420/* 10421 * Spit out the number in r0, preserving registers. 10422 */ 10423common_printNum: 10424 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10425 mov r1, r0 10426 ldr r0, strSqueak 10427 bl printf 10428 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10429 bx lr 10430 10431/* 10432 * Print a newline, preserving registers. 10433 */ 10434common_printNewline: 10435 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10436 ldr r0, strNewline 10437 bl printf 10438 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10439 bx lr 10440 10441 /* 10442 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 10443 */ 10444common_printHex: 10445 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10446 mov r1, r0 10447 ldr r0, strPrintHex 10448 bl printf 10449 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10450 bx lr 10451 10452/* 10453 * Print the 64-bit quantity in r0-r1, preserving registers. 10454 */ 10455common_printLong: 10456 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10457 mov r3, r1 10458 mov r2, r0 10459 ldr r0, strPrintLong 10460 bl printf 10461 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10462 bx lr 10463 10464/* 10465 * Print full method info. Pass the Method* in r0. Preserves regs. 10466 */ 10467common_printMethod: 10468 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10469 bl dvmMterpPrintMethod 10470 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10471 bx lr 10472 10473/* 10474 * Call a C helper function that dumps regs and possibly some 10475 * additional info. Requires the C function to be compiled in. 10476 */ 10477 .if 0 10478common_dumpRegs: 10479 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10480 bl dvmMterpDumpArmRegs 10481 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10482 bx lr 10483 .endif 10484 10485#if 0 10486/* 10487 * Experiment on VFP mode. 10488 * 10489 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 10490 * 10491 * Updates the bits specified by "mask", setting them to the values in "val". 10492 */ 10493setFPSCR: 10494 and r0, r0, r1 @ make sure no stray bits are set 10495 fmrx r2, fpscr @ get VFP reg 10496 mvn r1, r1 @ bit-invert mask 10497 and r2, r2, r1 @ clear masked bits 10498 orr r2, r2, r0 @ set specified bits 10499 fmxr fpscr, r2 @ set VFP reg 10500 mov r0, r2 @ return new value 10501 bx lr 10502 10503 .align 2 10504 .global dvmConfigureFP 10505 .type dvmConfigureFP, %function 10506dvmConfigureFP: 10507 stmfd sp!, {ip, lr} 10508 /* 0x03000000 sets DN/FZ */ 10509 /* 0x00009f00 clears the six exception enable flags */ 10510 bl common_squeak0 10511 mov r0, #0x03000000 @ r0<- 0x03000000 10512 add r1, r0, #0x9f00 @ r1<- 0x03009f00 10513 bl setFPSCR 10514 ldmfd sp!, {ip, pc} 10515#endif 10516 10517 10518/* 10519 * String references, must be close to the code that uses them. 10520 */ 10521 .align 2 10522strArithmeticException: 10523 .word .LstrArithmeticException 10524strArrayIndexException: 10525 .word .LstrArrayIndexException 10526strArrayStoreException: 10527 .word .LstrArrayStoreException 10528strDivideByZero: 10529 .word .LstrDivideByZero 10530strNegativeArraySizeException: 10531 .word .LstrNegativeArraySizeException 10532strNoSuchMethodError: 10533 .word .LstrNoSuchMethodError 10534strNullPointerException: 10535 .word .LstrNullPointerException 10536 10537strLogTag: 10538 .word .LstrLogTag 10539strExceptionNotCaughtLocally: 10540 .word .LstrExceptionNotCaughtLocally 10541 10542strNewline: 10543 .word .LstrNewline 10544strSqueak: 10545 .word .LstrSqueak 10546strPrintHex: 10547 .word .LstrPrintHex 10548strPrintLong: 10549 .word .LstrPrintLong 10550 10551/* 10552 * Zero-terminated ASCII string data. 10553 * 10554 * On ARM we have two choices: do like gcc does, and LDR from a .word 10555 * with the address, or use an ADR pseudo-op to get the address 10556 * directly. ADR saves 4 bytes and an indirection, but it's using a 10557 * PC-relative addressing mode and hence has a limited range, which 10558 * makes it not work well with mergeable string sections. 10559 */ 10560 .section .rodata.str1.4,"aMS",%progbits,1 10561 10562.LstrBadEntryPoint: 10563 .asciz "Bad entry point %d\n" 10564.LstrArithmeticException: 10565 .asciz "Ljava/lang/ArithmeticException;" 10566.LstrArrayIndexException: 10567 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 10568.LstrArrayStoreException: 10569 .asciz "Ljava/lang/ArrayStoreException;" 10570.LstrClassCastException: 10571 .asciz "Ljava/lang/ClassCastException;" 10572.LstrDivideByZero: 10573 .asciz "divide by zero" 10574.LstrFilledNewArrayNotImpl: 10575 .asciz "filled-new-array only implemented for objects and 'int'" 10576.LstrInternalError: 10577 .asciz "Ljava/lang/InternalError;" 10578.LstrInstantiationError: 10579 .asciz "Ljava/lang/InstantiationError;" 10580.LstrNegativeArraySizeException: 10581 .asciz "Ljava/lang/NegativeArraySizeException;" 10582.LstrNoSuchMethodError: 10583 .asciz "Ljava/lang/NoSuchMethodError;" 10584.LstrNullPointerException: 10585 .asciz "Ljava/lang/NullPointerException;" 10586 10587.LstrLogTag: 10588 .asciz "mterp" 10589.LstrExceptionNotCaughtLocally: 10590 .asciz "Exception %s from %s:%d not caught locally\n" 10591 10592.LstrNewline: 10593 .asciz "\n" 10594.LstrSqueak: 10595 .asciz "<%d>" 10596.LstrPrintHex: 10597 .asciz "<0x%x>" 10598.LstrPrintLong: 10599 .asciz "<%lld>" 10600 10601