InterpAsm-armv7-a.S revision 5cc61d70ec727aa22f58463bf7940cc717cf3eb1
1/* 2 * This file was generated automatically by gen-mterp.py for 'armv7-a'. 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; not meaningful pre-ARMv6K. 252 * If the argument is nonzero, emit barrier; otherwise, emit nothing. 253 */ 254.macro SMP_DMB 255#if ANDROID_SMP != 0 256 dmb 257#else 258 /* not SMP */ 259#endif 260.endm 261 262/* File: armv5te/entry.S */ 263/* 264 * Copyright (C) 2008 The Android Open Source Project 265 * 266 * Licensed under the Apache License, Version 2.0 (the "License"); 267 * you may not use this file except in compliance with the License. 268 * You may obtain a copy of the License at 269 * 270 * http://www.apache.org/licenses/LICENSE-2.0 271 * 272 * Unless required by applicable law or agreed to in writing, software 273 * distributed under the License is distributed on an "AS IS" BASIS, 274 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 275 * See the License for the specific language governing permissions and 276 * limitations under the License. 277 */ 278/* 279 * Interpreter entry point. 280 */ 281 282/* 283 * We don't have formal stack frames, so gdb scans upward in the code 284 * to find the start of the function (a label with the %function type), 285 * and then looks at the next few instructions to figure out what 286 * got pushed onto the stack. From this it figures out how to restore 287 * the registers, including PC, for the previous stack frame. If gdb 288 * sees a non-function label, it stops scanning, so either we need to 289 * have nothing but assembler-local labels between the entry point and 290 * the break, or we need to fake it out. 291 * 292 * When this is defined, we add some stuff to make gdb less confused. 293 */ 294#define ASSIST_DEBUGGER 1 295 296 .text 297 .align 2 298 .global dvmMterpStdRun 299 .type dvmMterpStdRun, %function 300 301/* 302 * On entry: 303 * r0 MterpGlue* glue 304 * 305 * This function returns a boolean "changeInterp" value. The return comes 306 * via a call to dvmMterpStdBail(). 307 */ 308dvmMterpStdRun: 309#define MTERP_ENTRY1 \ 310 .save {r4-r10,fp,lr}; \ 311 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs 312#define MTERP_ENTRY2 \ 313 .pad #4; \ 314 sub sp, sp, #4 @ align 64 315 316 .fnstart 317 MTERP_ENTRY1 318 MTERP_ENTRY2 319 320 /* save stack pointer, add magic word for debuggerd */ 321 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return 322 323 /* set up "named" registers, figure out entry point */ 324 mov rGLUE, r0 @ set rGLUE 325 ldr r1, [r0, #offGlue_entryPoint] @ enum is 4 bytes in aapcs-EABI 326 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue" 327 adr rIBASE, dvmAsmInstructionStart @ set rIBASE 328 cmp r1, #kInterpEntryInstr @ usual case? 329 bne .Lnot_instr @ no, handle it 330 331#if defined(WITH_JIT) 332.LentryInstr: 333 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 334 /* Entry is always a possible trace start */ 335 GET_JIT_PROF_TABLE(r0) 336 FETCH_INST() 337 mov r1, #0 @ prepare the value for the new state 338 str r1, [r10, #offThread_inJitCodeCache] @ back to the interp land 339 cmp r0,#0 @ is profiling disabled? 340#if !defined(WITH_SELF_VERIFICATION) 341 bne common_updateProfile @ profiling is enabled 342#else 343 ldr r2, [r10, #offThread_shadowSpace] @ to find out the jit exit state 344 beq 1f @ profiling is disabled 345 ldr r3, [r2, #offShadowSpace_jitExitState] @ jit exit state 346 cmp r3, #kSVSTraceSelect @ hot trace following? 347 moveq r2,#kJitTSelectRequestHot @ ask for trace selection 348 beq common_selectTrace @ go build the trace 349 cmp r3, #kSVSNoProfile @ don't profile the next instruction? 350 beq 1f @ intrepret the next instruction 351 b common_updateProfile @ collect profiles 352#endif 3531: 354 GET_INST_OPCODE(ip) 355 GOTO_OPCODE(ip) 356#else 357 /* start executing the instruction at rPC */ 358 FETCH_INST() @ load rINST from rPC 359 GET_INST_OPCODE(ip) @ extract opcode from rINST 360 GOTO_OPCODE(ip) @ jump to next instruction 361#endif 362 363.Lnot_instr: 364 cmp r1, #kInterpEntryReturn @ were we returning from a method? 365 beq common_returnFromMethod 366 367.Lnot_return: 368 cmp r1, #kInterpEntryThrow @ were we throwing an exception? 369 beq common_exceptionThrown 370 371#if defined(WITH_JIT) 372.Lnot_throw: 373 ldr r10,[rGLUE, #offGlue_jitResumeNPC] 374 ldr r2,[rGLUE, #offGlue_jitResumeDPC] 375 cmp r1, #kInterpEntryResume @ resuming after Jit single-step? 376 bne .Lbad_arg 377 cmp rPC,r2 378 bne .LentryInstr @ must have branched, don't resume 379#if defined(WITH_SELF_VERIFICATION) 380 @ glue->entryPoint will be set in dvmSelfVerificationSaveState 381 b jitSVShadowRunStart @ re-enter the translation after the 382 @ single-stepped instruction 383 @noreturn 384#endif 385 mov r1, #kInterpEntryInstr 386 str r1, [rGLUE, #offGlue_entryPoint] 387 bx r10 @ re-enter the translation 388#endif 389 390.Lbad_arg: 391 ldr r0, strBadEntryPoint 392 @ r1 holds value of entryPoint 393 bl printf 394 bl dvmAbort 395 .fnend 396 397 398 .global dvmMterpStdBail 399 .type dvmMterpStdBail, %function 400 401/* 402 * Restore the stack pointer and PC from the save point established on entry. 403 * This is essentially the same as a longjmp, but should be cheaper. The 404 * last instruction causes us to return to whoever called dvmMterpStdRun. 405 * 406 * We pushed some registers on the stack in dvmMterpStdRun, then saved 407 * SP and LR. Here we restore SP, restore the registers, and then restore 408 * LR to PC. 409 * 410 * On entry: 411 * r0 MterpGlue* glue 412 * r1 bool changeInterp 413 */ 414dvmMterpStdBail: 415 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 416 mov r0, r1 @ return the changeInterp value 417 add sp, sp, #4 @ un-align 64 418 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return 419 420 421/* 422 * String references. 423 */ 424strBadEntryPoint: 425 .word .LstrBadEntryPoint 426 427 428 .global dvmAsmInstructionStart 429 .type dvmAsmInstructionStart, %function 430dvmAsmInstructionStart = .L_OP_NOP 431 .text 432 433/* ------------------------------ */ 434 .balign 64 435.L_OP_NOP: /* 0x00 */ 436/* File: armv5te/OP_NOP.S */ 437 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST 438 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 439 GOTO_OPCODE(ip) @ execute it 440 441#ifdef ASSIST_DEBUGGER 442 /* insert fake function header to help gdb find the stack frame */ 443 .type dalvik_inst, %function 444dalvik_inst: 445 .fnstart 446 MTERP_ENTRY1 447 MTERP_ENTRY2 448 .fnend 449#endif 450 451/* ------------------------------ */ 452 .balign 64 453.L_OP_MOVE: /* 0x01 */ 454/* File: armv6t2/OP_MOVE.S */ 455 /* for move, move-object, long-to-int */ 456 /* op vA, vB */ 457 mov r1, rINST, lsr #12 @ r1<- B from 15:12 458 ubfx r0, rINST, #8, #4 @ r0<- A from 11:8 459 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 460 GET_VREG(r2, r1) @ r2<- fp[B] 461 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 462 SET_VREG(r2, r0) @ fp[A]<- r2 463 GOTO_OPCODE(ip) @ execute next instruction 464 465/* ------------------------------ */ 466 .balign 64 467.L_OP_MOVE_FROM16: /* 0x02 */ 468/* File: armv5te/OP_MOVE_FROM16.S */ 469 /* for: move/from16, move-object/from16 */ 470 /* op vAA, vBBBB */ 471 FETCH(r1, 1) @ r1<- BBBB 472 mov r0, rINST, lsr #8 @ r0<- AA 473 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 474 GET_VREG(r2, r1) @ r2<- fp[BBBB] 475 GET_INST_OPCODE(ip) @ extract opcode from rINST 476 SET_VREG(r2, r0) @ fp[AA]<- r2 477 GOTO_OPCODE(ip) @ jump to next instruction 478 479/* ------------------------------ */ 480 .balign 64 481.L_OP_MOVE_16: /* 0x03 */ 482/* File: armv5te/OP_MOVE_16.S */ 483 /* for: move/16, move-object/16 */ 484 /* op vAAAA, vBBBB */ 485 FETCH(r1, 2) @ r1<- BBBB 486 FETCH(r0, 1) @ r0<- AAAA 487 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 488 GET_VREG(r2, r1) @ r2<- fp[BBBB] 489 GET_INST_OPCODE(ip) @ extract opcode from rINST 490 SET_VREG(r2, r0) @ fp[AAAA]<- r2 491 GOTO_OPCODE(ip) @ jump to next instruction 492 493/* ------------------------------ */ 494 .balign 64 495.L_OP_MOVE_WIDE: /* 0x04 */ 496/* File: armv6t2/OP_MOVE_WIDE.S */ 497 /* move-wide vA, vB */ 498 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 499 mov r3, rINST, lsr #12 @ r3<- B 500 ubfx r2, rINST, #8, #4 @ r2<- A 501 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 502 add r2, rFP, r2, lsl #2 @ r2<- &fp[A] 503 ldmia r3, {r0-r1} @ r0/r1<- fp[B] 504 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 505 GET_INST_OPCODE(ip) @ extract opcode from rINST 506 stmia r2, {r0-r1} @ fp[A]<- r0/r1 507 GOTO_OPCODE(ip) @ jump to next instruction 508 509/* ------------------------------ */ 510 .balign 64 511.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 512/* File: armv5te/OP_MOVE_WIDE_FROM16.S */ 513 /* move-wide/from16 vAA, vBBBB */ 514 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 515 FETCH(r3, 1) @ r3<- BBBB 516 mov r2, rINST, lsr #8 @ r2<- AA 517 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 518 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 519 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 520 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 521 GET_INST_OPCODE(ip) @ extract opcode from rINST 522 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 523 GOTO_OPCODE(ip) @ jump to next instruction 524 525/* ------------------------------ */ 526 .balign 64 527.L_OP_MOVE_WIDE_16: /* 0x06 */ 528/* File: armv5te/OP_MOVE_WIDE_16.S */ 529 /* move-wide/16 vAAAA, vBBBB */ 530 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 531 FETCH(r3, 2) @ r3<- BBBB 532 FETCH(r2, 1) @ r2<- AAAA 533 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 534 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA] 535 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 536 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 537 GET_INST_OPCODE(ip) @ extract opcode from rINST 538 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1 539 GOTO_OPCODE(ip) @ jump to next instruction 540 541/* ------------------------------ */ 542 .balign 64 543.L_OP_MOVE_OBJECT: /* 0x07 */ 544/* File: armv5te/OP_MOVE_OBJECT.S */ 545/* File: armv5te/OP_MOVE.S */ 546 /* for move, move-object, long-to-int */ 547 /* op vA, vB */ 548 mov r1, rINST, lsr #12 @ r1<- B from 15:12 549 mov r0, rINST, lsr #8 @ r0<- A from 11:8 550 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 551 GET_VREG(r2, r1) @ r2<- fp[B] 552 and r0, r0, #15 553 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 554 SET_VREG(r2, r0) @ fp[A]<- r2 555 GOTO_OPCODE(ip) @ execute next instruction 556 557 558/* ------------------------------ */ 559 .balign 64 560.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 561/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */ 562/* File: armv5te/OP_MOVE_FROM16.S */ 563 /* for: move/from16, move-object/from16 */ 564 /* op vAA, vBBBB */ 565 FETCH(r1, 1) @ r1<- BBBB 566 mov r0, rINST, lsr #8 @ r0<- AA 567 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 568 GET_VREG(r2, r1) @ r2<- fp[BBBB] 569 GET_INST_OPCODE(ip) @ extract opcode from rINST 570 SET_VREG(r2, r0) @ fp[AA]<- r2 571 GOTO_OPCODE(ip) @ jump to next instruction 572 573 574/* ------------------------------ */ 575 .balign 64 576.L_OP_MOVE_OBJECT_16: /* 0x09 */ 577/* File: armv5te/OP_MOVE_OBJECT_16.S */ 578/* File: armv5te/OP_MOVE_16.S */ 579 /* for: move/16, move-object/16 */ 580 /* op vAAAA, vBBBB */ 581 FETCH(r1, 2) @ r1<- BBBB 582 FETCH(r0, 1) @ r0<- AAAA 583 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 584 GET_VREG(r2, r1) @ r2<- fp[BBBB] 585 GET_INST_OPCODE(ip) @ extract opcode from rINST 586 SET_VREG(r2, r0) @ fp[AAAA]<- r2 587 GOTO_OPCODE(ip) @ jump to next instruction 588 589 590/* ------------------------------ */ 591 .balign 64 592.L_OP_MOVE_RESULT: /* 0x0a */ 593/* File: armv5te/OP_MOVE_RESULT.S */ 594 /* for: move-result, move-result-object */ 595 /* op vAA */ 596 mov r2, rINST, lsr #8 @ r2<- AA 597 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 598 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 599 GET_INST_OPCODE(ip) @ extract opcode from rINST 600 SET_VREG(r0, r2) @ fp[AA]<- r0 601 GOTO_OPCODE(ip) @ jump to next instruction 602 603/* ------------------------------ */ 604 .balign 64 605.L_OP_MOVE_RESULT_WIDE: /* 0x0b */ 606/* File: armv5te/OP_MOVE_RESULT_WIDE.S */ 607 /* move-result-wide vAA */ 608 mov r2, rINST, lsr #8 @ r2<- AA 609 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 610 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 611 ldmia r3, {r0-r1} @ r0/r1<- retval.j 612 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 613 GET_INST_OPCODE(ip) @ extract opcode from rINST 614 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 615 GOTO_OPCODE(ip) @ jump to next instruction 616 617/* ------------------------------ */ 618 .balign 64 619.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 620/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */ 621/* File: armv5te/OP_MOVE_RESULT.S */ 622 /* for: move-result, move-result-object */ 623 /* op vAA */ 624 mov r2, rINST, lsr #8 @ r2<- AA 625 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 626 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 627 GET_INST_OPCODE(ip) @ extract opcode from rINST 628 SET_VREG(r0, r2) @ fp[AA]<- r0 629 GOTO_OPCODE(ip) @ jump to next instruction 630 631 632/* ------------------------------ */ 633 .balign 64 634.L_OP_MOVE_EXCEPTION: /* 0x0d */ 635/* File: armv5te/OP_MOVE_EXCEPTION.S */ 636 /* move-exception vAA */ 637 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 638 mov r2, rINST, lsr #8 @ r2<- AA 639 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass 640 mov r1, #0 @ r1<- 0 641 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 642 SET_VREG(r3, r2) @ fp[AA]<- exception obj 643 GET_INST_OPCODE(ip) @ extract opcode from rINST 644 str r1, [r0, #offThread_exception] @ dvmClearException bypass 645 GOTO_OPCODE(ip) @ jump to next instruction 646 647/* ------------------------------ */ 648 .balign 64 649.L_OP_RETURN_VOID: /* 0x0e */ 650/* File: armv5te/OP_RETURN_VOID.S */ 651 b common_returnFromMethod 652 653/* ------------------------------ */ 654 .balign 64 655.L_OP_RETURN: /* 0x0f */ 656/* File: armv5te/OP_RETURN.S */ 657 /* 658 * Return a 32-bit value. Copies the return value into the "glue" 659 * structure, then jumps to the return handler. 660 * 661 * for: return, return-object 662 */ 663 /* op vAA */ 664 mov r2, rINST, lsr #8 @ r2<- AA 665 GET_VREG(r0, r2) @ r0<- vAA 666 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 667 b common_returnFromMethod 668 669/* ------------------------------ */ 670 .balign 64 671.L_OP_RETURN_WIDE: /* 0x10 */ 672/* File: armv5te/OP_RETURN_WIDE.S */ 673 /* 674 * Return a 64-bit value. Copies the return value into the "glue" 675 * structure, then jumps to the return handler. 676 */ 677 /* return-wide vAA */ 678 mov r2, rINST, lsr #8 @ r2<- AA 679 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 680 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 681 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1 682 stmia r3, {r0-r1} @ retval<- r0/r1 683 b common_returnFromMethod 684 685/* ------------------------------ */ 686 .balign 64 687.L_OP_RETURN_OBJECT: /* 0x11 */ 688/* File: armv5te/OP_RETURN_OBJECT.S */ 689/* File: armv5te/OP_RETURN.S */ 690 /* 691 * Return a 32-bit value. Copies the return value into the "glue" 692 * structure, then jumps to the return handler. 693 * 694 * for: return, return-object 695 */ 696 /* op vAA */ 697 mov r2, rINST, lsr #8 @ r2<- AA 698 GET_VREG(r0, r2) @ r0<- vAA 699 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 700 b common_returnFromMethod 701 702 703/* ------------------------------ */ 704 .balign 64 705.L_OP_CONST_4: /* 0x12 */ 706/* File: armv6t2/OP_CONST_4.S */ 707 /* const/4 vA, #+B */ 708 mov r1, rINST, lsl #16 @ r1<- Bxxx0000 709 ubfx r0, rINST, #8, #4 @ r0<- A 710 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 711 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended) 712 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 713 SET_VREG(r1, r0) @ fp[A]<- r1 714 GOTO_OPCODE(ip) @ execute next instruction 715 716/* ------------------------------ */ 717 .balign 64 718.L_OP_CONST_16: /* 0x13 */ 719/* File: armv5te/OP_CONST_16.S */ 720 /* const/16 vAA, #+BBBB */ 721 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 722 mov r3, rINST, lsr #8 @ r3<- AA 723 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 724 SET_VREG(r0, r3) @ vAA<- r0 725 GET_INST_OPCODE(ip) @ extract opcode from rINST 726 GOTO_OPCODE(ip) @ jump to next instruction 727 728/* ------------------------------ */ 729 .balign 64 730.L_OP_CONST: /* 0x14 */ 731/* File: armv5te/OP_CONST.S */ 732 /* const vAA, #+BBBBbbbb */ 733 mov r3, rINST, lsr #8 @ r3<- AA 734 FETCH(r0, 1) @ r0<- bbbb (low) 735 FETCH(r1, 2) @ r1<- BBBB (high) 736 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 737 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 738 GET_INST_OPCODE(ip) @ extract opcode from rINST 739 SET_VREG(r0, r3) @ vAA<- r0 740 GOTO_OPCODE(ip) @ jump to next instruction 741 742/* ------------------------------ */ 743 .balign 64 744.L_OP_CONST_HIGH16: /* 0x15 */ 745/* File: armv5te/OP_CONST_HIGH16.S */ 746 /* const/high16 vAA, #+BBBB0000 */ 747 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended) 748 mov r3, rINST, lsr #8 @ r3<- AA 749 mov r0, r0, lsl #16 @ r0<- BBBB0000 750 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 751 SET_VREG(r0, r3) @ vAA<- r0 752 GET_INST_OPCODE(ip) @ extract opcode from rINST 753 GOTO_OPCODE(ip) @ jump to next instruction 754 755/* ------------------------------ */ 756 .balign 64 757.L_OP_CONST_WIDE_16: /* 0x16 */ 758/* File: armv5te/OP_CONST_WIDE_16.S */ 759 /* const-wide/16 vAA, #+BBBB */ 760 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 761 mov r3, rINST, lsr #8 @ r3<- AA 762 mov r1, r0, asr #31 @ r1<- ssssssss 763 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 764 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 765 GET_INST_OPCODE(ip) @ extract opcode from rINST 766 stmia r3, {r0-r1} @ vAA<- r0/r1 767 GOTO_OPCODE(ip) @ jump to next instruction 768 769/* ------------------------------ */ 770 .balign 64 771.L_OP_CONST_WIDE_32: /* 0x17 */ 772/* File: armv5te/OP_CONST_WIDE_32.S */ 773 /* const-wide/32 vAA, #+BBBBbbbb */ 774 FETCH(r0, 1) @ r0<- 0000bbbb (low) 775 mov r3, rINST, lsr #8 @ r3<- AA 776 FETCH_S(r2, 2) @ r2<- ssssBBBB (high) 777 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 778 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb 779 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 780 mov r1, r0, asr #31 @ r1<- ssssssss 781 GET_INST_OPCODE(ip) @ extract opcode from rINST 782 stmia r3, {r0-r1} @ vAA<- r0/r1 783 GOTO_OPCODE(ip) @ jump to next instruction 784 785/* ------------------------------ */ 786 .balign 64 787.L_OP_CONST_WIDE: /* 0x18 */ 788/* File: armv5te/OP_CONST_WIDE.S */ 789 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 790 FETCH(r0, 1) @ r0<- bbbb (low) 791 FETCH(r1, 2) @ r1<- BBBB (low middle) 792 FETCH(r2, 3) @ r2<- hhhh (high middle) 793 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word) 794 FETCH(r3, 4) @ r3<- HHHH (high) 795 mov r9, rINST, lsr #8 @ r9<- AA 796 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word) 797 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 798 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 799 GET_INST_OPCODE(ip) @ extract opcode from rINST 800 stmia r9, {r0-r1} @ vAA<- r0/r1 801 GOTO_OPCODE(ip) @ jump to next instruction 802 803/* ------------------------------ */ 804 .balign 64 805.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 806/* File: armv5te/OP_CONST_WIDE_HIGH16.S */ 807 /* const-wide/high16 vAA, #+BBBB000000000000 */ 808 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended) 809 mov r3, rINST, lsr #8 @ r3<- AA 810 mov r0, #0 @ r0<- 00000000 811 mov r1, r1, lsl #16 @ r1<- BBBB0000 812 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 813 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 814 GET_INST_OPCODE(ip) @ extract opcode from rINST 815 stmia r3, {r0-r1} @ vAA<- r0/r1 816 GOTO_OPCODE(ip) @ jump to next instruction 817 818/* ------------------------------ */ 819 .balign 64 820.L_OP_CONST_STRING: /* 0x1a */ 821/* File: armv5te/OP_CONST_STRING.S */ 822 /* const/string vAA, String@BBBB */ 823 FETCH(r1, 1) @ r1<- BBBB 824 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 825 mov r9, rINST, lsr #8 @ r9<- AA 826 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 827 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 828 cmp r0, #0 @ not yet resolved? 829 beq .LOP_CONST_STRING_resolve 830 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 831 GET_INST_OPCODE(ip) @ extract opcode from rINST 832 SET_VREG(r0, r9) @ vAA<- r0 833 GOTO_OPCODE(ip) @ jump to next instruction 834 835/* ------------------------------ */ 836 .balign 64 837.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 838/* File: armv5te/OP_CONST_STRING_JUMBO.S */ 839 /* const/string vAA, String@BBBBBBBB */ 840 FETCH(r0, 1) @ r0<- bbbb (low) 841 FETCH(r1, 2) @ r1<- BBBB (high) 842 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 843 mov r9, rINST, lsr #8 @ r9<- AA 844 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 845 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 846 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 847 cmp r0, #0 848 beq .LOP_CONST_STRING_JUMBO_resolve 849 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 850 GET_INST_OPCODE(ip) @ extract opcode from rINST 851 SET_VREG(r0, r9) @ vAA<- r0 852 GOTO_OPCODE(ip) @ jump to next instruction 853 854/* ------------------------------ */ 855 .balign 64 856.L_OP_CONST_CLASS: /* 0x1c */ 857/* File: armv5te/OP_CONST_CLASS.S */ 858 /* const/class vAA, Class@BBBB */ 859 FETCH(r1, 1) @ r1<- BBBB 860 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 861 mov r9, rINST, lsr #8 @ r9<- AA 862 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 863 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB] 864 cmp r0, #0 @ not yet resolved? 865 beq .LOP_CONST_CLASS_resolve 866 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 867 GET_INST_OPCODE(ip) @ extract opcode from rINST 868 SET_VREG(r0, r9) @ vAA<- r0 869 GOTO_OPCODE(ip) @ jump to next instruction 870 871/* ------------------------------ */ 872 .balign 64 873.L_OP_MONITOR_ENTER: /* 0x1d */ 874/* File: armv5te/OP_MONITOR_ENTER.S */ 875 /* 876 * Synchronize on an object. 877 */ 878 /* monitor-enter vAA */ 879 mov r2, rINST, lsr #8 @ r2<- AA 880 GET_VREG(r1, r2) @ r1<- vAA (object) 881 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 882 cmp r1, #0 @ null object? 883 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING 884 beq common_errNullObject @ null object, throw an exception 885 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 886 bl dvmLockObject @ call(self, obj) 887#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ 888 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 889 ldr r1, [r0, #offThread_exception] @ check for exception 890 cmp r1, #0 891 bne common_exceptionThrown @ exception raised, bail out 892#endif 893 GET_INST_OPCODE(ip) @ extract opcode from rINST 894 GOTO_OPCODE(ip) @ jump to next instruction 895 896/* ------------------------------ */ 897 .balign 64 898.L_OP_MONITOR_EXIT: /* 0x1e */ 899/* File: armv5te/OP_MONITOR_EXIT.S */ 900 /* 901 * Unlock an object. 902 * 903 * Exceptions that occur when unlocking a monitor need to appear as 904 * if they happened at the following instruction. See the Dalvik 905 * instruction spec. 906 */ 907 /* monitor-exit vAA */ 908 mov r2, rINST, lsr #8 @ r2<- AA 909 EXPORT_PC() @ before fetch: export the PC 910 GET_VREG(r1, r2) @ r1<- vAA (object) 911 cmp r1, #0 @ null object? 912 beq 1f @ yes 913 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 914 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 915 cmp r0, #0 @ failed? 916 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 917 beq common_exceptionThrown @ yes, exception is pending 918 GET_INST_OPCODE(ip) @ extract opcode from rINST 919 GOTO_OPCODE(ip) @ jump to next instruction 9201: 921 FETCH_ADVANCE_INST(1) @ advance before throw 922 b common_errNullObject 923 924/* ------------------------------ */ 925 .balign 64 926.L_OP_CHECK_CAST: /* 0x1f */ 927/* File: armv5te/OP_CHECK_CAST.S */ 928 /* 929 * Check to see if a cast from one class to another is allowed. 930 */ 931 /* check-cast vAA, class@BBBB */ 932 mov r3, rINST, lsr #8 @ r3<- AA 933 FETCH(r2, 1) @ r2<- BBBB 934 GET_VREG(r9, r3) @ r9<- object 935 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 936 cmp r9, #0 @ is object null? 937 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 938 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 939 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 940 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 941 cmp r1, #0 @ have we resolved this before? 942 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 943.LOP_CHECK_CAST_resolved: 944 cmp r0, r1 @ same class (trivial success)? 945 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 946.LOP_CHECK_CAST_okay: 947 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 948 GET_INST_OPCODE(ip) @ extract opcode from rINST 949 GOTO_OPCODE(ip) @ jump to next instruction 950 951/* ------------------------------ */ 952 .balign 64 953.L_OP_INSTANCE_OF: /* 0x20 */ 954/* File: armv5te/OP_INSTANCE_OF.S */ 955 /* 956 * Check to see if an object reference is an instance of a class. 957 * 958 * Most common situation is a non-null object, being compared against 959 * an already-resolved class. 960 */ 961 /* instance-of vA, vB, class@CCCC */ 962 mov r3, rINST, lsr #12 @ r3<- B 963 mov r9, rINST, lsr #8 @ r9<- A+ 964 GET_VREG(r0, r3) @ r0<- vB (object) 965 and r9, r9, #15 @ r9<- A 966 cmp r0, #0 @ is object null? 967 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 968 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 969 FETCH(r3, 1) @ r3<- CCCC 970 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 971 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 972 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 973 cmp r1, #0 @ have we resolved this before? 974 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 975.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 976 cmp r0, r1 @ same class (trivial success)? 977 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 978 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 979 980/* ------------------------------ */ 981 .balign 64 982.L_OP_ARRAY_LENGTH: /* 0x21 */ 983/* File: armv6t2/OP_ARRAY_LENGTH.S */ 984 /* 985 * Return the length of an array. 986 */ 987 mov r1, rINST, lsr #12 @ r1<- B 988 ubfx r2, rINST, #8, #4 @ r2<- A 989 GET_VREG(r0, r1) @ r0<- vB (object ref) 990 cmp r0, #0 @ is object null? 991 beq common_errNullObject @ yup, fail 992 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 993 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 994 GET_INST_OPCODE(ip) @ extract opcode from rINST 995 SET_VREG(r3, r2) @ vB<- length 996 GOTO_OPCODE(ip) @ jump to next instruction 997 998/* ------------------------------ */ 999 .balign 64 1000.L_OP_NEW_INSTANCE: /* 0x22 */ 1001/* File: armv5te/OP_NEW_INSTANCE.S */ 1002 /* 1003 * Create a new instance of a class. 1004 */ 1005 /* new-instance vAA, class@BBBB */ 1006 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1007 FETCH(r1, 1) @ r1<- BBBB 1008 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1009 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1010 EXPORT_PC() @ req'd for init, resolve, alloc 1011 cmp r0, #0 @ already resolved? 1012 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 1013.LOP_NEW_INSTANCE_resolved: @ r0=class 1014 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 1015 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 1016 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 1017.LOP_NEW_INSTANCE_initialized: @ r0=class 1018 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 1019 bl dvmAllocObject @ r0<- new object 1020 b .LOP_NEW_INSTANCE_finish @ continue 1021 1022/* ------------------------------ */ 1023 .balign 64 1024.L_OP_NEW_ARRAY: /* 0x23 */ 1025/* File: armv5te/OP_NEW_ARRAY.S */ 1026 /* 1027 * Allocate an array of objects, specified with the array class 1028 * and a count. 1029 * 1030 * The verifier guarantees that this is an array class, so we don't 1031 * check for it here. 1032 */ 1033 /* new-array vA, vB, class@CCCC */ 1034 mov r0, rINST, lsr #12 @ r0<- B 1035 FETCH(r2, 1) @ r2<- CCCC 1036 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1037 GET_VREG(r1, r0) @ r1<- vB (array length) 1038 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1039 cmp r1, #0 @ check length 1040 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 1041 bmi common_errNegativeArraySize @ negative length, bail 1042 cmp r0, #0 @ already resolved? 1043 EXPORT_PC() @ req'd for resolve, alloc 1044 bne .LOP_NEW_ARRAY_finish @ resolved, continue 1045 b .LOP_NEW_ARRAY_resolve @ do resolve now 1046 1047/* ------------------------------ */ 1048 .balign 64 1049.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1050/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1051 /* 1052 * Create a new array with elements filled from registers. 1053 * 1054 * for: filled-new-array, filled-new-array/range 1055 */ 1056 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1057 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1058 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1059 FETCH(r1, 1) @ r1<- BBBB 1060 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1061 EXPORT_PC() @ need for resolve and alloc 1062 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1063 mov r10, rINST, lsr #8 @ r10<- AA or BA 1064 cmp r0, #0 @ already resolved? 1065 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10668: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1067 mov r2, #0 @ r2<- false 1068 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1069 bl dvmResolveClass @ r0<- call(clazz, ref) 1070 cmp r0, #0 @ got null? 1071 beq common_exceptionThrown @ yes, handle exception 1072 b .LOP_FILLED_NEW_ARRAY_continue 1073 1074/* ------------------------------ */ 1075 .balign 64 1076.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1077/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1078/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1079 /* 1080 * Create a new array with elements filled from registers. 1081 * 1082 * for: filled-new-array, filled-new-array/range 1083 */ 1084 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1085 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1086 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1087 FETCH(r1, 1) @ r1<- BBBB 1088 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1089 EXPORT_PC() @ need for resolve and alloc 1090 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1091 mov r10, rINST, lsr #8 @ r10<- AA or BA 1092 cmp r0, #0 @ already resolved? 1093 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10948: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1095 mov r2, #0 @ r2<- false 1096 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1097 bl dvmResolveClass @ r0<- call(clazz, ref) 1098 cmp r0, #0 @ got null? 1099 beq common_exceptionThrown @ yes, handle exception 1100 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1101 1102 1103/* ------------------------------ */ 1104 .balign 64 1105.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1106/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1107 /* fill-array-data vAA, +BBBBBBBB */ 1108 FETCH(r0, 1) @ r0<- bbbb (lo) 1109 FETCH(r1, 2) @ r1<- BBBB (hi) 1110 mov r3, rINST, lsr #8 @ r3<- AA 1111 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1112 GET_VREG(r0, r3) @ r0<- vAA (array object) 1113 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1114 EXPORT_PC(); 1115 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1116 cmp r0, #0 @ 0 means an exception is thrown 1117 beq common_exceptionThrown @ has exception 1118 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1119 GET_INST_OPCODE(ip) @ extract opcode from rINST 1120 GOTO_OPCODE(ip) @ jump to next instruction 1121 1122/* ------------------------------ */ 1123 .balign 64 1124.L_OP_THROW: /* 0x27 */ 1125/* File: armv5te/OP_THROW.S */ 1126 /* 1127 * Throw an exception object in the current thread. 1128 */ 1129 /* throw vAA */ 1130 mov r2, rINST, lsr #8 @ r2<- AA 1131 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1132 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1133 EXPORT_PC() @ exception handler can throw 1134 cmp r1, #0 @ null object? 1135 beq common_errNullObject @ yes, throw an NPE instead 1136 @ bypass dvmSetException, just store it 1137 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1138 b common_exceptionThrown 1139 1140/* ------------------------------ */ 1141 .balign 64 1142.L_OP_GOTO: /* 0x28 */ 1143/* File: armv5te/OP_GOTO.S */ 1144 /* 1145 * Unconditional branch, 8-bit offset. 1146 * 1147 * The branch distance is a signed code-unit offset, which we need to 1148 * double to get a byte offset. 1149 */ 1150 /* goto +AA */ 1151 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1152 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1153 mov r9, r9, lsl #1 @ r9<- byte offset 1154 bmi common_backwardBranch @ backward branch, do periodic checks 1155#if defined(WITH_JIT) 1156 GET_JIT_PROF_TABLE(r0) 1157 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1158 cmp r0,#0 1159 bne common_updateProfile 1160 GET_INST_OPCODE(ip) @ extract opcode from rINST 1161 GOTO_OPCODE(ip) @ jump to next instruction 1162#else 1163 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1164 GET_INST_OPCODE(ip) @ extract opcode from rINST 1165 GOTO_OPCODE(ip) @ jump to next instruction 1166#endif 1167 1168/* ------------------------------ */ 1169 .balign 64 1170.L_OP_GOTO_16: /* 0x29 */ 1171/* File: armv5te/OP_GOTO_16.S */ 1172 /* 1173 * Unconditional branch, 16-bit offset. 1174 * 1175 * The branch distance is a signed code-unit offset, which we need to 1176 * double to get a byte offset. 1177 */ 1178 /* goto/16 +AAAA */ 1179 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1180 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1181 bmi common_backwardBranch @ backward branch, do periodic checks 1182#if defined(WITH_JIT) 1183 GET_JIT_PROF_TABLE(r0) 1184 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1185 cmp r0,#0 1186 bne common_updateProfile 1187 GET_INST_OPCODE(ip) @ extract opcode from rINST 1188 GOTO_OPCODE(ip) @ jump to next instruction 1189#else 1190 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1191 GET_INST_OPCODE(ip) @ extract opcode from rINST 1192 GOTO_OPCODE(ip) @ jump to next instruction 1193#endif 1194 1195/* ------------------------------ */ 1196 .balign 64 1197.L_OP_GOTO_32: /* 0x2a */ 1198/* File: armv5te/OP_GOTO_32.S */ 1199 /* 1200 * Unconditional branch, 32-bit offset. 1201 * 1202 * The branch distance is a signed code-unit offset, which we need to 1203 * double to get a byte offset. 1204 * 1205 * Unlike most opcodes, this one is allowed to branch to itself, so 1206 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1207 * instruction doesn't affect the V flag, so we need to clear it 1208 * explicitly. 1209 */ 1210 /* goto/32 +AAAAAAAA */ 1211 FETCH(r0, 1) @ r0<- aaaa (lo) 1212 FETCH(r1, 2) @ r1<- AAAA (hi) 1213 cmp ip, ip @ (clear V flag during stall) 1214 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1215 mov r9, r0, asl #1 @ r9<- byte offset 1216 ble common_backwardBranch @ backward branch, do periodic checks 1217#if defined(WITH_JIT) 1218 GET_JIT_PROF_TABLE(r0) 1219 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1220 cmp r0,#0 1221 bne common_updateProfile 1222 GET_INST_OPCODE(ip) @ extract opcode from rINST 1223 GOTO_OPCODE(ip) @ jump to next instruction 1224#else 1225 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1226 GET_INST_OPCODE(ip) @ extract opcode from rINST 1227 GOTO_OPCODE(ip) @ jump to next instruction 1228#endif 1229 1230/* ------------------------------ */ 1231 .balign 64 1232.L_OP_PACKED_SWITCH: /* 0x2b */ 1233/* File: armv5te/OP_PACKED_SWITCH.S */ 1234 /* 1235 * Handle a packed-switch or sparse-switch instruction. In both cases 1236 * we decode it and hand it off to a helper function. 1237 * 1238 * We don't really expect backward branches in a switch statement, but 1239 * they're perfectly legal, so we check for them here. 1240 * 1241 * for: packed-switch, sparse-switch 1242 */ 1243 /* op vAA, +BBBB */ 1244 FETCH(r0, 1) @ r0<- bbbb (lo) 1245 FETCH(r1, 2) @ r1<- BBBB (hi) 1246 mov r3, rINST, lsr #8 @ r3<- AA 1247 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1248 GET_VREG(r1, r3) @ r1<- vAA 1249 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1250 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1251 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1252 bmi common_backwardBranch @ backward branch, do periodic checks 1253 beq common_backwardBranch @ (want to use BLE but V is unknown) 1254#if defined(WITH_JIT) 1255 GET_JIT_PROF_TABLE(r0) 1256 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1257 cmp r0,#0 1258 bne common_updateProfile 1259 GET_INST_OPCODE(ip) @ extract opcode from rINST 1260 GOTO_OPCODE(ip) @ jump to next instruction 1261#else 1262 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1263 GET_INST_OPCODE(ip) @ extract opcode from rINST 1264 GOTO_OPCODE(ip) @ jump to next instruction 1265#endif 1266 1267/* ------------------------------ */ 1268 .balign 64 1269.L_OP_SPARSE_SWITCH: /* 0x2c */ 1270/* File: armv5te/OP_SPARSE_SWITCH.S */ 1271/* File: armv5te/OP_PACKED_SWITCH.S */ 1272 /* 1273 * Handle a packed-switch or sparse-switch instruction. In both cases 1274 * we decode it and hand it off to a helper function. 1275 * 1276 * We don't really expect backward branches in a switch statement, but 1277 * they're perfectly legal, so we check for them here. 1278 * 1279 * for: packed-switch, sparse-switch 1280 */ 1281 /* op vAA, +BBBB */ 1282 FETCH(r0, 1) @ r0<- bbbb (lo) 1283 FETCH(r1, 2) @ r1<- BBBB (hi) 1284 mov r3, rINST, lsr #8 @ r3<- AA 1285 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1286 GET_VREG(r1, r3) @ r1<- vAA 1287 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1288 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1289 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1290 bmi common_backwardBranch @ backward branch, do periodic checks 1291 beq common_backwardBranch @ (want to use BLE but V is unknown) 1292#if defined(WITH_JIT) 1293 GET_JIT_PROF_TABLE(r0) 1294 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1295 cmp r0,#0 1296 bne common_updateProfile 1297 GET_INST_OPCODE(ip) @ extract opcode from rINST 1298 GOTO_OPCODE(ip) @ jump to next instruction 1299#else 1300 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1301 GET_INST_OPCODE(ip) @ extract opcode from rINST 1302 GOTO_OPCODE(ip) @ jump to next instruction 1303#endif 1304 1305 1306/* ------------------------------ */ 1307 .balign 64 1308.L_OP_CMPL_FLOAT: /* 0x2d */ 1309/* File: arm-vfp/OP_CMPL_FLOAT.S */ 1310 /* 1311 * Compare two floating-point values. Puts 0, 1, or -1 into the 1312 * destination register based on the results of the comparison. 1313 * 1314 * int compare(x, y) { 1315 * if (x == y) { 1316 * return 0; 1317 * } else if (x > y) { 1318 * return 1; 1319 * } else if (x < y) { 1320 * return -1; 1321 * } else { 1322 * return -1; 1323 * } 1324 * } 1325 */ 1326 /* op vAA, vBB, vCC */ 1327 FETCH(r0, 1) @ r0<- CCBB 1328 mov r9, rINST, lsr #8 @ r9<- AA 1329 and r2, r0, #255 @ r2<- BB 1330 mov r3, r0, lsr #8 @ r3<- CC 1331 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1332 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1333 flds s0, [r2] @ s0<- vBB 1334 flds s1, [r3] @ s1<- vCC 1335 fcmpes s0, s1 @ compare (vBB, vCC) 1336 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1337 mvn r0, #0 @ r0<- -1 (default) 1338 GET_INST_OPCODE(ip) @ extract opcode from rINST 1339 fmstat @ export status flags 1340 movgt r0, #1 @ (greater than) r1<- 1 1341 moveq r0, #0 @ (equal) r1<- 0 1342 b .LOP_CMPL_FLOAT_finish @ argh 1343 1344 1345/* ------------------------------ */ 1346 .balign 64 1347.L_OP_CMPG_FLOAT: /* 0x2e */ 1348/* File: arm-vfp/OP_CMPG_FLOAT.S */ 1349 /* 1350 * Compare two floating-point values. Puts 0, 1, or -1 into the 1351 * destination register based on the results of the comparison. 1352 * 1353 * int compare(x, y) { 1354 * if (x == y) { 1355 * return 0; 1356 * } else if (x < y) { 1357 * return -1; 1358 * } else if (x > y) { 1359 * return 1; 1360 * } else { 1361 * return 1; 1362 * } 1363 * } 1364 */ 1365 /* op vAA, vBB, vCC */ 1366 FETCH(r0, 1) @ r0<- CCBB 1367 mov r9, rINST, lsr #8 @ r9<- AA 1368 and r2, r0, #255 @ r2<- BB 1369 mov r3, r0, lsr #8 @ r3<- CC 1370 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1371 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1372 flds s0, [r2] @ s0<- vBB 1373 flds s1, [r3] @ s1<- vCC 1374 fcmpes s0, s1 @ compare (vBB, vCC) 1375 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1376 mov r0, #1 @ r0<- 1 (default) 1377 GET_INST_OPCODE(ip) @ extract opcode from rINST 1378 fmstat @ export status flags 1379 mvnmi r0, #0 @ (less than) r1<- -1 1380 moveq r0, #0 @ (equal) r1<- 0 1381 b .LOP_CMPG_FLOAT_finish @ argh 1382 1383 1384/* ------------------------------ */ 1385 .balign 64 1386.L_OP_CMPL_DOUBLE: /* 0x2f */ 1387/* File: arm-vfp/OP_CMPL_DOUBLE.S */ 1388 /* 1389 * Compare two floating-point values. Puts 0, 1, or -1 into the 1390 * destination register based on the results of the comparison. 1391 * 1392 * int compare(x, y) { 1393 * if (x == y) { 1394 * return 0; 1395 * } else if (x > y) { 1396 * return 1; 1397 * } else if (x < y) { 1398 * return -1; 1399 * } else { 1400 * return -1; 1401 * } 1402 * } 1403 */ 1404 /* op vAA, vBB, vCC */ 1405 FETCH(r0, 1) @ r0<- CCBB 1406 mov r9, rINST, lsr #8 @ r9<- AA 1407 and r2, r0, #255 @ r2<- BB 1408 mov r3, r0, lsr #8 @ r3<- CC 1409 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1410 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1411 fldd d0, [r2] @ d0<- vBB 1412 fldd d1, [r3] @ d1<- vCC 1413 fcmped d0, d1 @ compare (vBB, vCC) 1414 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1415 mvn r0, #0 @ r0<- -1 (default) 1416 GET_INST_OPCODE(ip) @ extract opcode from rINST 1417 fmstat @ export status flags 1418 movgt r0, #1 @ (greater than) r1<- 1 1419 moveq r0, #0 @ (equal) r1<- 0 1420 b .LOP_CMPL_DOUBLE_finish @ argh 1421 1422 1423/* ------------------------------ */ 1424 .balign 64 1425.L_OP_CMPG_DOUBLE: /* 0x30 */ 1426/* File: arm-vfp/OP_CMPG_DOUBLE.S */ 1427 /* 1428 * Compare two floating-point values. Puts 0, 1, or -1 into the 1429 * destination register based on the results of the comparison. 1430 * 1431 * int compare(x, y) { 1432 * if (x == y) { 1433 * return 0; 1434 * } else if (x < y) { 1435 * return -1; 1436 * } else if (x > y) { 1437 * return 1; 1438 * } else { 1439 * return 1; 1440 * } 1441 * } 1442 */ 1443 /* op vAA, vBB, vCC */ 1444 FETCH(r0, 1) @ r0<- CCBB 1445 mov r9, rINST, lsr #8 @ r9<- AA 1446 and r2, r0, #255 @ r2<- BB 1447 mov r3, r0, lsr #8 @ r3<- CC 1448 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1449 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1450 fldd d0, [r2] @ d0<- vBB 1451 fldd d1, [r3] @ d1<- vCC 1452 fcmped d0, d1 @ compare (vBB, vCC) 1453 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1454 mov r0, #1 @ r0<- 1 (default) 1455 GET_INST_OPCODE(ip) @ extract opcode from rINST 1456 fmstat @ export status flags 1457 mvnmi r0, #0 @ (less than) r1<- -1 1458 moveq r0, #0 @ (equal) r1<- 0 1459 b .LOP_CMPG_DOUBLE_finish @ argh 1460 1461 1462/* ------------------------------ */ 1463 .balign 64 1464.L_OP_CMP_LONG: /* 0x31 */ 1465/* File: armv5te/OP_CMP_LONG.S */ 1466 /* 1467 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1468 * register based on the results of the comparison. 1469 * 1470 * We load the full values with LDM, but in practice many values could 1471 * be resolved by only looking at the high word. This could be made 1472 * faster or slower by splitting the LDM into a pair of LDRs. 1473 * 1474 * If we just wanted to set condition flags, we could do this: 1475 * subs ip, r0, r2 1476 * sbcs ip, r1, r3 1477 * subeqs ip, r0, r2 1478 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1479 * integer value, which we can do with 2 conditional mov/mvn instructions 1480 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1481 * us a constant 5-cycle path plus a branch at the end to the 1482 * instruction epilogue code. The multi-compare approach below needs 1483 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1484 * in the worst case (the 64-bit values are equal). 1485 */ 1486 /* cmp-long vAA, vBB, vCC */ 1487 FETCH(r0, 1) @ r0<- CCBB 1488 mov r9, rINST, lsr #8 @ r9<- AA 1489 and r2, r0, #255 @ r2<- BB 1490 mov r3, r0, lsr #8 @ r3<- CC 1491 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1492 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1493 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1494 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1495 cmp r1, r3 @ compare (vBB+1, vCC+1) 1496 blt .LOP_CMP_LONG_less @ signed compare on high part 1497 bgt .LOP_CMP_LONG_greater 1498 subs r1, r0, r2 @ r1<- r0 - r2 1499 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1500 bne .LOP_CMP_LONG_less 1501 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1502 1503/* ------------------------------ */ 1504 .balign 64 1505.L_OP_IF_EQ: /* 0x32 */ 1506/* File: armv6t2/OP_IF_EQ.S */ 1507/* File: armv6t2/bincmp.S */ 1508 /* 1509 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1510 * fragment that specifies the *reverse* comparison to perform, e.g. 1511 * for "if-le" you would use "gt". 1512 * 1513 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1514 */ 1515 /* if-cmp vA, vB, +CCCC */ 1516 mov r1, rINST, lsr #12 @ r1<- B 1517 ubfx r0, rINST, #8, #4 @ r0<- A 1518 GET_VREG(r3, r1) @ r3<- vB 1519 GET_VREG(r2, r0) @ r2<- vA 1520 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1521 cmp r2, r3 @ compare (vA, vB) 1522 bne 1f @ branch to 1 if comparison failed 1523 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1524 movs r9, r9, asl #1 @ convert to bytes, check sign 1525 bmi common_backwardBranch @ yes, do periodic checks 15261: 1527#if defined(WITH_JIT) 1528 GET_JIT_PROF_TABLE(r0) 1529 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1530 b common_testUpdateProfile 1531#else 1532 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1533 GET_INST_OPCODE(ip) @ extract opcode from rINST 1534 GOTO_OPCODE(ip) @ jump to next instruction 1535#endif 1536 1537 1538/* ------------------------------ */ 1539 .balign 64 1540.L_OP_IF_NE: /* 0x33 */ 1541/* File: armv6t2/OP_IF_NE.S */ 1542/* File: armv6t2/bincmp.S */ 1543 /* 1544 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1545 * fragment that specifies the *reverse* comparison to perform, e.g. 1546 * for "if-le" you would use "gt". 1547 * 1548 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1549 */ 1550 /* if-cmp vA, vB, +CCCC */ 1551 mov r1, rINST, lsr #12 @ r1<- B 1552 ubfx r0, rINST, #8, #4 @ r0<- A 1553 GET_VREG(r3, r1) @ r3<- vB 1554 GET_VREG(r2, r0) @ r2<- vA 1555 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1556 cmp r2, r3 @ compare (vA, vB) 1557 beq 1f @ branch to 1 if comparison failed 1558 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1559 movs r9, r9, asl #1 @ convert to bytes, check sign 1560 bmi common_backwardBranch @ yes, do periodic checks 15611: 1562#if defined(WITH_JIT) 1563 GET_JIT_PROF_TABLE(r0) 1564 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1565 b common_testUpdateProfile 1566#else 1567 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1568 GET_INST_OPCODE(ip) @ extract opcode from rINST 1569 GOTO_OPCODE(ip) @ jump to next instruction 1570#endif 1571 1572 1573/* ------------------------------ */ 1574 .balign 64 1575.L_OP_IF_LT: /* 0x34 */ 1576/* File: armv6t2/OP_IF_LT.S */ 1577/* File: armv6t2/bincmp.S */ 1578 /* 1579 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1580 * fragment that specifies the *reverse* comparison to perform, e.g. 1581 * for "if-le" you would use "gt". 1582 * 1583 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1584 */ 1585 /* if-cmp vA, vB, +CCCC */ 1586 mov r1, rINST, lsr #12 @ r1<- B 1587 ubfx r0, rINST, #8, #4 @ r0<- A 1588 GET_VREG(r3, r1) @ r3<- vB 1589 GET_VREG(r2, r0) @ r2<- vA 1590 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1591 cmp r2, r3 @ compare (vA, vB) 1592 bge 1f @ branch to 1 if comparison failed 1593 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1594 movs r9, r9, asl #1 @ convert to bytes, check sign 1595 bmi common_backwardBranch @ yes, do periodic checks 15961: 1597#if defined(WITH_JIT) 1598 GET_JIT_PROF_TABLE(r0) 1599 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1600 b common_testUpdateProfile 1601#else 1602 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1603 GET_INST_OPCODE(ip) @ extract opcode from rINST 1604 GOTO_OPCODE(ip) @ jump to next instruction 1605#endif 1606 1607 1608/* ------------------------------ */ 1609 .balign 64 1610.L_OP_IF_GE: /* 0x35 */ 1611/* File: armv6t2/OP_IF_GE.S */ 1612/* File: armv6t2/bincmp.S */ 1613 /* 1614 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1615 * fragment that specifies the *reverse* comparison to perform, e.g. 1616 * for "if-le" you would use "gt". 1617 * 1618 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1619 */ 1620 /* if-cmp vA, vB, +CCCC */ 1621 mov r1, rINST, lsr #12 @ r1<- B 1622 ubfx r0, rINST, #8, #4 @ r0<- A 1623 GET_VREG(r3, r1) @ r3<- vB 1624 GET_VREG(r2, r0) @ r2<- vA 1625 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1626 cmp r2, r3 @ compare (vA, vB) 1627 blt 1f @ branch to 1 if comparison failed 1628 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1629 movs r9, r9, asl #1 @ convert to bytes, check sign 1630 bmi common_backwardBranch @ yes, do periodic checks 16311: 1632#if defined(WITH_JIT) 1633 GET_JIT_PROF_TABLE(r0) 1634 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1635 b common_testUpdateProfile 1636#else 1637 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1638 GET_INST_OPCODE(ip) @ extract opcode from rINST 1639 GOTO_OPCODE(ip) @ jump to next instruction 1640#endif 1641 1642 1643/* ------------------------------ */ 1644 .balign 64 1645.L_OP_IF_GT: /* 0x36 */ 1646/* File: armv6t2/OP_IF_GT.S */ 1647/* File: armv6t2/bincmp.S */ 1648 /* 1649 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1650 * fragment that specifies the *reverse* comparison to perform, e.g. 1651 * for "if-le" you would use "gt". 1652 * 1653 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1654 */ 1655 /* if-cmp vA, vB, +CCCC */ 1656 mov r1, rINST, lsr #12 @ r1<- B 1657 ubfx r0, rINST, #8, #4 @ r0<- A 1658 GET_VREG(r3, r1) @ r3<- vB 1659 GET_VREG(r2, r0) @ r2<- vA 1660 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1661 cmp r2, r3 @ compare (vA, vB) 1662 ble 1f @ branch to 1 if comparison failed 1663 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1664 movs r9, r9, asl #1 @ convert to bytes, check sign 1665 bmi common_backwardBranch @ yes, do periodic checks 16661: 1667#if defined(WITH_JIT) 1668 GET_JIT_PROF_TABLE(r0) 1669 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1670 b common_testUpdateProfile 1671#else 1672 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1673 GET_INST_OPCODE(ip) @ extract opcode from rINST 1674 GOTO_OPCODE(ip) @ jump to next instruction 1675#endif 1676 1677 1678/* ------------------------------ */ 1679 .balign 64 1680.L_OP_IF_LE: /* 0x37 */ 1681/* File: armv6t2/OP_IF_LE.S */ 1682/* File: armv6t2/bincmp.S */ 1683 /* 1684 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1685 * fragment that specifies the *reverse* comparison to perform, e.g. 1686 * for "if-le" you would use "gt". 1687 * 1688 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1689 */ 1690 /* if-cmp vA, vB, +CCCC */ 1691 mov r1, rINST, lsr #12 @ r1<- B 1692 ubfx r0, rINST, #8, #4 @ r0<- A 1693 GET_VREG(r3, r1) @ r3<- vB 1694 GET_VREG(r2, r0) @ r2<- vA 1695 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1696 cmp r2, r3 @ compare (vA, vB) 1697 bgt 1f @ branch to 1 if comparison failed 1698 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1699 movs r9, r9, asl #1 @ convert to bytes, check sign 1700 bmi common_backwardBranch @ yes, do periodic checks 17011: 1702#if defined(WITH_JIT) 1703 GET_JIT_PROF_TABLE(r0) 1704 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1705 b common_testUpdateProfile 1706#else 1707 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1708 GET_INST_OPCODE(ip) @ extract opcode from rINST 1709 GOTO_OPCODE(ip) @ jump to next instruction 1710#endif 1711 1712 1713/* ------------------------------ */ 1714 .balign 64 1715.L_OP_IF_EQZ: /* 0x38 */ 1716/* File: armv5te/OP_IF_EQZ.S */ 1717/* File: armv5te/zcmp.S */ 1718 /* 1719 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1720 * fragment that specifies the *reverse* comparison to perform, e.g. 1721 * for "if-le" you would use "gt". 1722 * 1723 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1724 */ 1725 /* if-cmp vAA, +BBBB */ 1726 mov r0, rINST, lsr #8 @ r0<- AA 1727 GET_VREG(r2, r0) @ r2<- vAA 1728 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1729 cmp r2, #0 @ compare (vA, 0) 1730 bne 1f @ branch to 1 if comparison failed 1731 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1732 movs r9, r9, asl #1 @ convert to bytes, check sign 1733 bmi common_backwardBranch @ backward branch, do periodic checks 17341: 1735#if defined(WITH_JIT) 1736 GET_JIT_PROF_TABLE(r0) 1737 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1738 cmp r0,#0 1739 bne common_updateProfile 1740 GET_INST_OPCODE(ip) @ extract opcode from rINST 1741 GOTO_OPCODE(ip) @ jump to next instruction 1742#else 1743 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1744 GET_INST_OPCODE(ip) @ extract opcode from rINST 1745 GOTO_OPCODE(ip) @ jump to next instruction 1746#endif 1747 1748 1749/* ------------------------------ */ 1750 .balign 64 1751.L_OP_IF_NEZ: /* 0x39 */ 1752/* File: armv5te/OP_IF_NEZ.S */ 1753/* File: armv5te/zcmp.S */ 1754 /* 1755 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1756 * fragment that specifies the *reverse* comparison to perform, e.g. 1757 * for "if-le" you would use "gt". 1758 * 1759 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1760 */ 1761 /* if-cmp vAA, +BBBB */ 1762 mov r0, rINST, lsr #8 @ r0<- AA 1763 GET_VREG(r2, r0) @ r2<- vAA 1764 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1765 cmp r2, #0 @ compare (vA, 0) 1766 beq 1f @ branch to 1 if comparison failed 1767 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1768 movs r9, r9, asl #1 @ convert to bytes, check sign 1769 bmi common_backwardBranch @ backward branch, do periodic checks 17701: 1771#if defined(WITH_JIT) 1772 GET_JIT_PROF_TABLE(r0) 1773 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1774 cmp r0,#0 1775 bne common_updateProfile 1776 GET_INST_OPCODE(ip) @ extract opcode from rINST 1777 GOTO_OPCODE(ip) @ jump to next instruction 1778#else 1779 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1780 GET_INST_OPCODE(ip) @ extract opcode from rINST 1781 GOTO_OPCODE(ip) @ jump to next instruction 1782#endif 1783 1784 1785/* ------------------------------ */ 1786 .balign 64 1787.L_OP_IF_LTZ: /* 0x3a */ 1788/* File: armv5te/OP_IF_LTZ.S */ 1789/* File: armv5te/zcmp.S */ 1790 /* 1791 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1792 * fragment that specifies the *reverse* comparison to perform, e.g. 1793 * for "if-le" you would use "gt". 1794 * 1795 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1796 */ 1797 /* if-cmp vAA, +BBBB */ 1798 mov r0, rINST, lsr #8 @ r0<- AA 1799 GET_VREG(r2, r0) @ r2<- vAA 1800 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1801 cmp r2, #0 @ compare (vA, 0) 1802 bge 1f @ branch to 1 if comparison failed 1803 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1804 movs r9, r9, asl #1 @ convert to bytes, check sign 1805 bmi common_backwardBranch @ backward branch, do periodic checks 18061: 1807#if defined(WITH_JIT) 1808 GET_JIT_PROF_TABLE(r0) 1809 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1810 cmp r0,#0 1811 bne common_updateProfile 1812 GET_INST_OPCODE(ip) @ extract opcode from rINST 1813 GOTO_OPCODE(ip) @ jump to next instruction 1814#else 1815 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1816 GET_INST_OPCODE(ip) @ extract opcode from rINST 1817 GOTO_OPCODE(ip) @ jump to next instruction 1818#endif 1819 1820 1821/* ------------------------------ */ 1822 .balign 64 1823.L_OP_IF_GEZ: /* 0x3b */ 1824/* File: armv5te/OP_IF_GEZ.S */ 1825/* File: armv5te/zcmp.S */ 1826 /* 1827 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1828 * fragment that specifies the *reverse* comparison to perform, e.g. 1829 * for "if-le" you would use "gt". 1830 * 1831 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1832 */ 1833 /* if-cmp vAA, +BBBB */ 1834 mov r0, rINST, lsr #8 @ r0<- AA 1835 GET_VREG(r2, r0) @ r2<- vAA 1836 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1837 cmp r2, #0 @ compare (vA, 0) 1838 blt 1f @ branch to 1 if comparison failed 1839 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1840 movs r9, r9, asl #1 @ convert to bytes, check sign 1841 bmi common_backwardBranch @ backward branch, do periodic checks 18421: 1843#if defined(WITH_JIT) 1844 GET_JIT_PROF_TABLE(r0) 1845 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1846 cmp r0,#0 1847 bne common_updateProfile 1848 GET_INST_OPCODE(ip) @ extract opcode from rINST 1849 GOTO_OPCODE(ip) @ jump to next instruction 1850#else 1851 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1852 GET_INST_OPCODE(ip) @ extract opcode from rINST 1853 GOTO_OPCODE(ip) @ jump to next instruction 1854#endif 1855 1856 1857/* ------------------------------ */ 1858 .balign 64 1859.L_OP_IF_GTZ: /* 0x3c */ 1860/* File: armv5te/OP_IF_GTZ.S */ 1861/* File: armv5te/zcmp.S */ 1862 /* 1863 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1864 * fragment that specifies the *reverse* comparison to perform, e.g. 1865 * for "if-le" you would use "gt". 1866 * 1867 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1868 */ 1869 /* if-cmp vAA, +BBBB */ 1870 mov r0, rINST, lsr #8 @ r0<- AA 1871 GET_VREG(r2, r0) @ r2<- vAA 1872 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1873 cmp r2, #0 @ compare (vA, 0) 1874 ble 1f @ branch to 1 if comparison failed 1875 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1876 movs r9, r9, asl #1 @ convert to bytes, check sign 1877 bmi common_backwardBranch @ backward branch, do periodic checks 18781: 1879#if defined(WITH_JIT) 1880 GET_JIT_PROF_TABLE(r0) 1881 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1882 cmp r0,#0 1883 bne common_updateProfile 1884 GET_INST_OPCODE(ip) @ extract opcode from rINST 1885 GOTO_OPCODE(ip) @ jump to next instruction 1886#else 1887 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1888 GET_INST_OPCODE(ip) @ extract opcode from rINST 1889 GOTO_OPCODE(ip) @ jump to next instruction 1890#endif 1891 1892 1893/* ------------------------------ */ 1894 .balign 64 1895.L_OP_IF_LEZ: /* 0x3d */ 1896/* File: armv5te/OP_IF_LEZ.S */ 1897/* File: armv5te/zcmp.S */ 1898 /* 1899 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1900 * fragment that specifies the *reverse* comparison to perform, e.g. 1901 * for "if-le" you would use "gt". 1902 * 1903 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1904 */ 1905 /* if-cmp vAA, +BBBB */ 1906 mov r0, rINST, lsr #8 @ r0<- AA 1907 GET_VREG(r2, r0) @ r2<- vAA 1908 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1909 cmp r2, #0 @ compare (vA, 0) 1910 bgt 1f @ branch to 1 if comparison failed 1911 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1912 movs r9, r9, asl #1 @ convert to bytes, check sign 1913 bmi common_backwardBranch @ backward branch, do periodic checks 19141: 1915#if defined(WITH_JIT) 1916 GET_JIT_PROF_TABLE(r0) 1917 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1918 cmp r0,#0 1919 bne common_updateProfile 1920 GET_INST_OPCODE(ip) @ extract opcode from rINST 1921 GOTO_OPCODE(ip) @ jump to next instruction 1922#else 1923 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1924 GET_INST_OPCODE(ip) @ extract opcode from rINST 1925 GOTO_OPCODE(ip) @ jump to next instruction 1926#endif 1927 1928 1929/* ------------------------------ */ 1930 .balign 64 1931.L_OP_UNUSED_3E: /* 0x3e */ 1932/* File: armv5te/OP_UNUSED_3E.S */ 1933/* File: armv5te/unused.S */ 1934 bl common_abort 1935 1936 1937/* ------------------------------ */ 1938 .balign 64 1939.L_OP_UNUSED_3F: /* 0x3f */ 1940/* File: armv5te/OP_UNUSED_3F.S */ 1941/* File: armv5te/unused.S */ 1942 bl common_abort 1943 1944 1945/* ------------------------------ */ 1946 .balign 64 1947.L_OP_UNUSED_40: /* 0x40 */ 1948/* File: armv5te/OP_UNUSED_40.S */ 1949/* File: armv5te/unused.S */ 1950 bl common_abort 1951 1952 1953/* ------------------------------ */ 1954 .balign 64 1955.L_OP_UNUSED_41: /* 0x41 */ 1956/* File: armv5te/OP_UNUSED_41.S */ 1957/* File: armv5te/unused.S */ 1958 bl common_abort 1959 1960 1961/* ------------------------------ */ 1962 .balign 64 1963.L_OP_UNUSED_42: /* 0x42 */ 1964/* File: armv5te/OP_UNUSED_42.S */ 1965/* File: armv5te/unused.S */ 1966 bl common_abort 1967 1968 1969/* ------------------------------ */ 1970 .balign 64 1971.L_OP_UNUSED_43: /* 0x43 */ 1972/* File: armv5te/OP_UNUSED_43.S */ 1973/* File: armv5te/unused.S */ 1974 bl common_abort 1975 1976 1977/* ------------------------------ */ 1978 .balign 64 1979.L_OP_AGET: /* 0x44 */ 1980/* File: armv5te/OP_AGET.S */ 1981 /* 1982 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1983 * 1984 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1985 * instructions. We use a pair of FETCH_Bs instead. 1986 * 1987 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1988 */ 1989 /* op vAA, vBB, vCC */ 1990 FETCH_B(r2, 1, 0) @ r2<- BB 1991 mov r9, rINST, lsr #8 @ r9<- AA 1992 FETCH_B(r3, 1, 1) @ r3<- CC 1993 GET_VREG(r0, r2) @ r0<- vBB (array object) 1994 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1995 cmp r0, #0 @ null array object? 1996 beq common_errNullObject @ yes, bail 1997 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1998 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 1999 cmp r1, r3 @ compare unsigned index, length 2000 bcs common_errArrayIndex @ index >= length, bail 2001 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2002 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2003 GET_INST_OPCODE(ip) @ extract opcode from rINST 2004 SET_VREG(r2, r9) @ vAA<- r2 2005 GOTO_OPCODE(ip) @ jump to next instruction 2006 2007/* ------------------------------ */ 2008 .balign 64 2009.L_OP_AGET_WIDE: /* 0x45 */ 2010/* File: armv5te/OP_AGET_WIDE.S */ 2011 /* 2012 * Array get, 64 bits. vAA <- vBB[vCC]. 2013 * 2014 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 2015 */ 2016 /* aget-wide vAA, vBB, vCC */ 2017 FETCH(r0, 1) @ r0<- CCBB 2018 mov r9, rINST, lsr #8 @ r9<- AA 2019 and r2, r0, #255 @ r2<- BB 2020 mov r3, r0, lsr #8 @ r3<- CC 2021 GET_VREG(r0, r2) @ r0<- vBB (array object) 2022 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2023 cmp r0, #0 @ null array object? 2024 beq common_errNullObject @ yes, bail 2025 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2026 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2027 cmp r1, r3 @ compare unsigned index, length 2028 bcc .LOP_AGET_WIDE_finish @ okay, continue below 2029 b common_errArrayIndex @ index >= length, bail 2030 @ May want to swap the order of these two branches depending on how the 2031 @ branch prediction (if any) handles conditional forward branches vs. 2032 @ unconditional forward branches. 2033 2034/* ------------------------------ */ 2035 .balign 64 2036.L_OP_AGET_OBJECT: /* 0x46 */ 2037/* File: armv5te/OP_AGET_OBJECT.S */ 2038/* File: armv5te/OP_AGET.S */ 2039 /* 2040 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2041 * 2042 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2043 * instructions. We use a pair of FETCH_Bs instead. 2044 * 2045 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2046 */ 2047 /* op vAA, vBB, vCC */ 2048 FETCH_B(r2, 1, 0) @ r2<- BB 2049 mov r9, rINST, lsr #8 @ r9<- AA 2050 FETCH_B(r3, 1, 1) @ r3<- CC 2051 GET_VREG(r0, r2) @ r0<- vBB (array object) 2052 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2053 cmp r0, #0 @ null array object? 2054 beq common_errNullObject @ yes, bail 2055 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2056 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2057 cmp r1, r3 @ compare unsigned index, length 2058 bcs common_errArrayIndex @ index >= length, bail 2059 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2060 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2061 GET_INST_OPCODE(ip) @ extract opcode from rINST 2062 SET_VREG(r2, r9) @ vAA<- r2 2063 GOTO_OPCODE(ip) @ jump to next instruction 2064 2065 2066/* ------------------------------ */ 2067 .balign 64 2068.L_OP_AGET_BOOLEAN: /* 0x47 */ 2069/* File: armv5te/OP_AGET_BOOLEAN.S */ 2070/* File: armv5te/OP_AGET.S */ 2071 /* 2072 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2073 * 2074 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2075 * instructions. We use a pair of FETCH_Bs instead. 2076 * 2077 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2078 */ 2079 /* op vAA, vBB, vCC */ 2080 FETCH_B(r2, 1, 0) @ r2<- BB 2081 mov r9, rINST, lsr #8 @ r9<- AA 2082 FETCH_B(r3, 1, 1) @ r3<- CC 2083 GET_VREG(r0, r2) @ r0<- vBB (array object) 2084 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2085 cmp r0, #0 @ null array object? 2086 beq common_errNullObject @ yes, bail 2087 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2088 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2089 cmp r1, r3 @ compare unsigned index, length 2090 bcs common_errArrayIndex @ index >= length, bail 2091 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2092 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2093 GET_INST_OPCODE(ip) @ extract opcode from rINST 2094 SET_VREG(r2, r9) @ vAA<- r2 2095 GOTO_OPCODE(ip) @ jump to next instruction 2096 2097 2098/* ------------------------------ */ 2099 .balign 64 2100.L_OP_AGET_BYTE: /* 0x48 */ 2101/* File: armv5te/OP_AGET_BYTE.S */ 2102/* File: armv5te/OP_AGET.S */ 2103 /* 2104 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2105 * 2106 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2107 * instructions. We use a pair of FETCH_Bs instead. 2108 * 2109 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2110 */ 2111 /* op vAA, vBB, vCC */ 2112 FETCH_B(r2, 1, 0) @ r2<- BB 2113 mov r9, rINST, lsr #8 @ r9<- AA 2114 FETCH_B(r3, 1, 1) @ r3<- CC 2115 GET_VREG(r0, r2) @ r0<- vBB (array object) 2116 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2117 cmp r0, #0 @ null array object? 2118 beq common_errNullObject @ yes, bail 2119 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2120 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2121 cmp r1, r3 @ compare unsigned index, length 2122 bcs common_errArrayIndex @ index >= length, bail 2123 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2124 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2125 GET_INST_OPCODE(ip) @ extract opcode from rINST 2126 SET_VREG(r2, r9) @ vAA<- r2 2127 GOTO_OPCODE(ip) @ jump to next instruction 2128 2129 2130/* ------------------------------ */ 2131 .balign 64 2132.L_OP_AGET_CHAR: /* 0x49 */ 2133/* File: armv5te/OP_AGET_CHAR.S */ 2134/* File: armv5te/OP_AGET.S */ 2135 /* 2136 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2137 * 2138 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2139 * instructions. We use a pair of FETCH_Bs instead. 2140 * 2141 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2142 */ 2143 /* op vAA, vBB, vCC */ 2144 FETCH_B(r2, 1, 0) @ r2<- BB 2145 mov r9, rINST, lsr #8 @ r9<- AA 2146 FETCH_B(r3, 1, 1) @ r3<- CC 2147 GET_VREG(r0, r2) @ r0<- vBB (array object) 2148 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2149 cmp r0, #0 @ null array object? 2150 beq common_errNullObject @ yes, bail 2151 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2152 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2153 cmp r1, r3 @ compare unsigned index, length 2154 bcs common_errArrayIndex @ index >= length, bail 2155 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2156 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2157 GET_INST_OPCODE(ip) @ extract opcode from rINST 2158 SET_VREG(r2, r9) @ vAA<- r2 2159 GOTO_OPCODE(ip) @ jump to next instruction 2160 2161 2162/* ------------------------------ */ 2163 .balign 64 2164.L_OP_AGET_SHORT: /* 0x4a */ 2165/* File: armv5te/OP_AGET_SHORT.S */ 2166/* File: armv5te/OP_AGET.S */ 2167 /* 2168 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2169 * 2170 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2171 * instructions. We use a pair of FETCH_Bs instead. 2172 * 2173 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2174 */ 2175 /* op vAA, vBB, vCC */ 2176 FETCH_B(r2, 1, 0) @ r2<- BB 2177 mov r9, rINST, lsr #8 @ r9<- AA 2178 FETCH_B(r3, 1, 1) @ r3<- CC 2179 GET_VREG(r0, r2) @ r0<- vBB (array object) 2180 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2181 cmp r0, #0 @ null array object? 2182 beq common_errNullObject @ yes, bail 2183 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2184 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2185 cmp r1, r3 @ compare unsigned index, length 2186 bcs common_errArrayIndex @ index >= length, bail 2187 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2188 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2189 GET_INST_OPCODE(ip) @ extract opcode from rINST 2190 SET_VREG(r2, r9) @ vAA<- r2 2191 GOTO_OPCODE(ip) @ jump to next instruction 2192 2193 2194/* ------------------------------ */ 2195 .balign 64 2196.L_OP_APUT: /* 0x4b */ 2197/* File: armv5te/OP_APUT.S */ 2198 /* 2199 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2200 * 2201 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2202 * instructions. We use a pair of FETCH_Bs instead. 2203 * 2204 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2205 */ 2206 /* op vAA, vBB, vCC */ 2207 FETCH_B(r2, 1, 0) @ r2<- BB 2208 mov r9, rINST, lsr #8 @ r9<- AA 2209 FETCH_B(r3, 1, 1) @ r3<- CC 2210 GET_VREG(r0, r2) @ r0<- vBB (array object) 2211 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2212 cmp r0, #0 @ null array object? 2213 beq common_errNullObject @ yes, bail 2214 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2215 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2216 cmp r1, r3 @ compare unsigned index, length 2217 bcs common_errArrayIndex @ index >= length, bail 2218 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2219 GET_VREG(r2, r9) @ r2<- vAA 2220 GET_INST_OPCODE(ip) @ extract opcode from rINST 2221 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2222 GOTO_OPCODE(ip) @ jump to next instruction 2223 2224/* ------------------------------ */ 2225 .balign 64 2226.L_OP_APUT_WIDE: /* 0x4c */ 2227/* File: armv5te/OP_APUT_WIDE.S */ 2228 /* 2229 * Array put, 64 bits. vBB[vCC] <- vAA. 2230 * 2231 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 2232 */ 2233 /* aput-wide vAA, vBB, vCC */ 2234 FETCH(r0, 1) @ r0<- CCBB 2235 mov r9, rINST, lsr #8 @ r9<- AA 2236 and r2, r0, #255 @ r2<- BB 2237 mov r3, r0, lsr #8 @ r3<- CC 2238 GET_VREG(r0, r2) @ r0<- vBB (array object) 2239 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2240 cmp r0, #0 @ null array object? 2241 beq common_errNullObject @ yes, bail 2242 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2243 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2244 cmp r1, r3 @ compare unsigned index, length 2245 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2246 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2247 b common_errArrayIndex @ index >= length, bail 2248 @ May want to swap the order of these two branches depending on how the 2249 @ branch prediction (if any) handles conditional forward branches vs. 2250 @ unconditional forward branches. 2251 2252/* ------------------------------ */ 2253 .balign 64 2254.L_OP_APUT_OBJECT: /* 0x4d */ 2255/* File: armv5te/OP_APUT_OBJECT.S */ 2256 /* 2257 * Store an object into an array. vBB[vCC] <- vAA. 2258 * 2259 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2260 * instructions. We use a pair of FETCH_Bs instead. 2261 */ 2262 /* op vAA, vBB, vCC */ 2263 FETCH(r0, 1) @ r0<- CCBB 2264 mov r9, rINST, lsr #8 @ r9<- AA 2265 and r2, r0, #255 @ r2<- BB 2266 mov r3, r0, lsr #8 @ r3<- CC 2267 GET_VREG(r1, r2) @ r1<- vBB (array object) 2268 GET_VREG(r0, r3) @ r0<- vCC (requested index) 2269 cmp r1, #0 @ null array object? 2270 GET_VREG(r9, r9) @ r9<- vAA 2271 beq common_errNullObject @ yes, bail 2272 ldr r3, [r1, #offArrayObject_length] @ r3<- arrayObj->length 2273 add r10, r1, r0, lsl #2 @ r10<- arrayObj + index*width 2274 cmp r0, r3 @ compare unsigned index, length 2275 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2276 b common_errArrayIndex @ index >= length, bail 2277 2278 2279/* ------------------------------ */ 2280 .balign 64 2281.L_OP_APUT_BOOLEAN: /* 0x4e */ 2282/* File: armv5te/OP_APUT_BOOLEAN.S */ 2283/* File: armv5te/OP_APUT.S */ 2284 /* 2285 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2286 * 2287 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2288 * instructions. We use a pair of FETCH_Bs instead. 2289 * 2290 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2291 */ 2292 /* op vAA, vBB, vCC */ 2293 FETCH_B(r2, 1, 0) @ r2<- BB 2294 mov r9, rINST, lsr #8 @ r9<- AA 2295 FETCH_B(r3, 1, 1) @ r3<- CC 2296 GET_VREG(r0, r2) @ r0<- vBB (array object) 2297 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2298 cmp r0, #0 @ null array object? 2299 beq common_errNullObject @ yes, bail 2300 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2301 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2302 cmp r1, r3 @ compare unsigned index, length 2303 bcs common_errArrayIndex @ index >= length, bail 2304 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2305 GET_VREG(r2, r9) @ r2<- vAA 2306 GET_INST_OPCODE(ip) @ extract opcode from rINST 2307 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2308 GOTO_OPCODE(ip) @ jump to next instruction 2309 2310 2311/* ------------------------------ */ 2312 .balign 64 2313.L_OP_APUT_BYTE: /* 0x4f */ 2314/* File: armv5te/OP_APUT_BYTE.S */ 2315/* File: armv5te/OP_APUT.S */ 2316 /* 2317 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2318 * 2319 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2320 * instructions. We use a pair of FETCH_Bs instead. 2321 * 2322 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2323 */ 2324 /* op vAA, vBB, vCC */ 2325 FETCH_B(r2, 1, 0) @ r2<- BB 2326 mov r9, rINST, lsr #8 @ r9<- AA 2327 FETCH_B(r3, 1, 1) @ r3<- CC 2328 GET_VREG(r0, r2) @ r0<- vBB (array object) 2329 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2330 cmp r0, #0 @ null array object? 2331 beq common_errNullObject @ yes, bail 2332 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2333 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2334 cmp r1, r3 @ compare unsigned index, length 2335 bcs common_errArrayIndex @ index >= length, bail 2336 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2337 GET_VREG(r2, r9) @ r2<- vAA 2338 GET_INST_OPCODE(ip) @ extract opcode from rINST 2339 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2340 GOTO_OPCODE(ip) @ jump to next instruction 2341 2342 2343/* ------------------------------ */ 2344 .balign 64 2345.L_OP_APUT_CHAR: /* 0x50 */ 2346/* File: armv5te/OP_APUT_CHAR.S */ 2347/* File: armv5te/OP_APUT.S */ 2348 /* 2349 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2350 * 2351 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2352 * instructions. We use a pair of FETCH_Bs instead. 2353 * 2354 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2355 */ 2356 /* op vAA, vBB, vCC */ 2357 FETCH_B(r2, 1, 0) @ r2<- BB 2358 mov r9, rINST, lsr #8 @ r9<- AA 2359 FETCH_B(r3, 1, 1) @ r3<- CC 2360 GET_VREG(r0, r2) @ r0<- vBB (array object) 2361 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2362 cmp r0, #0 @ null array object? 2363 beq common_errNullObject @ yes, bail 2364 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2365 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2366 cmp r1, r3 @ compare unsigned index, length 2367 bcs common_errArrayIndex @ index >= length, bail 2368 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2369 GET_VREG(r2, r9) @ r2<- vAA 2370 GET_INST_OPCODE(ip) @ extract opcode from rINST 2371 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2372 GOTO_OPCODE(ip) @ jump to next instruction 2373 2374 2375/* ------------------------------ */ 2376 .balign 64 2377.L_OP_APUT_SHORT: /* 0x51 */ 2378/* File: armv5te/OP_APUT_SHORT.S */ 2379/* File: armv5te/OP_APUT.S */ 2380 /* 2381 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2382 * 2383 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2384 * instructions. We use a pair of FETCH_Bs instead. 2385 * 2386 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2387 */ 2388 /* op vAA, vBB, vCC */ 2389 FETCH_B(r2, 1, 0) @ r2<- BB 2390 mov r9, rINST, lsr #8 @ r9<- AA 2391 FETCH_B(r3, 1, 1) @ r3<- CC 2392 GET_VREG(r0, r2) @ r0<- vBB (array object) 2393 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2394 cmp r0, #0 @ null array object? 2395 beq common_errNullObject @ yes, bail 2396 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2397 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2398 cmp r1, r3 @ compare unsigned index, length 2399 bcs common_errArrayIndex @ index >= length, bail 2400 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2401 GET_VREG(r2, r9) @ r2<- vAA 2402 GET_INST_OPCODE(ip) @ extract opcode from rINST 2403 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2404 GOTO_OPCODE(ip) @ jump to next instruction 2405 2406 2407/* ------------------------------ */ 2408 .balign 64 2409.L_OP_IGET: /* 0x52 */ 2410/* File: armv6t2/OP_IGET.S */ 2411 /* 2412 * General 32-bit instance field get. 2413 * 2414 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2415 */ 2416 /* op vA, vB, field@CCCC */ 2417 mov r0, rINST, lsr #12 @ r0<- B 2418 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2419 FETCH(r1, 1) @ r1<- field ref CCCC 2420 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2421 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2422 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2423 cmp r0, #0 @ is resolved entry null? 2424 bne .LOP_IGET_finish @ no, already resolved 24258: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2426 EXPORT_PC() @ resolve() could throw 2427 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2428 bl dvmResolveInstField @ r0<- resolved InstField ptr 2429 cmp r0, #0 2430 bne .LOP_IGET_finish 2431 b common_exceptionThrown 2432 2433/* ------------------------------ */ 2434 .balign 64 2435.L_OP_IGET_WIDE: /* 0x53 */ 2436/* File: armv6t2/OP_IGET_WIDE.S */ 2437 /* 2438 * Wide 32-bit instance field get. 2439 */ 2440 /* iget-wide vA, vB, field@CCCC */ 2441 mov r0, rINST, lsr #12 @ r0<- B 2442 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2443 FETCH(r1, 1) @ r1<- field ref CCCC 2444 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2445 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2446 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2447 cmp r0, #0 @ is resolved entry null? 2448 bne .LOP_IGET_WIDE_finish @ no, already resolved 24498: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2450 EXPORT_PC() @ resolve() could throw 2451 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2452 bl dvmResolveInstField @ r0<- resolved InstField ptr 2453 cmp r0, #0 2454 bne .LOP_IGET_WIDE_finish 2455 b common_exceptionThrown 2456 2457/* ------------------------------ */ 2458 .balign 64 2459.L_OP_IGET_OBJECT: /* 0x54 */ 2460/* File: armv5te/OP_IGET_OBJECT.S */ 2461/* File: armv5te/OP_IGET.S */ 2462 /* 2463 * General 32-bit instance field get. 2464 * 2465 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2466 */ 2467 /* op vA, vB, field@CCCC */ 2468 mov r0, rINST, lsr #12 @ r0<- B 2469 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2470 FETCH(r1, 1) @ r1<- field ref CCCC 2471 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2472 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2473 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2474 cmp r0, #0 @ is resolved entry null? 2475 bne .LOP_IGET_OBJECT_finish @ no, already resolved 24768: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2477 EXPORT_PC() @ resolve() could throw 2478 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2479 bl dvmResolveInstField @ r0<- resolved InstField ptr 2480 cmp r0, #0 2481 bne .LOP_IGET_OBJECT_finish 2482 b common_exceptionThrown 2483 2484 2485/* ------------------------------ */ 2486 .balign 64 2487.L_OP_IGET_BOOLEAN: /* 0x55 */ 2488/* File: armv5te/OP_IGET_BOOLEAN.S */ 2489@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2490/* File: armv5te/OP_IGET.S */ 2491 /* 2492 * General 32-bit instance field get. 2493 * 2494 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2495 */ 2496 /* op vA, vB, field@CCCC */ 2497 mov r0, rINST, lsr #12 @ r0<- B 2498 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2499 FETCH(r1, 1) @ r1<- field ref CCCC 2500 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2501 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2502 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2503 cmp r0, #0 @ is resolved entry null? 2504 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 25058: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2506 EXPORT_PC() @ resolve() could throw 2507 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2508 bl dvmResolveInstField @ r0<- resolved InstField ptr 2509 cmp r0, #0 2510 bne .LOP_IGET_BOOLEAN_finish 2511 b common_exceptionThrown 2512 2513 2514/* ------------------------------ */ 2515 .balign 64 2516.L_OP_IGET_BYTE: /* 0x56 */ 2517/* File: armv5te/OP_IGET_BYTE.S */ 2518@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2519/* File: armv5te/OP_IGET.S */ 2520 /* 2521 * General 32-bit instance field get. 2522 * 2523 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2524 */ 2525 /* op vA, vB, field@CCCC */ 2526 mov r0, rINST, lsr #12 @ r0<- B 2527 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2528 FETCH(r1, 1) @ r1<- field ref CCCC 2529 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2530 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2531 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2532 cmp r0, #0 @ is resolved entry null? 2533 bne .LOP_IGET_BYTE_finish @ no, already resolved 25348: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2535 EXPORT_PC() @ resolve() could throw 2536 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2537 bl dvmResolveInstField @ r0<- resolved InstField ptr 2538 cmp r0, #0 2539 bne .LOP_IGET_BYTE_finish 2540 b common_exceptionThrown 2541 2542 2543/* ------------------------------ */ 2544 .balign 64 2545.L_OP_IGET_CHAR: /* 0x57 */ 2546/* File: armv5te/OP_IGET_CHAR.S */ 2547@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2548/* File: armv5te/OP_IGET.S */ 2549 /* 2550 * General 32-bit instance field get. 2551 * 2552 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2553 */ 2554 /* op vA, vB, field@CCCC */ 2555 mov r0, rINST, lsr #12 @ r0<- B 2556 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2557 FETCH(r1, 1) @ r1<- field ref CCCC 2558 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2559 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2560 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2561 cmp r0, #0 @ is resolved entry null? 2562 bne .LOP_IGET_CHAR_finish @ no, already resolved 25638: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2564 EXPORT_PC() @ resolve() could throw 2565 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2566 bl dvmResolveInstField @ r0<- resolved InstField ptr 2567 cmp r0, #0 2568 bne .LOP_IGET_CHAR_finish 2569 b common_exceptionThrown 2570 2571 2572/* ------------------------------ */ 2573 .balign 64 2574.L_OP_IGET_SHORT: /* 0x58 */ 2575/* File: armv5te/OP_IGET_SHORT.S */ 2576@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2577/* File: armv5te/OP_IGET.S */ 2578 /* 2579 * General 32-bit instance field get. 2580 * 2581 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2582 */ 2583 /* op vA, vB, field@CCCC */ 2584 mov r0, rINST, lsr #12 @ r0<- B 2585 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2586 FETCH(r1, 1) @ r1<- field ref CCCC 2587 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2588 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2589 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2590 cmp r0, #0 @ is resolved entry null? 2591 bne .LOP_IGET_SHORT_finish @ no, already resolved 25928: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2593 EXPORT_PC() @ resolve() could throw 2594 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2595 bl dvmResolveInstField @ r0<- resolved InstField ptr 2596 cmp r0, #0 2597 bne .LOP_IGET_SHORT_finish 2598 b common_exceptionThrown 2599 2600 2601/* ------------------------------ */ 2602 .balign 64 2603.L_OP_IPUT: /* 0x59 */ 2604/* File: armv6t2/OP_IPUT.S */ 2605 /* 2606 * General 32-bit instance field put. 2607 * 2608 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2609 */ 2610 /* op vA, vB, field@CCCC */ 2611 mov r0, rINST, lsr #12 @ r0<- B 2612 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2613 FETCH(r1, 1) @ r1<- field ref CCCC 2614 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2615 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2616 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2617 cmp r0, #0 @ is resolved entry null? 2618 bne .LOP_IPUT_finish @ no, already resolved 26198: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2620 EXPORT_PC() @ resolve() could throw 2621 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2622 bl dvmResolveInstField @ r0<- resolved InstField ptr 2623 cmp r0, #0 @ success? 2624 bne .LOP_IPUT_finish @ yes, finish up 2625 b common_exceptionThrown 2626 2627/* ------------------------------ */ 2628 .balign 64 2629.L_OP_IPUT_WIDE: /* 0x5a */ 2630/* File: armv6t2/OP_IPUT_WIDE.S */ 2631 /* iput-wide vA, vB, field@CCCC */ 2632 mov r0, rINST, lsr #12 @ r0<- B 2633 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2634 FETCH(r1, 1) @ r1<- field ref CCCC 2635 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2636 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2637 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2638 cmp r0, #0 @ is resolved entry null? 2639 bne .LOP_IPUT_WIDE_finish @ no, already resolved 26408: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2641 EXPORT_PC() @ resolve() could throw 2642 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2643 bl dvmResolveInstField @ r0<- resolved InstField ptr 2644 cmp r0, #0 @ success? 2645 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2646 b common_exceptionThrown 2647 2648/* ------------------------------ */ 2649 .balign 64 2650.L_OP_IPUT_OBJECT: /* 0x5b */ 2651/* File: armv5te/OP_IPUT_OBJECT.S */ 2652 /* 2653 * 32-bit instance field put. 2654 * 2655 * for: iput-object, iput-object-volatile 2656 */ 2657 /* op vA, vB, field@CCCC */ 2658 mov r0, rINST, lsr #12 @ r0<- B 2659 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2660 FETCH(r1, 1) @ r1<- field ref CCCC 2661 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2662 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2663 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2664 cmp r0, #0 @ is resolved entry null? 2665 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 26668: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2667 EXPORT_PC() @ resolve() could throw 2668 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2669 bl dvmResolveInstField @ r0<- resolved InstField ptr 2670 cmp r0, #0 @ success? 2671 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2672 b common_exceptionThrown 2673 2674/* ------------------------------ */ 2675 .balign 64 2676.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2677/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2678@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2679/* File: armv5te/OP_IPUT.S */ 2680 /* 2681 * General 32-bit instance field put. 2682 * 2683 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2684 */ 2685 /* op vA, vB, field@CCCC */ 2686 mov r0, rINST, lsr #12 @ r0<- B 2687 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2688 FETCH(r1, 1) @ r1<- field ref CCCC 2689 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2690 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2691 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2692 cmp r0, #0 @ is resolved entry null? 2693 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 26948: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2695 EXPORT_PC() @ resolve() could throw 2696 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2697 bl dvmResolveInstField @ r0<- resolved InstField ptr 2698 cmp r0, #0 @ success? 2699 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2700 b common_exceptionThrown 2701 2702 2703/* ------------------------------ */ 2704 .balign 64 2705.L_OP_IPUT_BYTE: /* 0x5d */ 2706/* File: armv5te/OP_IPUT_BYTE.S */ 2707@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2708/* File: armv5te/OP_IPUT.S */ 2709 /* 2710 * General 32-bit instance field put. 2711 * 2712 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2713 */ 2714 /* op vA, vB, field@CCCC */ 2715 mov r0, rINST, lsr #12 @ r0<- B 2716 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2717 FETCH(r1, 1) @ r1<- field ref CCCC 2718 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2719 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2720 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2721 cmp r0, #0 @ is resolved entry null? 2722 bne .LOP_IPUT_BYTE_finish @ no, already resolved 27238: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2724 EXPORT_PC() @ resolve() could throw 2725 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2726 bl dvmResolveInstField @ r0<- resolved InstField ptr 2727 cmp r0, #0 @ success? 2728 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2729 b common_exceptionThrown 2730 2731 2732/* ------------------------------ */ 2733 .balign 64 2734.L_OP_IPUT_CHAR: /* 0x5e */ 2735/* File: armv5te/OP_IPUT_CHAR.S */ 2736@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2737/* File: armv5te/OP_IPUT.S */ 2738 /* 2739 * General 32-bit instance field put. 2740 * 2741 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2742 */ 2743 /* op vA, vB, field@CCCC */ 2744 mov r0, rINST, lsr #12 @ r0<- B 2745 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2746 FETCH(r1, 1) @ r1<- field ref CCCC 2747 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2748 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2749 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2750 cmp r0, #0 @ is resolved entry null? 2751 bne .LOP_IPUT_CHAR_finish @ no, already resolved 27528: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2753 EXPORT_PC() @ resolve() could throw 2754 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2755 bl dvmResolveInstField @ r0<- resolved InstField ptr 2756 cmp r0, #0 @ success? 2757 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2758 b common_exceptionThrown 2759 2760 2761/* ------------------------------ */ 2762 .balign 64 2763.L_OP_IPUT_SHORT: /* 0x5f */ 2764/* File: armv5te/OP_IPUT_SHORT.S */ 2765@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2766/* File: armv5te/OP_IPUT.S */ 2767 /* 2768 * General 32-bit instance field put. 2769 * 2770 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2771 */ 2772 /* op vA, vB, field@CCCC */ 2773 mov r0, rINST, lsr #12 @ r0<- B 2774 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2775 FETCH(r1, 1) @ r1<- field ref CCCC 2776 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2777 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2778 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2779 cmp r0, #0 @ is resolved entry null? 2780 bne .LOP_IPUT_SHORT_finish @ no, already resolved 27818: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2782 EXPORT_PC() @ resolve() could throw 2783 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2784 bl dvmResolveInstField @ r0<- resolved InstField ptr 2785 cmp r0, #0 @ success? 2786 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2787 b common_exceptionThrown 2788 2789 2790/* ------------------------------ */ 2791 .balign 64 2792.L_OP_SGET: /* 0x60 */ 2793/* File: armv5te/OP_SGET.S */ 2794 /* 2795 * General 32-bit SGET handler. 2796 * 2797 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2798 */ 2799 /* op vAA, field@BBBB */ 2800 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2801 FETCH(r1, 1) @ r1<- field ref BBBB 2802 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2803 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2804 cmp r0, #0 @ is resolved entry null? 2805 beq .LOP_SGET_resolve @ yes, do resolve 2806.LOP_SGET_finish: @ field ptr in r0 2807 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2808 @ no-op @ acquiring load 2809 mov r2, rINST, lsr #8 @ r2<- AA 2810 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2811 SET_VREG(r1, r2) @ fp[AA]<- r1 2812 GET_INST_OPCODE(ip) @ extract opcode from rINST 2813 GOTO_OPCODE(ip) @ jump to next instruction 2814 2815/* ------------------------------ */ 2816 .balign 64 2817.L_OP_SGET_WIDE: /* 0x61 */ 2818/* File: armv5te/OP_SGET_WIDE.S */ 2819 /* 2820 * 64-bit SGET handler. 2821 */ 2822 /* sget-wide vAA, field@BBBB */ 2823 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2824 FETCH(r1, 1) @ r1<- field ref BBBB 2825 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2826 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2827 cmp r0, #0 @ is resolved entry null? 2828 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2829.LOP_SGET_WIDE_finish: 2830 mov r9, rINST, lsr #8 @ r9<- AA 2831 .if 0 2832 add r0, r0, #offStaticField_value @ r0<- pointer to data 2833 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 2834 .else 2835 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 2836 .endif 2837 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2838 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2839 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 2840 GET_INST_OPCODE(ip) @ extract opcode from rINST 2841 GOTO_OPCODE(ip) @ jump to next instruction 2842 2843/* ------------------------------ */ 2844 .balign 64 2845.L_OP_SGET_OBJECT: /* 0x62 */ 2846/* File: armv5te/OP_SGET_OBJECT.S */ 2847/* File: armv5te/OP_SGET.S */ 2848 /* 2849 * General 32-bit SGET handler. 2850 * 2851 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2852 */ 2853 /* op vAA, field@BBBB */ 2854 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2855 FETCH(r1, 1) @ r1<- field ref BBBB 2856 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2857 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2858 cmp r0, #0 @ is resolved entry null? 2859 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2860.LOP_SGET_OBJECT_finish: @ field ptr in r0 2861 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2862 @ no-op @ acquiring load 2863 mov r2, rINST, lsr #8 @ r2<- AA 2864 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2865 SET_VREG(r1, r2) @ fp[AA]<- r1 2866 GET_INST_OPCODE(ip) @ extract opcode from rINST 2867 GOTO_OPCODE(ip) @ jump to next instruction 2868 2869 2870/* ------------------------------ */ 2871 .balign 64 2872.L_OP_SGET_BOOLEAN: /* 0x63 */ 2873/* File: armv5te/OP_SGET_BOOLEAN.S */ 2874/* File: armv5te/OP_SGET.S */ 2875 /* 2876 * General 32-bit SGET handler. 2877 * 2878 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2879 */ 2880 /* op vAA, field@BBBB */ 2881 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2882 FETCH(r1, 1) @ r1<- field ref BBBB 2883 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2884 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2885 cmp r0, #0 @ is resolved entry null? 2886 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2887.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2888 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2889 @ no-op @ acquiring load 2890 mov r2, rINST, lsr #8 @ r2<- AA 2891 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2892 SET_VREG(r1, r2) @ fp[AA]<- r1 2893 GET_INST_OPCODE(ip) @ extract opcode from rINST 2894 GOTO_OPCODE(ip) @ jump to next instruction 2895 2896 2897/* ------------------------------ */ 2898 .balign 64 2899.L_OP_SGET_BYTE: /* 0x64 */ 2900/* File: armv5te/OP_SGET_BYTE.S */ 2901/* File: armv5te/OP_SGET.S */ 2902 /* 2903 * General 32-bit SGET handler. 2904 * 2905 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2906 */ 2907 /* op vAA, field@BBBB */ 2908 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2909 FETCH(r1, 1) @ r1<- field ref BBBB 2910 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2911 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2912 cmp r0, #0 @ is resolved entry null? 2913 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2914.LOP_SGET_BYTE_finish: @ field ptr in r0 2915 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2916 @ no-op @ acquiring load 2917 mov r2, rINST, lsr #8 @ r2<- AA 2918 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2919 SET_VREG(r1, r2) @ fp[AA]<- r1 2920 GET_INST_OPCODE(ip) @ extract opcode from rINST 2921 GOTO_OPCODE(ip) @ jump to next instruction 2922 2923 2924/* ------------------------------ */ 2925 .balign 64 2926.L_OP_SGET_CHAR: /* 0x65 */ 2927/* File: armv5te/OP_SGET_CHAR.S */ 2928/* File: armv5te/OP_SGET.S */ 2929 /* 2930 * General 32-bit SGET handler. 2931 * 2932 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2933 */ 2934 /* op vAA, field@BBBB */ 2935 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2936 FETCH(r1, 1) @ r1<- field ref BBBB 2937 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2938 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2939 cmp r0, #0 @ is resolved entry null? 2940 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2941.LOP_SGET_CHAR_finish: @ field ptr in r0 2942 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2943 @ no-op @ acquiring load 2944 mov r2, rINST, lsr #8 @ r2<- AA 2945 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2946 SET_VREG(r1, r2) @ fp[AA]<- r1 2947 GET_INST_OPCODE(ip) @ extract opcode from rINST 2948 GOTO_OPCODE(ip) @ jump to next instruction 2949 2950 2951/* ------------------------------ */ 2952 .balign 64 2953.L_OP_SGET_SHORT: /* 0x66 */ 2954/* File: armv5te/OP_SGET_SHORT.S */ 2955/* File: armv5te/OP_SGET.S */ 2956 /* 2957 * General 32-bit SGET handler. 2958 * 2959 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2960 */ 2961 /* op vAA, field@BBBB */ 2962 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2963 FETCH(r1, 1) @ r1<- field ref BBBB 2964 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2965 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2966 cmp r0, #0 @ is resolved entry null? 2967 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 2968.LOP_SGET_SHORT_finish: @ field ptr in r0 2969 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2970 @ no-op @ acquiring load 2971 mov r2, rINST, lsr #8 @ r2<- AA 2972 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2973 SET_VREG(r1, r2) @ fp[AA]<- r1 2974 GET_INST_OPCODE(ip) @ extract opcode from rINST 2975 GOTO_OPCODE(ip) @ jump to next instruction 2976 2977 2978/* ------------------------------ */ 2979 .balign 64 2980.L_OP_SPUT: /* 0x67 */ 2981/* File: armv5te/OP_SPUT.S */ 2982 /* 2983 * General 32-bit SPUT handler. 2984 * 2985 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 2986 */ 2987 /* op vAA, field@BBBB */ 2988 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2989 FETCH(r1, 1) @ r1<- field ref BBBB 2990 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2991 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2992 cmp r0, #0 @ is resolved entry null? 2993 beq .LOP_SPUT_resolve @ yes, do resolve 2994.LOP_SPUT_finish: @ field ptr in r0 2995 mov r2, rINST, lsr #8 @ r2<- AA 2996 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2997 GET_VREG(r1, r2) @ r1<- fp[AA] 2998 GET_INST_OPCODE(ip) @ extract opcode from rINST 2999 @ no-op @ releasing store 3000 str r1, [r0, #offStaticField_value] @ field<- vAA 3001 GOTO_OPCODE(ip) @ jump to next instruction 3002 3003/* ------------------------------ */ 3004 .balign 64 3005.L_OP_SPUT_WIDE: /* 0x68 */ 3006/* File: armv5te/OP_SPUT_WIDE.S */ 3007 /* 3008 * 64-bit SPUT handler. 3009 */ 3010 /* sput-wide vAA, field@BBBB */ 3011 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 3012 FETCH(r1, 1) @ r1<- field ref BBBB 3013 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 3014 mov r9, rINST, lsr #8 @ r9<- AA 3015 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 3016 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 3017 cmp r2, #0 @ is resolved entry null? 3018 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 3019.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9 3020 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3021 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 3022 GET_INST_OPCODE(r10) @ extract opcode from rINST 3023 .if 0 3024 add r2, r2, #offStaticField_value @ r2<- pointer to data 3025 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 3026 .else 3027 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 3028 .endif 3029 GOTO_OPCODE(r10) @ jump to next instruction 3030 3031/* ------------------------------ */ 3032 .balign 64 3033.L_OP_SPUT_OBJECT: /* 0x69 */ 3034/* File: armv5te/OP_SPUT_OBJECT.S */ 3035 /* 3036 * 32-bit SPUT handler for objects 3037 * 3038 * for: sput-object, sput-object-volatile 3039 */ 3040 /* op vAA, field@BBBB */ 3041 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3042 FETCH(r1, 1) @ r1<- field ref BBBB 3043 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3044 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3045 cmp r0, #0 @ is resolved entry null? 3046 bne .LOP_SPUT_OBJECT_finish @ no, continue 3047 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 3048 EXPORT_PC() @ resolve() could throw, so export now 3049 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 3050 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 3051 cmp r0, #0 @ success? 3052 bne .LOP_SPUT_OBJECT_finish @ yes, finish 3053 b common_exceptionThrown @ no, handle exception 3054 3055 3056/* ------------------------------ */ 3057 .balign 64 3058.L_OP_SPUT_BOOLEAN: /* 0x6a */ 3059/* File: armv5te/OP_SPUT_BOOLEAN.S */ 3060/* File: armv5te/OP_SPUT.S */ 3061 /* 3062 * General 32-bit SPUT handler. 3063 * 3064 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3065 */ 3066 /* op vAA, field@BBBB */ 3067 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3068 FETCH(r1, 1) @ r1<- field ref BBBB 3069 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3070 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3071 cmp r0, #0 @ is resolved entry null? 3072 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 3073.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 3074 mov r2, rINST, lsr #8 @ r2<- AA 3075 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3076 GET_VREG(r1, r2) @ r1<- fp[AA] 3077 GET_INST_OPCODE(ip) @ extract opcode from rINST 3078 @ no-op @ releasing store 3079 str r1, [r0, #offStaticField_value] @ field<- vAA 3080 GOTO_OPCODE(ip) @ jump to next instruction 3081 3082 3083/* ------------------------------ */ 3084 .balign 64 3085.L_OP_SPUT_BYTE: /* 0x6b */ 3086/* File: armv5te/OP_SPUT_BYTE.S */ 3087/* File: armv5te/OP_SPUT.S */ 3088 /* 3089 * General 32-bit SPUT handler. 3090 * 3091 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3092 */ 3093 /* op vAA, field@BBBB */ 3094 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3095 FETCH(r1, 1) @ r1<- field ref BBBB 3096 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3097 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3098 cmp r0, #0 @ is resolved entry null? 3099 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 3100.LOP_SPUT_BYTE_finish: @ field ptr in r0 3101 mov r2, rINST, lsr #8 @ r2<- AA 3102 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3103 GET_VREG(r1, r2) @ r1<- fp[AA] 3104 GET_INST_OPCODE(ip) @ extract opcode from rINST 3105 @ no-op @ releasing store 3106 str r1, [r0, #offStaticField_value] @ field<- vAA 3107 GOTO_OPCODE(ip) @ jump to next instruction 3108 3109 3110/* ------------------------------ */ 3111 .balign 64 3112.L_OP_SPUT_CHAR: /* 0x6c */ 3113/* File: armv5te/OP_SPUT_CHAR.S */ 3114/* File: armv5te/OP_SPUT.S */ 3115 /* 3116 * General 32-bit SPUT handler. 3117 * 3118 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3119 */ 3120 /* op vAA, field@BBBB */ 3121 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3122 FETCH(r1, 1) @ r1<- field ref BBBB 3123 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3124 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3125 cmp r0, #0 @ is resolved entry null? 3126 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 3127.LOP_SPUT_CHAR_finish: @ field ptr in r0 3128 mov r2, rINST, lsr #8 @ r2<- AA 3129 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3130 GET_VREG(r1, r2) @ r1<- fp[AA] 3131 GET_INST_OPCODE(ip) @ extract opcode from rINST 3132 @ no-op @ releasing store 3133 str r1, [r0, #offStaticField_value] @ field<- vAA 3134 GOTO_OPCODE(ip) @ jump to next instruction 3135 3136 3137/* ------------------------------ */ 3138 .balign 64 3139.L_OP_SPUT_SHORT: /* 0x6d */ 3140/* File: armv5te/OP_SPUT_SHORT.S */ 3141/* File: armv5te/OP_SPUT.S */ 3142 /* 3143 * General 32-bit SPUT handler. 3144 * 3145 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3146 */ 3147 /* op vAA, field@BBBB */ 3148 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3149 FETCH(r1, 1) @ r1<- field ref BBBB 3150 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3151 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3152 cmp r0, #0 @ is resolved entry null? 3153 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 3154.LOP_SPUT_SHORT_finish: @ field ptr in r0 3155 mov r2, rINST, lsr #8 @ r2<- AA 3156 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3157 GET_VREG(r1, r2) @ r1<- fp[AA] 3158 GET_INST_OPCODE(ip) @ extract opcode from rINST 3159 @ no-op @ releasing store 3160 str r1, [r0, #offStaticField_value] @ field<- vAA 3161 GOTO_OPCODE(ip) @ jump to next instruction 3162 3163 3164/* ------------------------------ */ 3165 .balign 64 3166.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3167/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3168 /* 3169 * Handle a virtual method call. 3170 * 3171 * for: invoke-virtual, invoke-virtual/range 3172 */ 3173 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3174 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3175 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3176 FETCH(r1, 1) @ r1<- BBBB 3177 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3178 FETCH(r10, 2) @ r10<- GFED or CCCC 3179 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3180 .if (!0) 3181 and r10, r10, #15 @ r10<- D (or stays CCCC) 3182 .endif 3183 cmp r0, #0 @ already resolved? 3184 EXPORT_PC() @ must export for invoke 3185 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3186 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3187 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3188 mov r2, #METHOD_VIRTUAL @ resolver method type 3189 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3190 cmp r0, #0 @ got null? 3191 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3192 b common_exceptionThrown @ yes, handle exception 3193 3194/* ------------------------------ */ 3195 .balign 64 3196.L_OP_INVOKE_SUPER: /* 0x6f */ 3197/* File: armv5te/OP_INVOKE_SUPER.S */ 3198 /* 3199 * Handle a "super" method call. 3200 * 3201 * for: invoke-super, invoke-super/range 3202 */ 3203 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3204 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3205 FETCH(r10, 2) @ r10<- GFED or CCCC 3206 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3207 .if (!0) 3208 and r10, r10, #15 @ r10<- D (or stays CCCC) 3209 .endif 3210 FETCH(r1, 1) @ r1<- BBBB 3211 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3212 GET_VREG(r2, r10) @ r2<- "this" ptr 3213 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3214 cmp r2, #0 @ null "this"? 3215 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3216 beq common_errNullObject @ null "this", throw exception 3217 cmp r0, #0 @ already resolved? 3218 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3219 EXPORT_PC() @ must export for invoke 3220 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3221 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3222 3223/* ------------------------------ */ 3224 .balign 64 3225.L_OP_INVOKE_DIRECT: /* 0x70 */ 3226/* File: armv5te/OP_INVOKE_DIRECT.S */ 3227 /* 3228 * Handle a direct method call. 3229 * 3230 * (We could defer the "is 'this' pointer null" test to the common 3231 * method invocation code, and use a flag to indicate that static 3232 * calls don't count. If we do this as part of copying the arguments 3233 * out we could avoiding loading the first arg twice.) 3234 * 3235 * for: invoke-direct, invoke-direct/range 3236 */ 3237 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3238 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3239 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3240 FETCH(r1, 1) @ r1<- BBBB 3241 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3242 FETCH(r10, 2) @ r10<- GFED or CCCC 3243 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3244 .if (!0) 3245 and r10, r10, #15 @ r10<- D (or stays CCCC) 3246 .endif 3247 cmp r0, #0 @ already resolved? 3248 EXPORT_PC() @ must export for invoke 3249 GET_VREG(r2, r10) @ r2<- "this" ptr 3250 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3251.LOP_INVOKE_DIRECT_finish: 3252 cmp r2, #0 @ null "this" ref? 3253 bne common_invokeMethodNoRange @ no, continue on 3254 b common_errNullObject @ yes, throw exception 3255 3256/* ------------------------------ */ 3257 .balign 64 3258.L_OP_INVOKE_STATIC: /* 0x71 */ 3259/* File: armv5te/OP_INVOKE_STATIC.S */ 3260 /* 3261 * Handle a static method call. 3262 * 3263 * for: invoke-static, invoke-static/range 3264 */ 3265 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3266 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3267 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3268 FETCH(r1, 1) @ r1<- BBBB 3269 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3270 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3271 cmp r0, #0 @ already resolved? 3272 EXPORT_PC() @ must export for invoke 3273 bne common_invokeMethodNoRange @ yes, continue on 32740: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3275 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3276 mov r2, #METHOD_STATIC @ resolver method type 3277 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3278 cmp r0, #0 @ got null? 3279 bne common_invokeMethodNoRange @ no, continue 3280 b common_exceptionThrown @ yes, handle exception 3281 3282/* ------------------------------ */ 3283 .balign 64 3284.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3285/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3286 /* 3287 * Handle an interface method call. 3288 * 3289 * for: invoke-interface, invoke-interface/range 3290 */ 3291 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3292 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3293 FETCH(r2, 2) @ r2<- FEDC or CCCC 3294 FETCH(r1, 1) @ r1<- BBBB 3295 .if (!0) 3296 and r2, r2, #15 @ r2<- C (or stays CCCC) 3297 .endif 3298 EXPORT_PC() @ must export for invoke 3299 GET_VREG(r0, r2) @ r0<- first arg ("this") 3300 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3301 cmp r0, #0 @ null obj? 3302 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3303 beq common_errNullObject @ yes, fail 3304 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3305 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3306 cmp r0, #0 @ failed? 3307 beq common_exceptionThrown @ yes, handle exception 3308 b common_invokeMethodNoRange @ jump to common handler 3309 3310/* ------------------------------ */ 3311 .balign 64 3312.L_OP_UNUSED_73: /* 0x73 */ 3313/* File: armv5te/OP_UNUSED_73.S */ 3314/* File: armv5te/unused.S */ 3315 bl common_abort 3316 3317 3318/* ------------------------------ */ 3319 .balign 64 3320.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3321/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3322/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3323 /* 3324 * Handle a virtual method call. 3325 * 3326 * for: invoke-virtual, invoke-virtual/range 3327 */ 3328 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3329 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3330 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3331 FETCH(r1, 1) @ r1<- BBBB 3332 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3333 FETCH(r10, 2) @ r10<- GFED or CCCC 3334 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3335 .if (!1) 3336 and r10, r10, #15 @ r10<- D (or stays CCCC) 3337 .endif 3338 cmp r0, #0 @ already resolved? 3339 EXPORT_PC() @ must export for invoke 3340 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3341 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3342 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3343 mov r2, #METHOD_VIRTUAL @ resolver method type 3344 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3345 cmp r0, #0 @ got null? 3346 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3347 b common_exceptionThrown @ yes, handle exception 3348 3349 3350/* ------------------------------ */ 3351 .balign 64 3352.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3353/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3354/* File: armv5te/OP_INVOKE_SUPER.S */ 3355 /* 3356 * Handle a "super" method call. 3357 * 3358 * for: invoke-super, invoke-super/range 3359 */ 3360 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3361 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3362 FETCH(r10, 2) @ r10<- GFED or CCCC 3363 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3364 .if (!1) 3365 and r10, r10, #15 @ r10<- D (or stays CCCC) 3366 .endif 3367 FETCH(r1, 1) @ r1<- BBBB 3368 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3369 GET_VREG(r2, r10) @ r2<- "this" ptr 3370 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3371 cmp r2, #0 @ null "this"? 3372 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3373 beq common_errNullObject @ null "this", throw exception 3374 cmp r0, #0 @ already resolved? 3375 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3376 EXPORT_PC() @ must export for invoke 3377 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3378 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3379 3380 3381/* ------------------------------ */ 3382 .balign 64 3383.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3384/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3385/* File: armv5te/OP_INVOKE_DIRECT.S */ 3386 /* 3387 * Handle a direct method call. 3388 * 3389 * (We could defer the "is 'this' pointer null" test to the common 3390 * method invocation code, and use a flag to indicate that static 3391 * calls don't count. If we do this as part of copying the arguments 3392 * out we could avoiding loading the first arg twice.) 3393 * 3394 * for: invoke-direct, invoke-direct/range 3395 */ 3396 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3397 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3398 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3399 FETCH(r1, 1) @ r1<- BBBB 3400 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3401 FETCH(r10, 2) @ r10<- GFED or CCCC 3402 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3403 .if (!1) 3404 and r10, r10, #15 @ r10<- D (or stays CCCC) 3405 .endif 3406 cmp r0, #0 @ already resolved? 3407 EXPORT_PC() @ must export for invoke 3408 GET_VREG(r2, r10) @ r2<- "this" ptr 3409 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3410.LOP_INVOKE_DIRECT_RANGE_finish: 3411 cmp r2, #0 @ null "this" ref? 3412 bne common_invokeMethodRange @ no, continue on 3413 b common_errNullObject @ yes, throw exception 3414 3415 3416/* ------------------------------ */ 3417 .balign 64 3418.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3419/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3420/* File: armv5te/OP_INVOKE_STATIC.S */ 3421 /* 3422 * Handle a static method call. 3423 * 3424 * for: invoke-static, invoke-static/range 3425 */ 3426 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3427 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3428 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3429 FETCH(r1, 1) @ r1<- BBBB 3430 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3431 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3432 cmp r0, #0 @ already resolved? 3433 EXPORT_PC() @ must export for invoke 3434 bne common_invokeMethodRange @ yes, continue on 34350: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3436 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3437 mov r2, #METHOD_STATIC @ resolver method type 3438 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3439 cmp r0, #0 @ got null? 3440 bne common_invokeMethodRange @ no, continue 3441 b common_exceptionThrown @ yes, handle exception 3442 3443 3444/* ------------------------------ */ 3445 .balign 64 3446.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3447/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3448/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3449 /* 3450 * Handle an interface method call. 3451 * 3452 * for: invoke-interface, invoke-interface/range 3453 */ 3454 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3455 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3456 FETCH(r2, 2) @ r2<- FEDC or CCCC 3457 FETCH(r1, 1) @ r1<- BBBB 3458 .if (!1) 3459 and r2, r2, #15 @ r2<- C (or stays CCCC) 3460 .endif 3461 EXPORT_PC() @ must export for invoke 3462 GET_VREG(r0, r2) @ r0<- first arg ("this") 3463 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3464 cmp r0, #0 @ null obj? 3465 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3466 beq common_errNullObject @ yes, fail 3467 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3468 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3469 cmp r0, #0 @ failed? 3470 beq common_exceptionThrown @ yes, handle exception 3471 b common_invokeMethodRange @ jump to common handler 3472 3473 3474/* ------------------------------ */ 3475 .balign 64 3476.L_OP_UNUSED_79: /* 0x79 */ 3477/* File: armv5te/OP_UNUSED_79.S */ 3478/* File: armv5te/unused.S */ 3479 bl common_abort 3480 3481 3482/* ------------------------------ */ 3483 .balign 64 3484.L_OP_UNUSED_7A: /* 0x7a */ 3485/* File: armv5te/OP_UNUSED_7A.S */ 3486/* File: armv5te/unused.S */ 3487 bl common_abort 3488 3489 3490/* ------------------------------ */ 3491 .balign 64 3492.L_OP_NEG_INT: /* 0x7b */ 3493/* File: armv6t2/OP_NEG_INT.S */ 3494/* File: armv6t2/unop.S */ 3495 /* 3496 * Generic 32-bit unary operation. Provide an "instr" line that 3497 * specifies an instruction that performs "result = op r0". 3498 * This could be an ARM instruction or a function call. 3499 * 3500 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3501 * int-to-byte, int-to-char, int-to-short 3502 */ 3503 /* unop vA, vB */ 3504 mov r3, rINST, lsr #12 @ r3<- B 3505 ubfx r9, rINST, #8, #4 @ r9<- A 3506 GET_VREG(r0, r3) @ r0<- vB 3507 @ optional op; may set condition codes 3508 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3509 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3510 GET_INST_OPCODE(ip) @ extract opcode from rINST 3511 SET_VREG(r0, r9) @ vAA<- r0 3512 GOTO_OPCODE(ip) @ jump to next instruction 3513 /* 8-9 instructions */ 3514 3515 3516/* ------------------------------ */ 3517 .balign 64 3518.L_OP_NOT_INT: /* 0x7c */ 3519/* File: armv6t2/OP_NOT_INT.S */ 3520/* File: armv6t2/unop.S */ 3521 /* 3522 * Generic 32-bit unary operation. Provide an "instr" line that 3523 * specifies an instruction that performs "result = op r0". 3524 * This could be an ARM instruction or a function call. 3525 * 3526 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3527 * int-to-byte, int-to-char, int-to-short 3528 */ 3529 /* unop vA, vB */ 3530 mov r3, rINST, lsr #12 @ r3<- B 3531 ubfx r9, rINST, #8, #4 @ r9<- A 3532 GET_VREG(r0, r3) @ r0<- vB 3533 @ optional op; may set condition codes 3534 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3535 mvn r0, r0 @ r0<- op, r0-r3 changed 3536 GET_INST_OPCODE(ip) @ extract opcode from rINST 3537 SET_VREG(r0, r9) @ vAA<- r0 3538 GOTO_OPCODE(ip) @ jump to next instruction 3539 /* 8-9 instructions */ 3540 3541 3542/* ------------------------------ */ 3543 .balign 64 3544.L_OP_NEG_LONG: /* 0x7d */ 3545/* File: armv6t2/OP_NEG_LONG.S */ 3546/* File: armv6t2/unopWide.S */ 3547 /* 3548 * Generic 64-bit unary operation. Provide an "instr" line that 3549 * specifies an instruction that performs "result = op r0/r1". 3550 * This could be an ARM instruction or a function call. 3551 * 3552 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3553 */ 3554 /* unop vA, vB */ 3555 mov r3, rINST, lsr #12 @ r3<- B 3556 ubfx r9, rINST, #8, #4 @ r9<- A 3557 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3558 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3559 ldmia r3, {r0-r1} @ r0/r1<- vAA 3560 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3561 rsbs r0, r0, #0 @ optional op; may set condition codes 3562 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3563 GET_INST_OPCODE(ip) @ extract opcode from rINST 3564 stmia r9, {r0-r1} @ vAA<- r0/r1 3565 GOTO_OPCODE(ip) @ jump to next instruction 3566 /* 10-11 instructions */ 3567 3568 3569/* ------------------------------ */ 3570 .balign 64 3571.L_OP_NOT_LONG: /* 0x7e */ 3572/* File: armv6t2/OP_NOT_LONG.S */ 3573/* File: armv6t2/unopWide.S */ 3574 /* 3575 * Generic 64-bit unary operation. Provide an "instr" line that 3576 * specifies an instruction that performs "result = op r0/r1". 3577 * This could be an ARM instruction or a function call. 3578 * 3579 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3580 */ 3581 /* unop vA, vB */ 3582 mov r3, rINST, lsr #12 @ r3<- B 3583 ubfx r9, rINST, #8, #4 @ r9<- A 3584 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3585 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3586 ldmia r3, {r0-r1} @ r0/r1<- vAA 3587 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3588 mvn r0, r0 @ optional op; may set condition codes 3589 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3590 GET_INST_OPCODE(ip) @ extract opcode from rINST 3591 stmia r9, {r0-r1} @ vAA<- r0/r1 3592 GOTO_OPCODE(ip) @ jump to next instruction 3593 /* 10-11 instructions */ 3594 3595 3596/* ------------------------------ */ 3597 .balign 64 3598.L_OP_NEG_FLOAT: /* 0x7f */ 3599/* File: armv6t2/OP_NEG_FLOAT.S */ 3600/* File: armv6t2/unop.S */ 3601 /* 3602 * Generic 32-bit unary operation. Provide an "instr" line that 3603 * specifies an instruction that performs "result = op r0". 3604 * This could be an ARM instruction or a function call. 3605 * 3606 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3607 * int-to-byte, int-to-char, int-to-short 3608 */ 3609 /* unop vA, vB */ 3610 mov r3, rINST, lsr #12 @ r3<- B 3611 ubfx r9, rINST, #8, #4 @ r9<- A 3612 GET_VREG(r0, r3) @ r0<- vB 3613 @ optional op; may set condition codes 3614 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3615 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3616 GET_INST_OPCODE(ip) @ extract opcode from rINST 3617 SET_VREG(r0, r9) @ vAA<- r0 3618 GOTO_OPCODE(ip) @ jump to next instruction 3619 /* 8-9 instructions */ 3620 3621 3622/* ------------------------------ */ 3623 .balign 64 3624.L_OP_NEG_DOUBLE: /* 0x80 */ 3625/* File: armv6t2/OP_NEG_DOUBLE.S */ 3626/* File: armv6t2/unopWide.S */ 3627 /* 3628 * Generic 64-bit unary operation. Provide an "instr" line that 3629 * specifies an instruction that performs "result = op r0/r1". 3630 * This could be an ARM instruction or a function call. 3631 * 3632 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3633 */ 3634 /* unop vA, vB */ 3635 mov r3, rINST, lsr #12 @ r3<- B 3636 ubfx r9, rINST, #8, #4 @ r9<- A 3637 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3638 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3639 ldmia r3, {r0-r1} @ r0/r1<- vAA 3640 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3641 @ optional op; may set condition codes 3642 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3643 GET_INST_OPCODE(ip) @ extract opcode from rINST 3644 stmia r9, {r0-r1} @ vAA<- r0/r1 3645 GOTO_OPCODE(ip) @ jump to next instruction 3646 /* 10-11 instructions */ 3647 3648 3649/* ------------------------------ */ 3650 .balign 64 3651.L_OP_INT_TO_LONG: /* 0x81 */ 3652/* File: armv6t2/OP_INT_TO_LONG.S */ 3653/* File: armv6t2/unopWider.S */ 3654 /* 3655 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3656 * that specifies an instruction that performs "result = op r0", where 3657 * "result" is a 64-bit quantity in r0/r1. 3658 * 3659 * For: int-to-long, int-to-double, float-to-long, float-to-double 3660 */ 3661 /* unop vA, vB */ 3662 mov r3, rINST, lsr #12 @ r3<- B 3663 ubfx r9, rINST, #8, #4 @ r9<- A 3664 GET_VREG(r0, r3) @ r0<- vB 3665 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3666 @ optional op; may set condition codes 3667 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3668 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3669 GET_INST_OPCODE(ip) @ extract opcode from rINST 3670 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3671 GOTO_OPCODE(ip) @ jump to next instruction 3672 /* 9-10 instructions */ 3673 3674 3675/* ------------------------------ */ 3676 .balign 64 3677.L_OP_INT_TO_FLOAT: /* 0x82 */ 3678/* File: arm-vfp/OP_INT_TO_FLOAT.S */ 3679/* File: arm-vfp/funop.S */ 3680 /* 3681 * Generic 32-bit unary floating-point operation. Provide an "instr" 3682 * line that specifies an instruction that performs "s1 = op s0". 3683 * 3684 * for: int-to-float, float-to-int 3685 */ 3686 /* unop vA, vB */ 3687 mov r3, rINST, lsr #12 @ r3<- B 3688 mov r9, rINST, lsr #8 @ r9<- A+ 3689 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3690 flds s0, [r3] @ s0<- vB 3691 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3692 and r9, r9, #15 @ r9<- A 3693 fsitos s1, s0 @ s1<- op 3694 GET_INST_OPCODE(ip) @ extract opcode from rINST 3695 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3696 fsts s1, [r9] @ vA<- s1 3697 GOTO_OPCODE(ip) @ jump to next instruction 3698 3699 3700/* ------------------------------ */ 3701 .balign 64 3702.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3703/* File: arm-vfp/OP_INT_TO_DOUBLE.S */ 3704/* File: arm-vfp/funopWider.S */ 3705 /* 3706 * Generic 32bit-to-64bit floating point unary operation. Provide an 3707 * "instr" line that specifies an instruction that performs "d0 = op s0". 3708 * 3709 * For: int-to-double, float-to-double 3710 */ 3711 /* unop vA, vB */ 3712 mov r3, rINST, lsr #12 @ r3<- B 3713 mov r9, rINST, lsr #8 @ r9<- A+ 3714 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3715 flds s0, [r3] @ s0<- vB 3716 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3717 and r9, r9, #15 @ r9<- A 3718 fsitod d0, s0 @ d0<- op 3719 GET_INST_OPCODE(ip) @ extract opcode from rINST 3720 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3721 fstd d0, [r9] @ vA<- d0 3722 GOTO_OPCODE(ip) @ jump to next instruction 3723 3724 3725/* ------------------------------ */ 3726 .balign 64 3727.L_OP_LONG_TO_INT: /* 0x84 */ 3728/* File: armv5te/OP_LONG_TO_INT.S */ 3729/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3730/* File: armv5te/OP_MOVE.S */ 3731 /* for move, move-object, long-to-int */ 3732 /* op vA, vB */ 3733 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3734 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3735 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3736 GET_VREG(r2, r1) @ r2<- fp[B] 3737 and r0, r0, #15 3738 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3739 SET_VREG(r2, r0) @ fp[A]<- r2 3740 GOTO_OPCODE(ip) @ execute next instruction 3741 3742 3743/* ------------------------------ */ 3744 .balign 64 3745.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3746/* File: armv6t2/OP_LONG_TO_FLOAT.S */ 3747/* File: armv6t2/unopNarrower.S */ 3748 /* 3749 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3750 * that specifies an instruction that performs "result = op r0/r1", where 3751 * "result" is a 32-bit quantity in r0. 3752 * 3753 * For: long-to-float, double-to-int, double-to-float 3754 * 3755 * (This would work for long-to-int, but that instruction is actually 3756 * an exact match for OP_MOVE.) 3757 */ 3758 /* unop vA, vB */ 3759 mov r3, rINST, lsr #12 @ r3<- B 3760 ubfx r9, rINST, #8, #4 @ r9<- A 3761 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3762 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3763 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3764 @ optional op; may set condition codes 3765 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3766 GET_INST_OPCODE(ip) @ extract opcode from rINST 3767 SET_VREG(r0, r9) @ vA<- r0 3768 GOTO_OPCODE(ip) @ jump to next instruction 3769 /* 9-10 instructions */ 3770 3771 3772/* ------------------------------ */ 3773 .balign 64 3774.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3775/* File: armv6t2/OP_LONG_TO_DOUBLE.S */ 3776/* File: armv6t2/unopWide.S */ 3777 /* 3778 * Generic 64-bit unary operation. Provide an "instr" line that 3779 * specifies an instruction that performs "result = op r0/r1". 3780 * This could be an ARM instruction or a function call. 3781 * 3782 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3783 */ 3784 /* unop vA, vB */ 3785 mov r3, rINST, lsr #12 @ r3<- B 3786 ubfx r9, rINST, #8, #4 @ r9<- A 3787 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3788 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3789 ldmia r3, {r0-r1} @ r0/r1<- vAA 3790 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3791 @ optional op; may set condition codes 3792 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3793 GET_INST_OPCODE(ip) @ extract opcode from rINST 3794 stmia r9, {r0-r1} @ vAA<- r0/r1 3795 GOTO_OPCODE(ip) @ jump to next instruction 3796 /* 10-11 instructions */ 3797 3798 3799/* ------------------------------ */ 3800 .balign 64 3801.L_OP_FLOAT_TO_INT: /* 0x87 */ 3802/* File: arm-vfp/OP_FLOAT_TO_INT.S */ 3803/* File: arm-vfp/funop.S */ 3804 /* 3805 * Generic 32-bit unary floating-point operation. Provide an "instr" 3806 * line that specifies an instruction that performs "s1 = op s0". 3807 * 3808 * for: int-to-float, float-to-int 3809 */ 3810 /* unop vA, vB */ 3811 mov r3, rINST, lsr #12 @ r3<- B 3812 mov r9, rINST, lsr #8 @ r9<- A+ 3813 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3814 flds s0, [r3] @ s0<- vB 3815 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3816 and r9, r9, #15 @ r9<- A 3817 ftosizs s1, s0 @ s1<- op 3818 GET_INST_OPCODE(ip) @ extract opcode from rINST 3819 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3820 fsts s1, [r9] @ vA<- s1 3821 GOTO_OPCODE(ip) @ jump to next instruction 3822 3823 3824/* ------------------------------ */ 3825 .balign 64 3826.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3827/* File: armv6t2/OP_FLOAT_TO_LONG.S */ 3828@include "armv6t2/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3829/* File: armv6t2/unopWider.S */ 3830 /* 3831 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3832 * that specifies an instruction that performs "result = op r0", where 3833 * "result" is a 64-bit quantity in r0/r1. 3834 * 3835 * For: int-to-long, int-to-double, float-to-long, float-to-double 3836 */ 3837 /* unop vA, vB */ 3838 mov r3, rINST, lsr #12 @ r3<- B 3839 ubfx r9, rINST, #8, #4 @ r9<- A 3840 GET_VREG(r0, r3) @ r0<- vB 3841 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3842 @ optional op; may set condition codes 3843 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3844 bl f2l_doconv @ r0<- op, r0-r3 changed 3845 GET_INST_OPCODE(ip) @ extract opcode from rINST 3846 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3847 GOTO_OPCODE(ip) @ jump to next instruction 3848 /* 9-10 instructions */ 3849 3850 3851 3852/* ------------------------------ */ 3853 .balign 64 3854.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3855/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */ 3856/* File: arm-vfp/funopWider.S */ 3857 /* 3858 * Generic 32bit-to-64bit floating point unary operation. Provide an 3859 * "instr" line that specifies an instruction that performs "d0 = op s0". 3860 * 3861 * For: int-to-double, float-to-double 3862 */ 3863 /* unop vA, vB */ 3864 mov r3, rINST, lsr #12 @ r3<- B 3865 mov r9, rINST, lsr #8 @ r9<- A+ 3866 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3867 flds s0, [r3] @ s0<- vB 3868 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3869 and r9, r9, #15 @ r9<- A 3870 fcvtds d0, s0 @ d0<- op 3871 GET_INST_OPCODE(ip) @ extract opcode from rINST 3872 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3873 fstd d0, [r9] @ vA<- d0 3874 GOTO_OPCODE(ip) @ jump to next instruction 3875 3876 3877/* ------------------------------ */ 3878 .balign 64 3879.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3880/* File: arm-vfp/OP_DOUBLE_TO_INT.S */ 3881/* File: arm-vfp/funopNarrower.S */ 3882 /* 3883 * Generic 64bit-to-32bit unary floating point operation. Provide an 3884 * "instr" line that specifies an instruction that performs "s0 = op d0". 3885 * 3886 * For: double-to-int, double-to-float 3887 */ 3888 /* unop vA, vB */ 3889 mov r3, rINST, lsr #12 @ r3<- B 3890 mov r9, rINST, lsr #8 @ r9<- A+ 3891 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3892 fldd d0, [r3] @ d0<- vB 3893 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3894 and r9, r9, #15 @ r9<- A 3895 ftosizd s0, d0 @ s0<- op 3896 GET_INST_OPCODE(ip) @ extract opcode from rINST 3897 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3898 fsts s0, [r9] @ vA<- s0 3899 GOTO_OPCODE(ip) @ jump to next instruction 3900 3901 3902/* ------------------------------ */ 3903 .balign 64 3904.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3905/* File: armv6t2/OP_DOUBLE_TO_LONG.S */ 3906@include "armv6t2/unopWide.S" {"instr":"bl __aeabi_d2lz"} 3907/* File: armv6t2/unopWide.S */ 3908 /* 3909 * Generic 64-bit unary operation. Provide an "instr" line that 3910 * specifies an instruction that performs "result = op r0/r1". 3911 * This could be an ARM instruction or a function call. 3912 * 3913 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3914 */ 3915 /* unop vA, vB */ 3916 mov r3, rINST, lsr #12 @ r3<- B 3917 ubfx r9, rINST, #8, #4 @ r9<- A 3918 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3919 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3920 ldmia r3, {r0-r1} @ r0/r1<- vAA 3921 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3922 @ optional op; may set condition codes 3923 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 3924 GET_INST_OPCODE(ip) @ extract opcode from rINST 3925 stmia r9, {r0-r1} @ vAA<- r0/r1 3926 GOTO_OPCODE(ip) @ jump to next instruction 3927 /* 10-11 instructions */ 3928 3929 3930 3931/* ------------------------------ */ 3932 .balign 64 3933.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3934/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */ 3935/* File: arm-vfp/funopNarrower.S */ 3936 /* 3937 * Generic 64bit-to-32bit unary floating point operation. Provide an 3938 * "instr" line that specifies an instruction that performs "s0 = op d0". 3939 * 3940 * For: double-to-int, double-to-float 3941 */ 3942 /* unop vA, vB */ 3943 mov r3, rINST, lsr #12 @ r3<- B 3944 mov r9, rINST, lsr #8 @ r9<- A+ 3945 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3946 fldd d0, [r3] @ d0<- vB 3947 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3948 and r9, r9, #15 @ r9<- A 3949 fcvtsd s0, d0 @ s0<- op 3950 GET_INST_OPCODE(ip) @ extract opcode from rINST 3951 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3952 fsts s0, [r9] @ vA<- s0 3953 GOTO_OPCODE(ip) @ jump to next instruction 3954 3955 3956/* ------------------------------ */ 3957 .balign 64 3958.L_OP_INT_TO_BYTE: /* 0x8d */ 3959/* File: armv6t2/OP_INT_TO_BYTE.S */ 3960/* File: armv6t2/unop.S */ 3961 /* 3962 * Generic 32-bit unary operation. Provide an "instr" line that 3963 * specifies an instruction that performs "result = op r0". 3964 * This could be an ARM instruction or a function call. 3965 * 3966 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3967 * int-to-byte, int-to-char, int-to-short 3968 */ 3969 /* unop vA, vB */ 3970 mov r3, rINST, lsr #12 @ r3<- B 3971 ubfx r9, rINST, #8, #4 @ r9<- A 3972 GET_VREG(r0, r3) @ r0<- vB 3973 @ optional op; may set condition codes 3974 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3975 sxtb r0, r0 @ r0<- op, r0-r3 changed 3976 GET_INST_OPCODE(ip) @ extract opcode from rINST 3977 SET_VREG(r0, r9) @ vAA<- r0 3978 GOTO_OPCODE(ip) @ jump to next instruction 3979 /* 8-9 instructions */ 3980 3981 3982/* ------------------------------ */ 3983 .balign 64 3984.L_OP_INT_TO_CHAR: /* 0x8e */ 3985/* File: armv6t2/OP_INT_TO_CHAR.S */ 3986/* File: armv6t2/unop.S */ 3987 /* 3988 * Generic 32-bit unary operation. Provide an "instr" line that 3989 * specifies an instruction that performs "result = op r0". 3990 * This could be an ARM instruction or a function call. 3991 * 3992 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3993 * int-to-byte, int-to-char, int-to-short 3994 */ 3995 /* unop vA, vB */ 3996 mov r3, rINST, lsr #12 @ r3<- B 3997 ubfx r9, rINST, #8, #4 @ r9<- A 3998 GET_VREG(r0, r3) @ r0<- vB 3999 @ optional op; may set condition codes 4000 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4001 uxth r0, r0 @ r0<- op, r0-r3 changed 4002 GET_INST_OPCODE(ip) @ extract opcode from rINST 4003 SET_VREG(r0, r9) @ vAA<- r0 4004 GOTO_OPCODE(ip) @ jump to next instruction 4005 /* 8-9 instructions */ 4006 4007 4008/* ------------------------------ */ 4009 .balign 64 4010.L_OP_INT_TO_SHORT: /* 0x8f */ 4011/* File: armv6t2/OP_INT_TO_SHORT.S */ 4012/* File: armv6t2/unop.S */ 4013 /* 4014 * Generic 32-bit unary operation. Provide an "instr" line that 4015 * specifies an instruction that performs "result = op r0". 4016 * This could be an ARM instruction or a function call. 4017 * 4018 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4019 * int-to-byte, int-to-char, int-to-short 4020 */ 4021 /* unop vA, vB */ 4022 mov r3, rINST, lsr #12 @ r3<- B 4023 ubfx r9, rINST, #8, #4 @ r9<- A 4024 GET_VREG(r0, r3) @ r0<- vB 4025 @ optional op; may set condition codes 4026 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4027 sxth r0, r0 @ r0<- op, r0-r3 changed 4028 GET_INST_OPCODE(ip) @ extract opcode from rINST 4029 SET_VREG(r0, r9) @ vAA<- r0 4030 GOTO_OPCODE(ip) @ jump to next instruction 4031 /* 8-9 instructions */ 4032 4033 4034/* ------------------------------ */ 4035 .balign 64 4036.L_OP_ADD_INT: /* 0x90 */ 4037/* File: armv5te/OP_ADD_INT.S */ 4038/* File: armv5te/binop.S */ 4039 /* 4040 * Generic 32-bit binary operation. Provide an "instr" line that 4041 * specifies an instruction that performs "result = r0 op r1". 4042 * This could be an ARM instruction or a function call. (If the result 4043 * comes back in a register other than r0, you can override "result".) 4044 * 4045 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4046 * vCC (r1). Useful for integer division and modulus. Note that we 4047 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4048 * handles it correctly. 4049 * 4050 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4051 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4052 * mul-float, div-float, rem-float 4053 */ 4054 /* binop vAA, vBB, vCC */ 4055 FETCH(r0, 1) @ r0<- CCBB 4056 mov r9, rINST, lsr #8 @ r9<- AA 4057 mov r3, r0, lsr #8 @ r3<- CC 4058 and r2, r0, #255 @ r2<- BB 4059 GET_VREG(r1, r3) @ r1<- vCC 4060 GET_VREG(r0, r2) @ r0<- vBB 4061 .if 0 4062 cmp r1, #0 @ is second operand zero? 4063 beq common_errDivideByZero 4064 .endif 4065 4066 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4067 @ optional op; may set condition codes 4068 add r0, r0, r1 @ r0<- op, r0-r3 changed 4069 GET_INST_OPCODE(ip) @ extract opcode from rINST 4070 SET_VREG(r0, r9) @ vAA<- r0 4071 GOTO_OPCODE(ip) @ jump to next instruction 4072 /* 11-14 instructions */ 4073 4074 4075/* ------------------------------ */ 4076 .balign 64 4077.L_OP_SUB_INT: /* 0x91 */ 4078/* File: armv5te/OP_SUB_INT.S */ 4079/* File: armv5te/binop.S */ 4080 /* 4081 * Generic 32-bit binary operation. Provide an "instr" line that 4082 * specifies an instruction that performs "result = r0 op r1". 4083 * This could be an ARM instruction or a function call. (If the result 4084 * comes back in a register other than r0, you can override "result".) 4085 * 4086 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4087 * vCC (r1). Useful for integer division and modulus. Note that we 4088 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4089 * handles it correctly. 4090 * 4091 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4092 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4093 * mul-float, div-float, rem-float 4094 */ 4095 /* binop vAA, vBB, vCC */ 4096 FETCH(r0, 1) @ r0<- CCBB 4097 mov r9, rINST, lsr #8 @ r9<- AA 4098 mov r3, r0, lsr #8 @ r3<- CC 4099 and r2, r0, #255 @ r2<- BB 4100 GET_VREG(r1, r3) @ r1<- vCC 4101 GET_VREG(r0, r2) @ r0<- vBB 4102 .if 0 4103 cmp r1, #0 @ is second operand zero? 4104 beq common_errDivideByZero 4105 .endif 4106 4107 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4108 @ optional op; may set condition codes 4109 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4110 GET_INST_OPCODE(ip) @ extract opcode from rINST 4111 SET_VREG(r0, r9) @ vAA<- r0 4112 GOTO_OPCODE(ip) @ jump to next instruction 4113 /* 11-14 instructions */ 4114 4115 4116/* ------------------------------ */ 4117 .balign 64 4118.L_OP_MUL_INT: /* 0x92 */ 4119/* File: armv5te/OP_MUL_INT.S */ 4120/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4121/* File: armv5te/binop.S */ 4122 /* 4123 * Generic 32-bit binary operation. Provide an "instr" line that 4124 * specifies an instruction that performs "result = r0 op r1". 4125 * This could be an ARM instruction or a function call. (If the result 4126 * comes back in a register other than r0, you can override "result".) 4127 * 4128 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4129 * vCC (r1). Useful for integer division and modulus. Note that we 4130 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4131 * handles it correctly. 4132 * 4133 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4134 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4135 * mul-float, div-float, rem-float 4136 */ 4137 /* binop vAA, vBB, vCC */ 4138 FETCH(r0, 1) @ r0<- CCBB 4139 mov r9, rINST, lsr #8 @ r9<- AA 4140 mov r3, r0, lsr #8 @ r3<- CC 4141 and r2, r0, #255 @ r2<- BB 4142 GET_VREG(r1, r3) @ r1<- vCC 4143 GET_VREG(r0, r2) @ r0<- vBB 4144 .if 0 4145 cmp r1, #0 @ is second operand zero? 4146 beq common_errDivideByZero 4147 .endif 4148 4149 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4150 @ optional op; may set condition codes 4151 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4152 GET_INST_OPCODE(ip) @ extract opcode from rINST 4153 SET_VREG(r0, r9) @ vAA<- r0 4154 GOTO_OPCODE(ip) @ jump to next instruction 4155 /* 11-14 instructions */ 4156 4157 4158/* ------------------------------ */ 4159 .balign 64 4160.L_OP_DIV_INT: /* 0x93 */ 4161/* File: armv5te/OP_DIV_INT.S */ 4162/* File: armv5te/binop.S */ 4163 /* 4164 * Generic 32-bit binary operation. Provide an "instr" line that 4165 * specifies an instruction that performs "result = r0 op r1". 4166 * This could be an ARM instruction or a function call. (If the result 4167 * comes back in a register other than r0, you can override "result".) 4168 * 4169 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4170 * vCC (r1). Useful for integer division and modulus. Note that we 4171 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4172 * handles it correctly. 4173 * 4174 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4175 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4176 * mul-float, div-float, rem-float 4177 */ 4178 /* binop vAA, vBB, vCC */ 4179 FETCH(r0, 1) @ r0<- CCBB 4180 mov r9, rINST, lsr #8 @ r9<- AA 4181 mov r3, r0, lsr #8 @ r3<- CC 4182 and r2, r0, #255 @ r2<- BB 4183 GET_VREG(r1, r3) @ r1<- vCC 4184 GET_VREG(r0, r2) @ r0<- vBB 4185 .if 1 4186 cmp r1, #0 @ is second operand zero? 4187 beq common_errDivideByZero 4188 .endif 4189 4190 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4191 @ optional op; may set condition codes 4192 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4193 GET_INST_OPCODE(ip) @ extract opcode from rINST 4194 SET_VREG(r0, r9) @ vAA<- r0 4195 GOTO_OPCODE(ip) @ jump to next instruction 4196 /* 11-14 instructions */ 4197 4198 4199/* ------------------------------ */ 4200 .balign 64 4201.L_OP_REM_INT: /* 0x94 */ 4202/* File: armv5te/OP_REM_INT.S */ 4203/* idivmod returns quotient in r0 and remainder in r1 */ 4204/* File: armv5te/binop.S */ 4205 /* 4206 * Generic 32-bit binary operation. Provide an "instr" line that 4207 * specifies an instruction that performs "result = r0 op r1". 4208 * This could be an ARM instruction or a function call. (If the result 4209 * comes back in a register other than r0, you can override "result".) 4210 * 4211 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4212 * vCC (r1). Useful for integer division and modulus. Note that we 4213 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4214 * handles it correctly. 4215 * 4216 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4217 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4218 * mul-float, div-float, rem-float 4219 */ 4220 /* binop vAA, vBB, vCC */ 4221 FETCH(r0, 1) @ r0<- CCBB 4222 mov r9, rINST, lsr #8 @ r9<- AA 4223 mov r3, r0, lsr #8 @ r3<- CC 4224 and r2, r0, #255 @ r2<- BB 4225 GET_VREG(r1, r3) @ r1<- vCC 4226 GET_VREG(r0, r2) @ r0<- vBB 4227 .if 1 4228 cmp r1, #0 @ is second operand zero? 4229 beq common_errDivideByZero 4230 .endif 4231 4232 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4233 @ optional op; may set condition codes 4234 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4235 GET_INST_OPCODE(ip) @ extract opcode from rINST 4236 SET_VREG(r1, r9) @ vAA<- r1 4237 GOTO_OPCODE(ip) @ jump to next instruction 4238 /* 11-14 instructions */ 4239 4240 4241/* ------------------------------ */ 4242 .balign 64 4243.L_OP_AND_INT: /* 0x95 */ 4244/* File: armv5te/OP_AND_INT.S */ 4245/* File: armv5te/binop.S */ 4246 /* 4247 * Generic 32-bit binary operation. Provide an "instr" line that 4248 * specifies an instruction that performs "result = r0 op r1". 4249 * This could be an ARM instruction or a function call. (If the result 4250 * comes back in a register other than r0, you can override "result".) 4251 * 4252 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4253 * vCC (r1). Useful for integer division and modulus. Note that we 4254 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4255 * handles it correctly. 4256 * 4257 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4258 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4259 * mul-float, div-float, rem-float 4260 */ 4261 /* binop vAA, vBB, vCC */ 4262 FETCH(r0, 1) @ r0<- CCBB 4263 mov r9, rINST, lsr #8 @ r9<- AA 4264 mov r3, r0, lsr #8 @ r3<- CC 4265 and r2, r0, #255 @ r2<- BB 4266 GET_VREG(r1, r3) @ r1<- vCC 4267 GET_VREG(r0, r2) @ r0<- vBB 4268 .if 0 4269 cmp r1, #0 @ is second operand zero? 4270 beq common_errDivideByZero 4271 .endif 4272 4273 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4274 @ optional op; may set condition codes 4275 and r0, r0, r1 @ r0<- op, r0-r3 changed 4276 GET_INST_OPCODE(ip) @ extract opcode from rINST 4277 SET_VREG(r0, r9) @ vAA<- r0 4278 GOTO_OPCODE(ip) @ jump to next instruction 4279 /* 11-14 instructions */ 4280 4281 4282/* ------------------------------ */ 4283 .balign 64 4284.L_OP_OR_INT: /* 0x96 */ 4285/* File: armv5te/OP_OR_INT.S */ 4286/* File: armv5te/binop.S */ 4287 /* 4288 * Generic 32-bit binary operation. Provide an "instr" line that 4289 * specifies an instruction that performs "result = r0 op r1". 4290 * This could be an ARM instruction or a function call. (If the result 4291 * comes back in a register other than r0, you can override "result".) 4292 * 4293 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4294 * vCC (r1). Useful for integer division and modulus. Note that we 4295 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4296 * handles it correctly. 4297 * 4298 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4299 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4300 * mul-float, div-float, rem-float 4301 */ 4302 /* binop vAA, vBB, vCC */ 4303 FETCH(r0, 1) @ r0<- CCBB 4304 mov r9, rINST, lsr #8 @ r9<- AA 4305 mov r3, r0, lsr #8 @ r3<- CC 4306 and r2, r0, #255 @ r2<- BB 4307 GET_VREG(r1, r3) @ r1<- vCC 4308 GET_VREG(r0, r2) @ r0<- vBB 4309 .if 0 4310 cmp r1, #0 @ is second operand zero? 4311 beq common_errDivideByZero 4312 .endif 4313 4314 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4315 @ optional op; may set condition codes 4316 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4317 GET_INST_OPCODE(ip) @ extract opcode from rINST 4318 SET_VREG(r0, r9) @ vAA<- r0 4319 GOTO_OPCODE(ip) @ jump to next instruction 4320 /* 11-14 instructions */ 4321 4322 4323/* ------------------------------ */ 4324 .balign 64 4325.L_OP_XOR_INT: /* 0x97 */ 4326/* File: armv5te/OP_XOR_INT.S */ 4327/* File: armv5te/binop.S */ 4328 /* 4329 * Generic 32-bit binary operation. Provide an "instr" line that 4330 * specifies an instruction that performs "result = r0 op r1". 4331 * This could be an ARM instruction or a function call. (If the result 4332 * comes back in a register other than r0, you can override "result".) 4333 * 4334 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4335 * vCC (r1). Useful for integer division and modulus. Note that we 4336 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4337 * handles it correctly. 4338 * 4339 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4340 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4341 * mul-float, div-float, rem-float 4342 */ 4343 /* binop vAA, vBB, vCC */ 4344 FETCH(r0, 1) @ r0<- CCBB 4345 mov r9, rINST, lsr #8 @ r9<- AA 4346 mov r3, r0, lsr #8 @ r3<- CC 4347 and r2, r0, #255 @ r2<- BB 4348 GET_VREG(r1, r3) @ r1<- vCC 4349 GET_VREG(r0, r2) @ r0<- vBB 4350 .if 0 4351 cmp r1, #0 @ is second operand zero? 4352 beq common_errDivideByZero 4353 .endif 4354 4355 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4356 @ optional op; may set condition codes 4357 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4358 GET_INST_OPCODE(ip) @ extract opcode from rINST 4359 SET_VREG(r0, r9) @ vAA<- r0 4360 GOTO_OPCODE(ip) @ jump to next instruction 4361 /* 11-14 instructions */ 4362 4363 4364/* ------------------------------ */ 4365 .balign 64 4366.L_OP_SHL_INT: /* 0x98 */ 4367/* File: armv5te/OP_SHL_INT.S */ 4368/* File: armv5te/binop.S */ 4369 /* 4370 * Generic 32-bit binary operation. Provide an "instr" line that 4371 * specifies an instruction that performs "result = r0 op r1". 4372 * This could be an ARM instruction or a function call. (If the result 4373 * comes back in a register other than r0, you can override "result".) 4374 * 4375 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4376 * vCC (r1). Useful for integer division and modulus. Note that we 4377 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4378 * handles it correctly. 4379 * 4380 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4381 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4382 * mul-float, div-float, rem-float 4383 */ 4384 /* binop vAA, vBB, vCC */ 4385 FETCH(r0, 1) @ r0<- CCBB 4386 mov r9, rINST, lsr #8 @ r9<- AA 4387 mov r3, r0, lsr #8 @ r3<- CC 4388 and r2, r0, #255 @ r2<- BB 4389 GET_VREG(r1, r3) @ r1<- vCC 4390 GET_VREG(r0, r2) @ r0<- vBB 4391 .if 0 4392 cmp r1, #0 @ is second operand zero? 4393 beq common_errDivideByZero 4394 .endif 4395 4396 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4397 and r1, r1, #31 @ optional op; may set condition codes 4398 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4399 GET_INST_OPCODE(ip) @ extract opcode from rINST 4400 SET_VREG(r0, r9) @ vAA<- r0 4401 GOTO_OPCODE(ip) @ jump to next instruction 4402 /* 11-14 instructions */ 4403 4404 4405/* ------------------------------ */ 4406 .balign 64 4407.L_OP_SHR_INT: /* 0x99 */ 4408/* File: armv5te/OP_SHR_INT.S */ 4409/* File: armv5te/binop.S */ 4410 /* 4411 * Generic 32-bit binary operation. Provide an "instr" line that 4412 * specifies an instruction that performs "result = r0 op r1". 4413 * This could be an ARM instruction or a function call. (If the result 4414 * comes back in a register other than r0, you can override "result".) 4415 * 4416 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4417 * vCC (r1). Useful for integer division and modulus. Note that we 4418 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4419 * handles it correctly. 4420 * 4421 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4422 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4423 * mul-float, div-float, rem-float 4424 */ 4425 /* binop vAA, vBB, vCC */ 4426 FETCH(r0, 1) @ r0<- CCBB 4427 mov r9, rINST, lsr #8 @ r9<- AA 4428 mov r3, r0, lsr #8 @ r3<- CC 4429 and r2, r0, #255 @ r2<- BB 4430 GET_VREG(r1, r3) @ r1<- vCC 4431 GET_VREG(r0, r2) @ r0<- vBB 4432 .if 0 4433 cmp r1, #0 @ is second operand zero? 4434 beq common_errDivideByZero 4435 .endif 4436 4437 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4438 and r1, r1, #31 @ optional op; may set condition codes 4439 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4440 GET_INST_OPCODE(ip) @ extract opcode from rINST 4441 SET_VREG(r0, r9) @ vAA<- r0 4442 GOTO_OPCODE(ip) @ jump to next instruction 4443 /* 11-14 instructions */ 4444 4445 4446/* ------------------------------ */ 4447 .balign 64 4448.L_OP_USHR_INT: /* 0x9a */ 4449/* File: armv5te/OP_USHR_INT.S */ 4450/* File: armv5te/binop.S */ 4451 /* 4452 * Generic 32-bit binary operation. Provide an "instr" line that 4453 * specifies an instruction that performs "result = r0 op r1". 4454 * This could be an ARM instruction or a function call. (If the result 4455 * comes back in a register other than r0, you can override "result".) 4456 * 4457 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4458 * vCC (r1). Useful for integer division and modulus. Note that we 4459 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4460 * handles it correctly. 4461 * 4462 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4463 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4464 * mul-float, div-float, rem-float 4465 */ 4466 /* binop vAA, vBB, vCC */ 4467 FETCH(r0, 1) @ r0<- CCBB 4468 mov r9, rINST, lsr #8 @ r9<- AA 4469 mov r3, r0, lsr #8 @ r3<- CC 4470 and r2, r0, #255 @ r2<- BB 4471 GET_VREG(r1, r3) @ r1<- vCC 4472 GET_VREG(r0, r2) @ r0<- vBB 4473 .if 0 4474 cmp r1, #0 @ is second operand zero? 4475 beq common_errDivideByZero 4476 .endif 4477 4478 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4479 and r1, r1, #31 @ optional op; may set condition codes 4480 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4481 GET_INST_OPCODE(ip) @ extract opcode from rINST 4482 SET_VREG(r0, r9) @ vAA<- r0 4483 GOTO_OPCODE(ip) @ jump to next instruction 4484 /* 11-14 instructions */ 4485 4486 4487/* ------------------------------ */ 4488 .balign 64 4489.L_OP_ADD_LONG: /* 0x9b */ 4490/* File: armv5te/OP_ADD_LONG.S */ 4491/* File: armv5te/binopWide.S */ 4492 /* 4493 * Generic 64-bit binary operation. Provide an "instr" line that 4494 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4495 * This could be an ARM instruction or a function call. (If the result 4496 * comes back in a register other than r0, you can override "result".) 4497 * 4498 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4499 * vCC (r1). Useful for integer division and modulus. 4500 * 4501 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4502 * xor-long, add-double, sub-double, mul-double, div-double, 4503 * rem-double 4504 * 4505 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4506 */ 4507 /* binop vAA, vBB, vCC */ 4508 FETCH(r0, 1) @ r0<- CCBB 4509 mov r9, rINST, lsr #8 @ r9<- AA 4510 and r2, r0, #255 @ r2<- BB 4511 mov r3, r0, lsr #8 @ r3<- CC 4512 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4513 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4514 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4515 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4516 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4517 .if 0 4518 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4519 beq common_errDivideByZero 4520 .endif 4521 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4522 4523 adds r0, r0, r2 @ optional op; may set condition codes 4524 adc r1, r1, r3 @ result<- op, r0-r3 changed 4525 GET_INST_OPCODE(ip) @ extract opcode from rINST 4526 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4527 GOTO_OPCODE(ip) @ jump to next instruction 4528 /* 14-17 instructions */ 4529 4530 4531/* ------------------------------ */ 4532 .balign 64 4533.L_OP_SUB_LONG: /* 0x9c */ 4534/* File: armv5te/OP_SUB_LONG.S */ 4535/* File: armv5te/binopWide.S */ 4536 /* 4537 * Generic 64-bit binary operation. Provide an "instr" line that 4538 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4539 * This could be an ARM instruction or a function call. (If the result 4540 * comes back in a register other than r0, you can override "result".) 4541 * 4542 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4543 * vCC (r1). Useful for integer division and modulus. 4544 * 4545 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4546 * xor-long, add-double, sub-double, mul-double, div-double, 4547 * rem-double 4548 * 4549 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4550 */ 4551 /* binop vAA, vBB, vCC */ 4552 FETCH(r0, 1) @ r0<- CCBB 4553 mov r9, rINST, lsr #8 @ r9<- AA 4554 and r2, r0, #255 @ r2<- BB 4555 mov r3, r0, lsr #8 @ r3<- CC 4556 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4557 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4558 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4559 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4560 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4561 .if 0 4562 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4563 beq common_errDivideByZero 4564 .endif 4565 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4566 4567 subs r0, r0, r2 @ optional op; may set condition codes 4568 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4569 GET_INST_OPCODE(ip) @ extract opcode from rINST 4570 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4571 GOTO_OPCODE(ip) @ jump to next instruction 4572 /* 14-17 instructions */ 4573 4574 4575/* ------------------------------ */ 4576 .balign 64 4577.L_OP_MUL_LONG: /* 0x9d */ 4578/* File: armv5te/OP_MUL_LONG.S */ 4579 /* 4580 * Signed 64-bit integer multiply. 4581 * 4582 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4583 * WX 4584 * x YZ 4585 * -------- 4586 * ZW ZX 4587 * YW YX 4588 * 4589 * The low word of the result holds ZX, the high word holds 4590 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4591 * it doesn't fit in the low 64 bits. 4592 * 4593 * Unlike most ARM math operations, multiply instructions have 4594 * restrictions on using the same register more than once (Rd and Rm 4595 * cannot be the same). 4596 */ 4597 /* mul-long vAA, vBB, vCC */ 4598 FETCH(r0, 1) @ r0<- CCBB 4599 and r2, r0, #255 @ r2<- BB 4600 mov r3, r0, lsr #8 @ r3<- CC 4601 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4602 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4603 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4604 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4605 mul ip, r2, r1 @ ip<- ZxW 4606 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4607 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4608 mov r0, rINST, lsr #8 @ r0<- AA 4609 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4610 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4611 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4612 b .LOP_MUL_LONG_finish 4613 4614/* ------------------------------ */ 4615 .balign 64 4616.L_OP_DIV_LONG: /* 0x9e */ 4617/* File: armv5te/OP_DIV_LONG.S */ 4618/* File: armv5te/binopWide.S */ 4619 /* 4620 * Generic 64-bit binary operation. Provide an "instr" line that 4621 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4622 * This could be an ARM instruction or a function call. (If the result 4623 * comes back in a register other than r0, you can override "result".) 4624 * 4625 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4626 * vCC (r1). Useful for integer division and modulus. 4627 * 4628 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4629 * xor-long, add-double, sub-double, mul-double, div-double, 4630 * rem-double 4631 * 4632 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4633 */ 4634 /* binop vAA, vBB, vCC */ 4635 FETCH(r0, 1) @ r0<- CCBB 4636 mov r9, rINST, lsr #8 @ r9<- AA 4637 and r2, r0, #255 @ r2<- BB 4638 mov r3, r0, lsr #8 @ r3<- CC 4639 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4640 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4641 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4642 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4643 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4644 .if 1 4645 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4646 beq common_errDivideByZero 4647 .endif 4648 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4649 4650 @ optional op; may set condition codes 4651 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4652 GET_INST_OPCODE(ip) @ extract opcode from rINST 4653 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4654 GOTO_OPCODE(ip) @ jump to next instruction 4655 /* 14-17 instructions */ 4656 4657 4658/* ------------------------------ */ 4659 .balign 64 4660.L_OP_REM_LONG: /* 0x9f */ 4661/* File: armv5te/OP_REM_LONG.S */ 4662/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4663/* File: armv5te/binopWide.S */ 4664 /* 4665 * Generic 64-bit binary operation. Provide an "instr" line that 4666 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4667 * This could be an ARM instruction or a function call. (If the result 4668 * comes back in a register other than r0, you can override "result".) 4669 * 4670 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4671 * vCC (r1). Useful for integer division and modulus. 4672 * 4673 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4674 * xor-long, add-double, sub-double, mul-double, div-double, 4675 * rem-double 4676 * 4677 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4678 */ 4679 /* binop vAA, vBB, vCC */ 4680 FETCH(r0, 1) @ r0<- CCBB 4681 mov r9, rINST, lsr #8 @ r9<- AA 4682 and r2, r0, #255 @ r2<- BB 4683 mov r3, r0, lsr #8 @ r3<- CC 4684 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4685 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4686 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4687 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4688 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4689 .if 1 4690 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4691 beq common_errDivideByZero 4692 .endif 4693 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4694 4695 @ optional op; may set condition codes 4696 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4697 GET_INST_OPCODE(ip) @ extract opcode from rINST 4698 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4699 GOTO_OPCODE(ip) @ jump to next instruction 4700 /* 14-17 instructions */ 4701 4702 4703/* ------------------------------ */ 4704 .balign 64 4705.L_OP_AND_LONG: /* 0xa0 */ 4706/* File: armv5te/OP_AND_LONG.S */ 4707/* File: armv5te/binopWide.S */ 4708 /* 4709 * Generic 64-bit binary operation. Provide an "instr" line that 4710 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4711 * This could be an ARM instruction or a function call. (If the result 4712 * comes back in a register other than r0, you can override "result".) 4713 * 4714 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4715 * vCC (r1). Useful for integer division and modulus. 4716 * 4717 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4718 * xor-long, add-double, sub-double, mul-double, div-double, 4719 * rem-double 4720 * 4721 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4722 */ 4723 /* binop vAA, vBB, vCC */ 4724 FETCH(r0, 1) @ r0<- CCBB 4725 mov r9, rINST, lsr #8 @ r9<- AA 4726 and r2, r0, #255 @ r2<- BB 4727 mov r3, r0, lsr #8 @ r3<- CC 4728 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4729 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4730 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4731 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4732 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4733 .if 0 4734 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4735 beq common_errDivideByZero 4736 .endif 4737 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4738 4739 and r0, r0, r2 @ optional op; may set condition codes 4740 and r1, r1, r3 @ result<- op, r0-r3 changed 4741 GET_INST_OPCODE(ip) @ extract opcode from rINST 4742 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4743 GOTO_OPCODE(ip) @ jump to next instruction 4744 /* 14-17 instructions */ 4745 4746 4747/* ------------------------------ */ 4748 .balign 64 4749.L_OP_OR_LONG: /* 0xa1 */ 4750/* File: armv5te/OP_OR_LONG.S */ 4751/* File: armv5te/binopWide.S */ 4752 /* 4753 * Generic 64-bit binary operation. Provide an "instr" line that 4754 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4755 * This could be an ARM instruction or a function call. (If the result 4756 * comes back in a register other than r0, you can override "result".) 4757 * 4758 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4759 * vCC (r1). Useful for integer division and modulus. 4760 * 4761 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4762 * xor-long, add-double, sub-double, mul-double, div-double, 4763 * rem-double 4764 * 4765 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4766 */ 4767 /* binop vAA, vBB, vCC */ 4768 FETCH(r0, 1) @ r0<- CCBB 4769 mov r9, rINST, lsr #8 @ r9<- AA 4770 and r2, r0, #255 @ r2<- BB 4771 mov r3, r0, lsr #8 @ r3<- CC 4772 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4773 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4774 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4775 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4776 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4777 .if 0 4778 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4779 beq common_errDivideByZero 4780 .endif 4781 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4782 4783 orr r0, r0, r2 @ optional op; may set condition codes 4784 orr r1, r1, r3 @ result<- op, r0-r3 changed 4785 GET_INST_OPCODE(ip) @ extract opcode from rINST 4786 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4787 GOTO_OPCODE(ip) @ jump to next instruction 4788 /* 14-17 instructions */ 4789 4790 4791/* ------------------------------ */ 4792 .balign 64 4793.L_OP_XOR_LONG: /* 0xa2 */ 4794/* File: armv5te/OP_XOR_LONG.S */ 4795/* File: armv5te/binopWide.S */ 4796 /* 4797 * Generic 64-bit binary operation. Provide an "instr" line that 4798 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4799 * This could be an ARM instruction or a function call. (If the result 4800 * comes back in a register other than r0, you can override "result".) 4801 * 4802 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4803 * vCC (r1). Useful for integer division and modulus. 4804 * 4805 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4806 * xor-long, add-double, sub-double, mul-double, div-double, 4807 * rem-double 4808 * 4809 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4810 */ 4811 /* binop vAA, vBB, vCC */ 4812 FETCH(r0, 1) @ r0<- CCBB 4813 mov r9, rINST, lsr #8 @ r9<- AA 4814 and r2, r0, #255 @ r2<- BB 4815 mov r3, r0, lsr #8 @ r3<- CC 4816 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4817 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4818 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4819 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4820 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4821 .if 0 4822 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4823 beq common_errDivideByZero 4824 .endif 4825 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4826 4827 eor r0, r0, r2 @ optional op; may set condition codes 4828 eor r1, r1, r3 @ result<- op, r0-r3 changed 4829 GET_INST_OPCODE(ip) @ extract opcode from rINST 4830 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4831 GOTO_OPCODE(ip) @ jump to next instruction 4832 /* 14-17 instructions */ 4833 4834 4835/* ------------------------------ */ 4836 .balign 64 4837.L_OP_SHL_LONG: /* 0xa3 */ 4838/* File: armv5te/OP_SHL_LONG.S */ 4839 /* 4840 * Long integer shift. This is different from the generic 32/64-bit 4841 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4842 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4843 * 6 bits of the shift distance. 4844 */ 4845 /* shl-long vAA, vBB, vCC */ 4846 FETCH(r0, 1) @ r0<- CCBB 4847 mov r9, rINST, lsr #8 @ r9<- AA 4848 and r3, r0, #255 @ r3<- BB 4849 mov r0, r0, lsr #8 @ r0<- CC 4850 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4851 GET_VREG(r2, r0) @ r2<- vCC 4852 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4853 and r2, r2, #63 @ r2<- r2 & 0x3f 4854 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4855 4856 mov r1, r1, asl r2 @ r1<- r1 << r2 4857 rsb r3, r2, #32 @ r3<- 32 - r2 4858 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 4859 subs ip, r2, #32 @ ip<- r2 - 32 4860 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 4861 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4862 b .LOP_SHL_LONG_finish 4863 4864/* ------------------------------ */ 4865 .balign 64 4866.L_OP_SHR_LONG: /* 0xa4 */ 4867/* File: armv5te/OP_SHR_LONG.S */ 4868 /* 4869 * Long integer shift. This is different from the generic 32/64-bit 4870 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4871 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4872 * 6 bits of the shift distance. 4873 */ 4874 /* shr-long vAA, vBB, vCC */ 4875 FETCH(r0, 1) @ r0<- CCBB 4876 mov r9, rINST, lsr #8 @ r9<- AA 4877 and r3, r0, #255 @ r3<- BB 4878 mov r0, r0, lsr #8 @ r0<- CC 4879 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4880 GET_VREG(r2, r0) @ r2<- vCC 4881 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4882 and r2, r2, #63 @ r0<- r0 & 0x3f 4883 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4884 4885 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4886 rsb r3, r2, #32 @ r3<- 32 - r2 4887 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4888 subs ip, r2, #32 @ ip<- r2 - 32 4889 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 4890 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4891 b .LOP_SHR_LONG_finish 4892 4893/* ------------------------------ */ 4894 .balign 64 4895.L_OP_USHR_LONG: /* 0xa5 */ 4896/* File: armv5te/OP_USHR_LONG.S */ 4897 /* 4898 * Long integer shift. This is different from the generic 32/64-bit 4899 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4900 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4901 * 6 bits of the shift distance. 4902 */ 4903 /* ushr-long vAA, vBB, vCC */ 4904 FETCH(r0, 1) @ r0<- CCBB 4905 mov r9, rINST, lsr #8 @ r9<- AA 4906 and r3, r0, #255 @ r3<- BB 4907 mov r0, r0, lsr #8 @ r0<- CC 4908 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4909 GET_VREG(r2, r0) @ r2<- vCC 4910 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4911 and r2, r2, #63 @ r0<- r0 & 0x3f 4912 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4913 4914 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4915 rsb r3, r2, #32 @ r3<- 32 - r2 4916 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4917 subs ip, r2, #32 @ ip<- r2 - 32 4918 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 4919 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4920 b .LOP_USHR_LONG_finish 4921 4922/* ------------------------------ */ 4923 .balign 64 4924.L_OP_ADD_FLOAT: /* 0xa6 */ 4925/* File: arm-vfp/OP_ADD_FLOAT.S */ 4926/* File: arm-vfp/fbinop.S */ 4927 /* 4928 * Generic 32-bit floating-point operation. Provide an "instr" line that 4929 * specifies an instruction that performs "s2 = s0 op s1". Because we 4930 * use the "softfp" ABI, this must be an instruction, not a function call. 4931 * 4932 * For: add-float, sub-float, mul-float, div-float 4933 */ 4934 /* floatop vAA, vBB, vCC */ 4935 FETCH(r0, 1) @ r0<- CCBB 4936 mov r9, rINST, lsr #8 @ r9<- AA 4937 mov r3, r0, lsr #8 @ r3<- CC 4938 and r2, r0, #255 @ r2<- BB 4939 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4940 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4941 flds s1, [r3] @ s1<- vCC 4942 flds s0, [r2] @ s0<- vBB 4943 4944 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4945 fadds s2, s0, s1 @ s2<- op 4946 GET_INST_OPCODE(ip) @ extract opcode from rINST 4947 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4948 fsts s2, [r9] @ vAA<- s2 4949 GOTO_OPCODE(ip) @ jump to next instruction 4950 4951 4952/* ------------------------------ */ 4953 .balign 64 4954.L_OP_SUB_FLOAT: /* 0xa7 */ 4955/* File: arm-vfp/OP_SUB_FLOAT.S */ 4956/* File: arm-vfp/fbinop.S */ 4957 /* 4958 * Generic 32-bit floating-point operation. Provide an "instr" line that 4959 * specifies an instruction that performs "s2 = s0 op s1". Because we 4960 * use the "softfp" ABI, this must be an instruction, not a function call. 4961 * 4962 * For: add-float, sub-float, mul-float, div-float 4963 */ 4964 /* floatop vAA, vBB, vCC */ 4965 FETCH(r0, 1) @ r0<- CCBB 4966 mov r9, rINST, lsr #8 @ r9<- AA 4967 mov r3, r0, lsr #8 @ r3<- CC 4968 and r2, r0, #255 @ r2<- BB 4969 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4970 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4971 flds s1, [r3] @ s1<- vCC 4972 flds s0, [r2] @ s0<- vBB 4973 4974 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4975 fsubs s2, s0, s1 @ s2<- op 4976 GET_INST_OPCODE(ip) @ extract opcode from rINST 4977 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4978 fsts s2, [r9] @ vAA<- s2 4979 GOTO_OPCODE(ip) @ jump to next instruction 4980 4981 4982/* ------------------------------ */ 4983 .balign 64 4984.L_OP_MUL_FLOAT: /* 0xa8 */ 4985/* File: arm-vfp/OP_MUL_FLOAT.S */ 4986/* File: arm-vfp/fbinop.S */ 4987 /* 4988 * Generic 32-bit floating-point operation. Provide an "instr" line that 4989 * specifies an instruction that performs "s2 = s0 op s1". Because we 4990 * use the "softfp" ABI, this must be an instruction, not a function call. 4991 * 4992 * For: add-float, sub-float, mul-float, div-float 4993 */ 4994 /* floatop vAA, vBB, vCC */ 4995 FETCH(r0, 1) @ r0<- CCBB 4996 mov r9, rINST, lsr #8 @ r9<- AA 4997 mov r3, r0, lsr #8 @ r3<- CC 4998 and r2, r0, #255 @ r2<- BB 4999 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5000 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5001 flds s1, [r3] @ s1<- vCC 5002 flds s0, [r2] @ s0<- vBB 5003 5004 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5005 fmuls s2, s0, s1 @ s2<- op 5006 GET_INST_OPCODE(ip) @ extract opcode from rINST 5007 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5008 fsts s2, [r9] @ vAA<- s2 5009 GOTO_OPCODE(ip) @ jump to next instruction 5010 5011 5012/* ------------------------------ */ 5013 .balign 64 5014.L_OP_DIV_FLOAT: /* 0xa9 */ 5015/* File: arm-vfp/OP_DIV_FLOAT.S */ 5016/* File: arm-vfp/fbinop.S */ 5017 /* 5018 * Generic 32-bit floating-point operation. Provide an "instr" line that 5019 * specifies an instruction that performs "s2 = s0 op s1". Because we 5020 * use the "softfp" ABI, this must be an instruction, not a function call. 5021 * 5022 * For: add-float, sub-float, mul-float, div-float 5023 */ 5024 /* floatop vAA, vBB, vCC */ 5025 FETCH(r0, 1) @ r0<- CCBB 5026 mov r9, rINST, lsr #8 @ r9<- AA 5027 mov r3, r0, lsr #8 @ r3<- CC 5028 and r2, r0, #255 @ r2<- BB 5029 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5030 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5031 flds s1, [r3] @ s1<- vCC 5032 flds s0, [r2] @ s0<- vBB 5033 5034 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5035 fdivs s2, s0, s1 @ s2<- op 5036 GET_INST_OPCODE(ip) @ extract opcode from rINST 5037 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5038 fsts s2, [r9] @ vAA<- s2 5039 GOTO_OPCODE(ip) @ jump to next instruction 5040 5041 5042/* ------------------------------ */ 5043 .balign 64 5044.L_OP_REM_FLOAT: /* 0xaa */ 5045/* File: armv5te/OP_REM_FLOAT.S */ 5046/* EABI doesn't define a float remainder function, but libm does */ 5047/* File: armv5te/binop.S */ 5048 /* 5049 * Generic 32-bit binary operation. Provide an "instr" line that 5050 * specifies an instruction that performs "result = r0 op r1". 5051 * This could be an ARM instruction or a function call. (If the result 5052 * comes back in a register other than r0, you can override "result".) 5053 * 5054 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5055 * vCC (r1). Useful for integer division and modulus. Note that we 5056 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5057 * handles it correctly. 5058 * 5059 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5060 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5061 * mul-float, div-float, rem-float 5062 */ 5063 /* binop vAA, vBB, vCC */ 5064 FETCH(r0, 1) @ r0<- CCBB 5065 mov r9, rINST, lsr #8 @ r9<- AA 5066 mov r3, r0, lsr #8 @ r3<- CC 5067 and r2, r0, #255 @ r2<- BB 5068 GET_VREG(r1, r3) @ r1<- vCC 5069 GET_VREG(r0, r2) @ r0<- vBB 5070 .if 0 5071 cmp r1, #0 @ is second operand zero? 5072 beq common_errDivideByZero 5073 .endif 5074 5075 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5076 @ optional op; may set condition codes 5077 bl fmodf @ r0<- op, r0-r3 changed 5078 GET_INST_OPCODE(ip) @ extract opcode from rINST 5079 SET_VREG(r0, r9) @ vAA<- r0 5080 GOTO_OPCODE(ip) @ jump to next instruction 5081 /* 11-14 instructions */ 5082 5083 5084/* ------------------------------ */ 5085 .balign 64 5086.L_OP_ADD_DOUBLE: /* 0xab */ 5087/* File: arm-vfp/OP_ADD_DOUBLE.S */ 5088/* File: arm-vfp/fbinopWide.S */ 5089 /* 5090 * Generic 64-bit double-precision floating point binary operation. 5091 * Provide an "instr" line that specifies an instruction that performs 5092 * "d2 = d0 op d1". 5093 * 5094 * for: add-double, sub-double, mul-double, div-double 5095 */ 5096 /* doubleop vAA, vBB, vCC */ 5097 FETCH(r0, 1) @ r0<- CCBB 5098 mov r9, rINST, lsr #8 @ r9<- AA 5099 mov r3, r0, lsr #8 @ r3<- CC 5100 and r2, r0, #255 @ r2<- BB 5101 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5102 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5103 fldd d1, [r3] @ d1<- vCC 5104 fldd d0, [r2] @ d0<- vBB 5105 5106 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5107 faddd d2, d0, d1 @ s2<- op 5108 GET_INST_OPCODE(ip) @ extract opcode from rINST 5109 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5110 fstd d2, [r9] @ vAA<- d2 5111 GOTO_OPCODE(ip) @ jump to next instruction 5112 5113 5114/* ------------------------------ */ 5115 .balign 64 5116.L_OP_SUB_DOUBLE: /* 0xac */ 5117/* File: arm-vfp/OP_SUB_DOUBLE.S */ 5118/* File: arm-vfp/fbinopWide.S */ 5119 /* 5120 * Generic 64-bit double-precision floating point binary operation. 5121 * Provide an "instr" line that specifies an instruction that performs 5122 * "d2 = d0 op d1". 5123 * 5124 * for: add-double, sub-double, mul-double, div-double 5125 */ 5126 /* doubleop vAA, vBB, vCC */ 5127 FETCH(r0, 1) @ r0<- CCBB 5128 mov r9, rINST, lsr #8 @ r9<- AA 5129 mov r3, r0, lsr #8 @ r3<- CC 5130 and r2, r0, #255 @ r2<- BB 5131 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5132 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5133 fldd d1, [r3] @ d1<- vCC 5134 fldd d0, [r2] @ d0<- vBB 5135 5136 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5137 fsubd d2, d0, d1 @ s2<- op 5138 GET_INST_OPCODE(ip) @ extract opcode from rINST 5139 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5140 fstd d2, [r9] @ vAA<- d2 5141 GOTO_OPCODE(ip) @ jump to next instruction 5142 5143 5144/* ------------------------------ */ 5145 .balign 64 5146.L_OP_MUL_DOUBLE: /* 0xad */ 5147/* File: arm-vfp/OP_MUL_DOUBLE.S */ 5148/* File: arm-vfp/fbinopWide.S */ 5149 /* 5150 * Generic 64-bit double-precision floating point binary operation. 5151 * Provide an "instr" line that specifies an instruction that performs 5152 * "d2 = d0 op d1". 5153 * 5154 * for: add-double, sub-double, mul-double, div-double 5155 */ 5156 /* doubleop vAA, vBB, vCC */ 5157 FETCH(r0, 1) @ r0<- CCBB 5158 mov r9, rINST, lsr #8 @ r9<- AA 5159 mov r3, r0, lsr #8 @ r3<- CC 5160 and r2, r0, #255 @ r2<- BB 5161 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5162 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5163 fldd d1, [r3] @ d1<- vCC 5164 fldd d0, [r2] @ d0<- vBB 5165 5166 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5167 fmuld d2, d0, d1 @ s2<- op 5168 GET_INST_OPCODE(ip) @ extract opcode from rINST 5169 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5170 fstd d2, [r9] @ vAA<- d2 5171 GOTO_OPCODE(ip) @ jump to next instruction 5172 5173 5174/* ------------------------------ */ 5175 .balign 64 5176.L_OP_DIV_DOUBLE: /* 0xae */ 5177/* File: arm-vfp/OP_DIV_DOUBLE.S */ 5178/* File: arm-vfp/fbinopWide.S */ 5179 /* 5180 * Generic 64-bit double-precision floating point binary operation. 5181 * Provide an "instr" line that specifies an instruction that performs 5182 * "d2 = d0 op d1". 5183 * 5184 * for: add-double, sub-double, mul-double, div-double 5185 */ 5186 /* doubleop vAA, vBB, vCC */ 5187 FETCH(r0, 1) @ r0<- CCBB 5188 mov r9, rINST, lsr #8 @ r9<- AA 5189 mov r3, r0, lsr #8 @ r3<- CC 5190 and r2, r0, #255 @ r2<- BB 5191 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5192 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5193 fldd d1, [r3] @ d1<- vCC 5194 fldd d0, [r2] @ d0<- vBB 5195 5196 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5197 fdivd d2, d0, d1 @ s2<- op 5198 GET_INST_OPCODE(ip) @ extract opcode from rINST 5199 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5200 fstd d2, [r9] @ vAA<- d2 5201 GOTO_OPCODE(ip) @ jump to next instruction 5202 5203 5204/* ------------------------------ */ 5205 .balign 64 5206.L_OP_REM_DOUBLE: /* 0xaf */ 5207/* File: armv5te/OP_REM_DOUBLE.S */ 5208/* EABI doesn't define a double remainder function, but libm does */ 5209/* File: armv5te/binopWide.S */ 5210 /* 5211 * Generic 64-bit binary operation. Provide an "instr" line that 5212 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5213 * This could be an ARM instruction or a function call. (If the result 5214 * comes back in a register other than r0, you can override "result".) 5215 * 5216 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5217 * vCC (r1). Useful for integer division and modulus. 5218 * 5219 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5220 * xor-long, add-double, sub-double, mul-double, div-double, 5221 * rem-double 5222 * 5223 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5224 */ 5225 /* binop vAA, vBB, vCC */ 5226 FETCH(r0, 1) @ r0<- CCBB 5227 mov r9, rINST, lsr #8 @ r9<- AA 5228 and r2, r0, #255 @ r2<- BB 5229 mov r3, r0, lsr #8 @ r3<- CC 5230 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5231 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5232 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5233 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5234 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5235 .if 0 5236 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5237 beq common_errDivideByZero 5238 .endif 5239 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5240 5241 @ optional op; may set condition codes 5242 bl fmod @ result<- op, r0-r3 changed 5243 GET_INST_OPCODE(ip) @ extract opcode from rINST 5244 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5245 GOTO_OPCODE(ip) @ jump to next instruction 5246 /* 14-17 instructions */ 5247 5248 5249/* ------------------------------ */ 5250 .balign 64 5251.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5252/* File: armv6t2/OP_ADD_INT_2ADDR.S */ 5253/* File: armv6t2/binop2addr.S */ 5254 /* 5255 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5256 * that specifies an instruction that performs "result = r0 op r1". 5257 * This could be an ARM instruction or a function call. (If the result 5258 * comes back in a register other than r0, you can override "result".) 5259 * 5260 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5261 * vCC (r1). Useful for integer division and modulus. 5262 * 5263 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5264 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5265 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5266 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5267 */ 5268 /* binop/2addr vA, vB */ 5269 mov r3, rINST, lsr #12 @ r3<- B 5270 ubfx r9, rINST, #8, #4 @ r9<- A 5271 GET_VREG(r1, r3) @ r1<- vB 5272 GET_VREG(r0, r9) @ r0<- vA 5273 .if 0 5274 cmp r1, #0 @ is second operand zero? 5275 beq common_errDivideByZero 5276 .endif 5277 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5278 5279 @ optional op; may set condition codes 5280 add r0, r0, r1 @ r0<- op, r0-r3 changed 5281 GET_INST_OPCODE(ip) @ extract opcode from rINST 5282 SET_VREG(r0, r9) @ vAA<- r0 5283 GOTO_OPCODE(ip) @ jump to next instruction 5284 /* 10-13 instructions */ 5285 5286 5287/* ------------------------------ */ 5288 .balign 64 5289.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5290/* File: armv6t2/OP_SUB_INT_2ADDR.S */ 5291/* File: armv6t2/binop2addr.S */ 5292 /* 5293 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5294 * that specifies an instruction that performs "result = r0 op r1". 5295 * This could be an ARM instruction or a function call. (If the result 5296 * comes back in a register other than r0, you can override "result".) 5297 * 5298 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5299 * vCC (r1). Useful for integer division and modulus. 5300 * 5301 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5302 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5303 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5304 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5305 */ 5306 /* binop/2addr vA, vB */ 5307 mov r3, rINST, lsr #12 @ r3<- B 5308 ubfx r9, rINST, #8, #4 @ r9<- A 5309 GET_VREG(r1, r3) @ r1<- vB 5310 GET_VREG(r0, r9) @ r0<- vA 5311 .if 0 5312 cmp r1, #0 @ is second operand zero? 5313 beq common_errDivideByZero 5314 .endif 5315 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5316 5317 @ optional op; may set condition codes 5318 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5319 GET_INST_OPCODE(ip) @ extract opcode from rINST 5320 SET_VREG(r0, r9) @ vAA<- r0 5321 GOTO_OPCODE(ip) @ jump to next instruction 5322 /* 10-13 instructions */ 5323 5324 5325/* ------------------------------ */ 5326 .balign 64 5327.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5328/* File: armv6t2/OP_MUL_INT_2ADDR.S */ 5329/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5330/* File: armv6t2/binop2addr.S */ 5331 /* 5332 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5333 * that specifies an instruction that performs "result = r0 op r1". 5334 * This could be an ARM instruction or a function call. (If the result 5335 * comes back in a register other than r0, you can override "result".) 5336 * 5337 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5338 * vCC (r1). Useful for integer division and modulus. 5339 * 5340 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5341 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5342 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5343 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5344 */ 5345 /* binop/2addr vA, vB */ 5346 mov r3, rINST, lsr #12 @ r3<- B 5347 ubfx r9, rINST, #8, #4 @ r9<- A 5348 GET_VREG(r1, r3) @ r1<- vB 5349 GET_VREG(r0, r9) @ r0<- vA 5350 .if 0 5351 cmp r1, #0 @ is second operand zero? 5352 beq common_errDivideByZero 5353 .endif 5354 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5355 5356 @ optional op; may set condition codes 5357 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5358 GET_INST_OPCODE(ip) @ extract opcode from rINST 5359 SET_VREG(r0, r9) @ vAA<- r0 5360 GOTO_OPCODE(ip) @ jump to next instruction 5361 /* 10-13 instructions */ 5362 5363 5364/* ------------------------------ */ 5365 .balign 64 5366.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5367/* File: armv6t2/OP_DIV_INT_2ADDR.S */ 5368/* File: armv6t2/binop2addr.S */ 5369 /* 5370 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5371 * that specifies an instruction that performs "result = r0 op r1". 5372 * This could be an ARM instruction or a function call. (If the result 5373 * comes back in a register other than r0, you can override "result".) 5374 * 5375 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5376 * vCC (r1). Useful for integer division and modulus. 5377 * 5378 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5379 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5380 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5381 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5382 */ 5383 /* binop/2addr vA, vB */ 5384 mov r3, rINST, lsr #12 @ r3<- B 5385 ubfx r9, rINST, #8, #4 @ r9<- A 5386 GET_VREG(r1, r3) @ r1<- vB 5387 GET_VREG(r0, r9) @ r0<- vA 5388 .if 1 5389 cmp r1, #0 @ is second operand zero? 5390 beq common_errDivideByZero 5391 .endif 5392 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5393 5394 @ optional op; may set condition codes 5395 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5396 GET_INST_OPCODE(ip) @ extract opcode from rINST 5397 SET_VREG(r0, r9) @ vAA<- r0 5398 GOTO_OPCODE(ip) @ jump to next instruction 5399 /* 10-13 instructions */ 5400 5401 5402/* ------------------------------ */ 5403 .balign 64 5404.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5405/* File: armv6t2/OP_REM_INT_2ADDR.S */ 5406/* idivmod returns quotient in r0 and remainder in r1 */ 5407/* File: armv6t2/binop2addr.S */ 5408 /* 5409 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5410 * that specifies an instruction that performs "result = r0 op r1". 5411 * This could be an ARM instruction or a function call. (If the result 5412 * comes back in a register other than r0, you can override "result".) 5413 * 5414 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5415 * vCC (r1). Useful for integer division and modulus. 5416 * 5417 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5418 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5419 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5420 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5421 */ 5422 /* binop/2addr vA, vB */ 5423 mov r3, rINST, lsr #12 @ r3<- B 5424 ubfx r9, rINST, #8, #4 @ r9<- A 5425 GET_VREG(r1, r3) @ r1<- vB 5426 GET_VREG(r0, r9) @ r0<- vA 5427 .if 1 5428 cmp r1, #0 @ is second operand zero? 5429 beq common_errDivideByZero 5430 .endif 5431 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5432 5433 @ optional op; may set condition codes 5434 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5435 GET_INST_OPCODE(ip) @ extract opcode from rINST 5436 SET_VREG(r1, r9) @ vAA<- r1 5437 GOTO_OPCODE(ip) @ jump to next instruction 5438 /* 10-13 instructions */ 5439 5440 5441/* ------------------------------ */ 5442 .balign 64 5443.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5444/* File: armv6t2/OP_AND_INT_2ADDR.S */ 5445/* File: armv6t2/binop2addr.S */ 5446 /* 5447 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5448 * that specifies an instruction that performs "result = r0 op r1". 5449 * This could be an ARM instruction or a function call. (If the result 5450 * comes back in a register other than r0, you can override "result".) 5451 * 5452 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5453 * vCC (r1). Useful for integer division and modulus. 5454 * 5455 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5456 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5457 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5458 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5459 */ 5460 /* binop/2addr vA, vB */ 5461 mov r3, rINST, lsr #12 @ r3<- B 5462 ubfx r9, rINST, #8, #4 @ r9<- A 5463 GET_VREG(r1, r3) @ r1<- vB 5464 GET_VREG(r0, r9) @ r0<- vA 5465 .if 0 5466 cmp r1, #0 @ is second operand zero? 5467 beq common_errDivideByZero 5468 .endif 5469 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5470 5471 @ optional op; may set condition codes 5472 and r0, r0, r1 @ r0<- op, r0-r3 changed 5473 GET_INST_OPCODE(ip) @ extract opcode from rINST 5474 SET_VREG(r0, r9) @ vAA<- r0 5475 GOTO_OPCODE(ip) @ jump to next instruction 5476 /* 10-13 instructions */ 5477 5478 5479/* ------------------------------ */ 5480 .balign 64 5481.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5482/* File: armv6t2/OP_OR_INT_2ADDR.S */ 5483/* File: armv6t2/binop2addr.S */ 5484 /* 5485 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5486 * that specifies an instruction that performs "result = r0 op r1". 5487 * This could be an ARM instruction or a function call. (If the result 5488 * comes back in a register other than r0, you can override "result".) 5489 * 5490 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5491 * vCC (r1). Useful for integer division and modulus. 5492 * 5493 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5494 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5495 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5496 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5497 */ 5498 /* binop/2addr vA, vB */ 5499 mov r3, rINST, lsr #12 @ r3<- B 5500 ubfx r9, rINST, #8, #4 @ r9<- A 5501 GET_VREG(r1, r3) @ r1<- vB 5502 GET_VREG(r0, r9) @ r0<- vA 5503 .if 0 5504 cmp r1, #0 @ is second operand zero? 5505 beq common_errDivideByZero 5506 .endif 5507 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5508 5509 @ optional op; may set condition codes 5510 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5511 GET_INST_OPCODE(ip) @ extract opcode from rINST 5512 SET_VREG(r0, r9) @ vAA<- r0 5513 GOTO_OPCODE(ip) @ jump to next instruction 5514 /* 10-13 instructions */ 5515 5516 5517/* ------------------------------ */ 5518 .balign 64 5519.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5520/* File: armv6t2/OP_XOR_INT_2ADDR.S */ 5521/* File: armv6t2/binop2addr.S */ 5522 /* 5523 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5524 * that specifies an instruction that performs "result = r0 op r1". 5525 * This could be an ARM instruction or a function call. (If the result 5526 * comes back in a register other than r0, you can override "result".) 5527 * 5528 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5529 * vCC (r1). Useful for integer division and modulus. 5530 * 5531 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5532 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5533 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5534 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5535 */ 5536 /* binop/2addr vA, vB */ 5537 mov r3, rINST, lsr #12 @ r3<- B 5538 ubfx r9, rINST, #8, #4 @ r9<- A 5539 GET_VREG(r1, r3) @ r1<- vB 5540 GET_VREG(r0, r9) @ r0<- vA 5541 .if 0 5542 cmp r1, #0 @ is second operand zero? 5543 beq common_errDivideByZero 5544 .endif 5545 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5546 5547 @ optional op; may set condition codes 5548 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5549 GET_INST_OPCODE(ip) @ extract opcode from rINST 5550 SET_VREG(r0, r9) @ vAA<- r0 5551 GOTO_OPCODE(ip) @ jump to next instruction 5552 /* 10-13 instructions */ 5553 5554 5555/* ------------------------------ */ 5556 .balign 64 5557.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5558/* File: armv6t2/OP_SHL_INT_2ADDR.S */ 5559/* File: armv6t2/binop2addr.S */ 5560 /* 5561 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5562 * that specifies an instruction that performs "result = r0 op r1". 5563 * This could be an ARM instruction or a function call. (If the result 5564 * comes back in a register other than r0, you can override "result".) 5565 * 5566 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5567 * vCC (r1). Useful for integer division and modulus. 5568 * 5569 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5570 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5571 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5572 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5573 */ 5574 /* binop/2addr vA, vB */ 5575 mov r3, rINST, lsr #12 @ r3<- B 5576 ubfx r9, rINST, #8, #4 @ r9<- A 5577 GET_VREG(r1, r3) @ r1<- vB 5578 GET_VREG(r0, r9) @ r0<- vA 5579 .if 0 5580 cmp r1, #0 @ is second operand zero? 5581 beq common_errDivideByZero 5582 .endif 5583 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5584 5585 and r1, r1, #31 @ optional op; may set condition codes 5586 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5587 GET_INST_OPCODE(ip) @ extract opcode from rINST 5588 SET_VREG(r0, r9) @ vAA<- r0 5589 GOTO_OPCODE(ip) @ jump to next instruction 5590 /* 10-13 instructions */ 5591 5592 5593/* ------------------------------ */ 5594 .balign 64 5595.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5596/* File: armv6t2/OP_SHR_INT_2ADDR.S */ 5597/* File: armv6t2/binop2addr.S */ 5598 /* 5599 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5600 * that specifies an instruction that performs "result = r0 op r1". 5601 * This could be an ARM instruction or a function call. (If the result 5602 * comes back in a register other than r0, you can override "result".) 5603 * 5604 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5605 * vCC (r1). Useful for integer division and modulus. 5606 * 5607 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5608 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5609 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5610 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5611 */ 5612 /* binop/2addr vA, vB */ 5613 mov r3, rINST, lsr #12 @ r3<- B 5614 ubfx r9, rINST, #8, #4 @ r9<- A 5615 GET_VREG(r1, r3) @ r1<- vB 5616 GET_VREG(r0, r9) @ r0<- vA 5617 .if 0 5618 cmp r1, #0 @ is second operand zero? 5619 beq common_errDivideByZero 5620 .endif 5621 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5622 5623 and r1, r1, #31 @ optional op; may set condition codes 5624 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5625 GET_INST_OPCODE(ip) @ extract opcode from rINST 5626 SET_VREG(r0, r9) @ vAA<- r0 5627 GOTO_OPCODE(ip) @ jump to next instruction 5628 /* 10-13 instructions */ 5629 5630 5631/* ------------------------------ */ 5632 .balign 64 5633.L_OP_USHR_INT_2ADDR: /* 0xba */ 5634/* File: armv6t2/OP_USHR_INT_2ADDR.S */ 5635/* File: armv6t2/binop2addr.S */ 5636 /* 5637 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5638 * that specifies an instruction that performs "result = r0 op r1". 5639 * This could be an ARM instruction or a function call. (If the result 5640 * comes back in a register other than r0, you can override "result".) 5641 * 5642 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5643 * vCC (r1). Useful for integer division and modulus. 5644 * 5645 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5646 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5647 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5648 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5649 */ 5650 /* binop/2addr vA, vB */ 5651 mov r3, rINST, lsr #12 @ r3<- B 5652 ubfx r9, rINST, #8, #4 @ r9<- A 5653 GET_VREG(r1, r3) @ r1<- vB 5654 GET_VREG(r0, r9) @ r0<- vA 5655 .if 0 5656 cmp r1, #0 @ is second operand zero? 5657 beq common_errDivideByZero 5658 .endif 5659 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5660 5661 and r1, r1, #31 @ optional op; may set condition codes 5662 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5663 GET_INST_OPCODE(ip) @ extract opcode from rINST 5664 SET_VREG(r0, r9) @ vAA<- r0 5665 GOTO_OPCODE(ip) @ jump to next instruction 5666 /* 10-13 instructions */ 5667 5668 5669/* ------------------------------ */ 5670 .balign 64 5671.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5672/* File: armv6t2/OP_ADD_LONG_2ADDR.S */ 5673/* File: armv6t2/binopWide2addr.S */ 5674 /* 5675 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5676 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5677 * This could be an ARM instruction or a function call. (If the result 5678 * comes back in a register other than r0, you can override "result".) 5679 * 5680 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5681 * vCC (r1). Useful for integer division and modulus. 5682 * 5683 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5684 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5685 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5686 * rem-double/2addr 5687 */ 5688 /* binop/2addr vA, vB */ 5689 mov r1, rINST, lsr #12 @ r1<- B 5690 ubfx r9, rINST, #8, #4 @ r9<- A 5691 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5692 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5693 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5694 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5695 .if 0 5696 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5697 beq common_errDivideByZero 5698 .endif 5699 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5700 5701 adds r0, r0, r2 @ optional op; may set condition codes 5702 adc r1, r1, r3 @ result<- op, r0-r3 changed 5703 GET_INST_OPCODE(ip) @ extract opcode from rINST 5704 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5705 GOTO_OPCODE(ip) @ jump to next instruction 5706 /* 12-15 instructions */ 5707 5708 5709/* ------------------------------ */ 5710 .balign 64 5711.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5712/* File: armv6t2/OP_SUB_LONG_2ADDR.S */ 5713/* File: armv6t2/binopWide2addr.S */ 5714 /* 5715 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5716 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5717 * This could be an ARM instruction or a function call. (If the result 5718 * comes back in a register other than r0, you can override "result".) 5719 * 5720 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5721 * vCC (r1). Useful for integer division and modulus. 5722 * 5723 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5724 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5725 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5726 * rem-double/2addr 5727 */ 5728 /* binop/2addr vA, vB */ 5729 mov r1, rINST, lsr #12 @ r1<- B 5730 ubfx r9, rINST, #8, #4 @ r9<- A 5731 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5732 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5733 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5734 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5735 .if 0 5736 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5737 beq common_errDivideByZero 5738 .endif 5739 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5740 5741 subs r0, r0, r2 @ optional op; may set condition codes 5742 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5743 GET_INST_OPCODE(ip) @ extract opcode from rINST 5744 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5745 GOTO_OPCODE(ip) @ jump to next instruction 5746 /* 12-15 instructions */ 5747 5748 5749/* ------------------------------ */ 5750 .balign 64 5751.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 5752/* File: armv6t2/OP_MUL_LONG_2ADDR.S */ 5753 /* 5754 * Signed 64-bit integer multiply, "/2addr" version. 5755 * 5756 * See OP_MUL_LONG for an explanation. 5757 * 5758 * We get a little tight on registers, so to avoid looking up &fp[A] 5759 * again we stuff it into rINST. 5760 */ 5761 /* mul-long/2addr vA, vB */ 5762 mov r1, rINST, lsr #12 @ r1<- B 5763 ubfx r9, rINST, #8, #4 @ r9<- A 5764 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5765 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 5766 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5767 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 5768 mul ip, r2, r1 @ ip<- ZxW 5769 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 5770 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 5771 mov r0, rINST @ r0<- &fp[A] (free up rINST) 5772 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5773 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 5774 GET_INST_OPCODE(ip) @ extract opcode from rINST 5775 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 5776 GOTO_OPCODE(ip) @ jump to next instruction 5777 5778/* ------------------------------ */ 5779 .balign 64 5780.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 5781/* File: armv6t2/OP_DIV_LONG_2ADDR.S */ 5782/* File: armv6t2/binopWide2addr.S */ 5783 /* 5784 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5785 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5786 * This could be an ARM instruction or a function call. (If the result 5787 * comes back in a register other than r0, you can override "result".) 5788 * 5789 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5790 * vCC (r1). Useful for integer division and modulus. 5791 * 5792 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5793 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5794 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5795 * rem-double/2addr 5796 */ 5797 /* binop/2addr vA, vB */ 5798 mov r1, rINST, lsr #12 @ r1<- B 5799 ubfx r9, rINST, #8, #4 @ r9<- A 5800 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5801 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5802 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5803 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5804 .if 1 5805 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5806 beq common_errDivideByZero 5807 .endif 5808 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5809 5810 @ optional op; may set condition codes 5811 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5812 GET_INST_OPCODE(ip) @ extract opcode from rINST 5813 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5814 GOTO_OPCODE(ip) @ jump to next instruction 5815 /* 12-15 instructions */ 5816 5817 5818/* ------------------------------ */ 5819 .balign 64 5820.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5821/* File: armv6t2/OP_REM_LONG_2ADDR.S */ 5822/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 5823/* File: armv6t2/binopWide2addr.S */ 5824 /* 5825 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5826 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5827 * This could be an ARM instruction or a function call. (If the result 5828 * comes back in a register other than r0, you can override "result".) 5829 * 5830 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5831 * vCC (r1). Useful for integer division and modulus. 5832 * 5833 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5834 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5835 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5836 * rem-double/2addr 5837 */ 5838 /* binop/2addr vA, vB */ 5839 mov r1, rINST, lsr #12 @ r1<- B 5840 ubfx r9, rINST, #8, #4 @ r9<- A 5841 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5842 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5843 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5844 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5845 .if 1 5846 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5847 beq common_errDivideByZero 5848 .endif 5849 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5850 5851 @ optional op; may set condition codes 5852 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5853 GET_INST_OPCODE(ip) @ extract opcode from rINST 5854 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 5855 GOTO_OPCODE(ip) @ jump to next instruction 5856 /* 12-15 instructions */ 5857 5858 5859/* ------------------------------ */ 5860 .balign 64 5861.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 5862/* File: armv6t2/OP_AND_LONG_2ADDR.S */ 5863/* File: armv6t2/binopWide2addr.S */ 5864 /* 5865 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5866 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5867 * This could be an ARM instruction or a function call. (If the result 5868 * comes back in a register other than r0, you can override "result".) 5869 * 5870 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5871 * vCC (r1). Useful for integer division and modulus. 5872 * 5873 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5874 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5875 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5876 * rem-double/2addr 5877 */ 5878 /* binop/2addr vA, vB */ 5879 mov r1, rINST, lsr #12 @ r1<- B 5880 ubfx r9, rINST, #8, #4 @ r9<- A 5881 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5882 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5883 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5884 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5885 .if 0 5886 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5887 beq common_errDivideByZero 5888 .endif 5889 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5890 5891 and r0, r0, r2 @ optional op; may set condition codes 5892 and r1, r1, r3 @ result<- op, r0-r3 changed 5893 GET_INST_OPCODE(ip) @ extract opcode from rINST 5894 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5895 GOTO_OPCODE(ip) @ jump to next instruction 5896 /* 12-15 instructions */ 5897 5898 5899/* ------------------------------ */ 5900 .balign 64 5901.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 5902/* File: armv6t2/OP_OR_LONG_2ADDR.S */ 5903/* File: armv6t2/binopWide2addr.S */ 5904 /* 5905 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5906 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5907 * This could be an ARM instruction or a function call. (If the result 5908 * comes back in a register other than r0, you can override "result".) 5909 * 5910 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5911 * vCC (r1). Useful for integer division and modulus. 5912 * 5913 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5914 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5915 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5916 * rem-double/2addr 5917 */ 5918 /* binop/2addr vA, vB */ 5919 mov r1, rINST, lsr #12 @ r1<- B 5920 ubfx r9, rINST, #8, #4 @ r9<- A 5921 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5922 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5923 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5924 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5925 .if 0 5926 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5927 beq common_errDivideByZero 5928 .endif 5929 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5930 5931 orr r0, r0, r2 @ optional op; may set condition codes 5932 orr r1, r1, r3 @ result<- op, r0-r3 changed 5933 GET_INST_OPCODE(ip) @ extract opcode from rINST 5934 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5935 GOTO_OPCODE(ip) @ jump to next instruction 5936 /* 12-15 instructions */ 5937 5938 5939/* ------------------------------ */ 5940 .balign 64 5941.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 5942/* File: armv6t2/OP_XOR_LONG_2ADDR.S */ 5943/* File: armv6t2/binopWide2addr.S */ 5944 /* 5945 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5946 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5947 * This could be an ARM instruction or a function call. (If the result 5948 * comes back in a register other than r0, you can override "result".) 5949 * 5950 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5951 * vCC (r1). Useful for integer division and modulus. 5952 * 5953 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5954 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5955 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5956 * rem-double/2addr 5957 */ 5958 /* binop/2addr vA, vB */ 5959 mov r1, rINST, lsr #12 @ r1<- B 5960 ubfx r9, rINST, #8, #4 @ r9<- A 5961 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5962 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5963 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5964 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5965 .if 0 5966 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5967 beq common_errDivideByZero 5968 .endif 5969 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5970 5971 eor r0, r0, r2 @ optional op; may set condition codes 5972 eor r1, r1, r3 @ result<- op, r0-r3 changed 5973 GET_INST_OPCODE(ip) @ extract opcode from rINST 5974 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5975 GOTO_OPCODE(ip) @ jump to next instruction 5976 /* 12-15 instructions */ 5977 5978 5979/* ------------------------------ */ 5980 .balign 64 5981.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 5982/* File: armv6t2/OP_SHL_LONG_2ADDR.S */ 5983 /* 5984 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 5985 * 32-bit shift distance. 5986 */ 5987 /* shl-long/2addr vA, vB */ 5988 mov r3, rINST, lsr #12 @ r3<- B 5989 ubfx r9, rINST, #8, #4 @ r9<- A 5990 GET_VREG(r2, r3) @ r2<- vB 5991 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5992 and r2, r2, #63 @ r2<- r2 & 0x3f 5993 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5994 5995 mov r1, r1, asl r2 @ r1<- r1 << r2 5996 rsb r3, r2, #32 @ r3<- 32 - r2 5997 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 5998 subs ip, r2, #32 @ ip<- r2 - 32 5999 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6000 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 6001 mov r0, r0, asl r2 @ r0<- r0 << r2 6002 b .LOP_SHL_LONG_2ADDR_finish 6003 6004/* ------------------------------ */ 6005 .balign 64 6006.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 6007/* File: armv6t2/OP_SHR_LONG_2ADDR.S */ 6008 /* 6009 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6010 * 32-bit shift distance. 6011 */ 6012 /* shr-long/2addr vA, vB */ 6013 mov r3, rINST, lsr #12 @ r3<- B 6014 ubfx r9, rINST, #8, #4 @ r9<- A 6015 GET_VREG(r2, r3) @ r2<- vB 6016 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6017 and r2, r2, #63 @ r2<- r2 & 0x3f 6018 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6019 6020 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6021 rsb r3, r2, #32 @ r3<- 32 - r2 6022 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6023 subs ip, r2, #32 @ ip<- r2 - 32 6024 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6025 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6026 mov r1, r1, asr r2 @ r1<- r1 >> r2 6027 b .LOP_SHR_LONG_2ADDR_finish 6028 6029/* ------------------------------ */ 6030 .balign 64 6031.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6032/* File: armv6t2/OP_USHR_LONG_2ADDR.S */ 6033 /* 6034 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6035 * 32-bit shift distance. 6036 */ 6037 /* ushr-long/2addr vA, vB */ 6038 mov r3, rINST, lsr #12 @ r3<- B 6039 ubfx r9, rINST, #8, #4 @ r9<- A 6040 GET_VREG(r2, r3) @ r2<- vB 6041 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6042 and r2, r2, #63 @ r2<- r2 & 0x3f 6043 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6044 6045 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6046 rsb r3, r2, #32 @ r3<- 32 - r2 6047 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6048 subs ip, r2, #32 @ ip<- r2 - 32 6049 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6050 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6051 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6052 b .LOP_USHR_LONG_2ADDR_finish 6053 6054/* ------------------------------ */ 6055 .balign 64 6056.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6057/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */ 6058/* File: arm-vfp/fbinop2addr.S */ 6059 /* 6060 * Generic 32-bit floating point "/2addr" binary operation. Provide 6061 * an "instr" line that specifies an instruction that performs 6062 * "s2 = s0 op s1". 6063 * 6064 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6065 */ 6066 /* binop/2addr vA, vB */ 6067 mov r3, rINST, lsr #12 @ r3<- B 6068 mov r9, rINST, lsr #8 @ r9<- A+ 6069 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6070 and r9, r9, #15 @ r9<- A 6071 flds s1, [r3] @ s1<- vB 6072 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6073 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6074 flds s0, [r9] @ s0<- vA 6075 6076 fadds s2, s0, s1 @ s2<- op 6077 GET_INST_OPCODE(ip) @ extract opcode from rINST 6078 fsts s2, [r9] @ vAA<- s2 6079 GOTO_OPCODE(ip) @ jump to next instruction 6080 6081 6082/* ------------------------------ */ 6083 .balign 64 6084.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6085/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */ 6086/* File: arm-vfp/fbinop2addr.S */ 6087 /* 6088 * Generic 32-bit floating point "/2addr" binary operation. Provide 6089 * an "instr" line that specifies an instruction that performs 6090 * "s2 = s0 op s1". 6091 * 6092 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6093 */ 6094 /* binop/2addr vA, vB */ 6095 mov r3, rINST, lsr #12 @ r3<- B 6096 mov r9, rINST, lsr #8 @ r9<- A+ 6097 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6098 and r9, r9, #15 @ r9<- A 6099 flds s1, [r3] @ s1<- vB 6100 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6101 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6102 flds s0, [r9] @ s0<- vA 6103 6104 fsubs s2, s0, s1 @ s2<- op 6105 GET_INST_OPCODE(ip) @ extract opcode from rINST 6106 fsts s2, [r9] @ vAA<- s2 6107 GOTO_OPCODE(ip) @ jump to next instruction 6108 6109 6110/* ------------------------------ */ 6111 .balign 64 6112.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6113/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */ 6114/* File: arm-vfp/fbinop2addr.S */ 6115 /* 6116 * Generic 32-bit floating point "/2addr" binary operation. Provide 6117 * an "instr" line that specifies an instruction that performs 6118 * "s2 = s0 op s1". 6119 * 6120 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6121 */ 6122 /* binop/2addr vA, vB */ 6123 mov r3, rINST, lsr #12 @ r3<- B 6124 mov r9, rINST, lsr #8 @ r9<- A+ 6125 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6126 and r9, r9, #15 @ r9<- A 6127 flds s1, [r3] @ s1<- vB 6128 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6129 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6130 flds s0, [r9] @ s0<- vA 6131 6132 fmuls s2, s0, s1 @ s2<- op 6133 GET_INST_OPCODE(ip) @ extract opcode from rINST 6134 fsts s2, [r9] @ vAA<- s2 6135 GOTO_OPCODE(ip) @ jump to next instruction 6136 6137 6138/* ------------------------------ */ 6139 .balign 64 6140.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6141/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */ 6142/* File: arm-vfp/fbinop2addr.S */ 6143 /* 6144 * Generic 32-bit floating point "/2addr" binary operation. Provide 6145 * an "instr" line that specifies an instruction that performs 6146 * "s2 = s0 op s1". 6147 * 6148 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6149 */ 6150 /* binop/2addr vA, vB */ 6151 mov r3, rINST, lsr #12 @ r3<- B 6152 mov r9, rINST, lsr #8 @ r9<- A+ 6153 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6154 and r9, r9, #15 @ r9<- A 6155 flds s1, [r3] @ s1<- vB 6156 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6157 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6158 flds s0, [r9] @ s0<- vA 6159 6160 fdivs s2, s0, s1 @ s2<- op 6161 GET_INST_OPCODE(ip) @ extract opcode from rINST 6162 fsts s2, [r9] @ vAA<- s2 6163 GOTO_OPCODE(ip) @ jump to next instruction 6164 6165 6166/* ------------------------------ */ 6167 .balign 64 6168.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6169/* File: armv6t2/OP_REM_FLOAT_2ADDR.S */ 6170/* EABI doesn't define a float remainder function, but libm does */ 6171/* File: armv6t2/binop2addr.S */ 6172 /* 6173 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6174 * that specifies an instruction that performs "result = r0 op r1". 6175 * This could be an ARM instruction or a function call. (If the result 6176 * comes back in a register other than r0, you can override "result".) 6177 * 6178 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6179 * vCC (r1). Useful for integer division and modulus. 6180 * 6181 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6182 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6183 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6184 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6185 */ 6186 /* binop/2addr vA, vB */ 6187 mov r3, rINST, lsr #12 @ r3<- B 6188 ubfx r9, rINST, #8, #4 @ r9<- A 6189 GET_VREG(r1, r3) @ r1<- vB 6190 GET_VREG(r0, r9) @ r0<- vA 6191 .if 0 6192 cmp r1, #0 @ is second operand zero? 6193 beq common_errDivideByZero 6194 .endif 6195 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6196 6197 @ optional op; may set condition codes 6198 bl fmodf @ r0<- op, r0-r3 changed 6199 GET_INST_OPCODE(ip) @ extract opcode from rINST 6200 SET_VREG(r0, r9) @ vAA<- r0 6201 GOTO_OPCODE(ip) @ jump to next instruction 6202 /* 10-13 instructions */ 6203 6204 6205/* ------------------------------ */ 6206 .balign 64 6207.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6208/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */ 6209/* File: arm-vfp/fbinopWide2addr.S */ 6210 /* 6211 * Generic 64-bit floating point "/2addr" binary operation. Provide 6212 * an "instr" line that specifies an instruction that performs 6213 * "d2 = d0 op d1". 6214 * 6215 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6216 * div-double/2addr 6217 */ 6218 /* binop/2addr vA, vB */ 6219 mov r3, rINST, lsr #12 @ r3<- B 6220 mov r9, rINST, lsr #8 @ r9<- A+ 6221 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6222 and r9, r9, #15 @ r9<- A 6223 fldd d1, [r3] @ d1<- vB 6224 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6225 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6226 fldd d0, [r9] @ d0<- vA 6227 6228 faddd d2, d0, d1 @ d2<- op 6229 GET_INST_OPCODE(ip) @ extract opcode from rINST 6230 fstd d2, [r9] @ vAA<- d2 6231 GOTO_OPCODE(ip) @ jump to next instruction 6232 6233 6234/* ------------------------------ */ 6235 .balign 64 6236.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6237/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */ 6238/* File: arm-vfp/fbinopWide2addr.S */ 6239 /* 6240 * Generic 64-bit floating point "/2addr" binary operation. Provide 6241 * an "instr" line that specifies an instruction that performs 6242 * "d2 = d0 op d1". 6243 * 6244 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6245 * div-double/2addr 6246 */ 6247 /* binop/2addr vA, vB */ 6248 mov r3, rINST, lsr #12 @ r3<- B 6249 mov r9, rINST, lsr #8 @ r9<- A+ 6250 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6251 and r9, r9, #15 @ r9<- A 6252 fldd d1, [r3] @ d1<- vB 6253 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6254 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6255 fldd d0, [r9] @ d0<- vA 6256 6257 fsubd d2, d0, d1 @ d2<- op 6258 GET_INST_OPCODE(ip) @ extract opcode from rINST 6259 fstd d2, [r9] @ vAA<- d2 6260 GOTO_OPCODE(ip) @ jump to next instruction 6261 6262 6263/* ------------------------------ */ 6264 .balign 64 6265.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6266/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */ 6267/* File: arm-vfp/fbinopWide2addr.S */ 6268 /* 6269 * Generic 64-bit floating point "/2addr" binary operation. Provide 6270 * an "instr" line that specifies an instruction that performs 6271 * "d2 = d0 op d1". 6272 * 6273 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6274 * div-double/2addr 6275 */ 6276 /* binop/2addr vA, vB */ 6277 mov r3, rINST, lsr #12 @ r3<- B 6278 mov r9, rINST, lsr #8 @ r9<- A+ 6279 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6280 and r9, r9, #15 @ r9<- A 6281 fldd d1, [r3] @ d1<- vB 6282 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6283 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6284 fldd d0, [r9] @ d0<- vA 6285 6286 fmuld d2, d0, d1 @ d2<- op 6287 GET_INST_OPCODE(ip) @ extract opcode from rINST 6288 fstd d2, [r9] @ vAA<- d2 6289 GOTO_OPCODE(ip) @ jump to next instruction 6290 6291 6292/* ------------------------------ */ 6293 .balign 64 6294.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6295/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */ 6296/* File: arm-vfp/fbinopWide2addr.S */ 6297 /* 6298 * Generic 64-bit floating point "/2addr" binary operation. Provide 6299 * an "instr" line that specifies an instruction that performs 6300 * "d2 = d0 op d1". 6301 * 6302 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6303 * div-double/2addr 6304 */ 6305 /* binop/2addr vA, vB */ 6306 mov r3, rINST, lsr #12 @ r3<- B 6307 mov r9, rINST, lsr #8 @ r9<- A+ 6308 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6309 and r9, r9, #15 @ r9<- A 6310 fldd d1, [r3] @ d1<- vB 6311 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6312 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6313 fldd d0, [r9] @ d0<- vA 6314 6315 fdivd d2, d0, d1 @ d2<- op 6316 GET_INST_OPCODE(ip) @ extract opcode from rINST 6317 fstd d2, [r9] @ vAA<- d2 6318 GOTO_OPCODE(ip) @ jump to next instruction 6319 6320 6321/* ------------------------------ */ 6322 .balign 64 6323.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6324/* File: armv6t2/OP_REM_DOUBLE_2ADDR.S */ 6325/* EABI doesn't define a double remainder function, but libm does */ 6326/* File: armv6t2/binopWide2addr.S */ 6327 /* 6328 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6329 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6330 * This could be an ARM instruction or a function call. (If the result 6331 * comes back in a register other than r0, you can override "result".) 6332 * 6333 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6334 * vCC (r1). Useful for integer division and modulus. 6335 * 6336 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6337 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6338 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6339 * rem-double/2addr 6340 */ 6341 /* binop/2addr vA, vB */ 6342 mov r1, rINST, lsr #12 @ r1<- B 6343 ubfx r9, rINST, #8, #4 @ r9<- A 6344 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6345 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6346 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6347 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6348 .if 0 6349 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6350 beq common_errDivideByZero 6351 .endif 6352 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6353 6354 @ optional op; may set condition codes 6355 bl fmod @ result<- op, r0-r3 changed 6356 GET_INST_OPCODE(ip) @ extract opcode from rINST 6357 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6358 GOTO_OPCODE(ip) @ jump to next instruction 6359 /* 12-15 instructions */ 6360 6361 6362/* ------------------------------ */ 6363 .balign 64 6364.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6365/* File: armv6t2/OP_ADD_INT_LIT16.S */ 6366/* File: armv6t2/binopLit16.S */ 6367 /* 6368 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6369 * that specifies an instruction that performs "result = r0 op r1". 6370 * This could be an ARM instruction or a function call. (If the result 6371 * comes back in a register other than r0, you can override "result".) 6372 * 6373 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6374 * vCC (r1). Useful for integer division and modulus. 6375 * 6376 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6377 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6378 */ 6379 /* binop/lit16 vA, vB, #+CCCC */ 6380 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6381 mov r2, rINST, lsr #12 @ r2<- B 6382 ubfx r9, rINST, #8, #4 @ r9<- A 6383 GET_VREG(r0, r2) @ r0<- vB 6384 .if 0 6385 cmp r1, #0 @ is second operand zero? 6386 beq common_errDivideByZero 6387 .endif 6388 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6389 6390 add r0, r0, r1 @ r0<- op, r0-r3 changed 6391 GET_INST_OPCODE(ip) @ extract opcode from rINST 6392 SET_VREG(r0, r9) @ vAA<- r0 6393 GOTO_OPCODE(ip) @ jump to next instruction 6394 /* 10-13 instructions */ 6395 6396 6397/* ------------------------------ */ 6398 .balign 64 6399.L_OP_RSUB_INT: /* 0xd1 */ 6400/* File: armv6t2/OP_RSUB_INT.S */ 6401/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6402/* File: armv6t2/binopLit16.S */ 6403 /* 6404 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6405 * that specifies an instruction that performs "result = r0 op r1". 6406 * This could be an ARM instruction or a function call. (If the result 6407 * comes back in a register other than r0, you can override "result".) 6408 * 6409 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6410 * vCC (r1). Useful for integer division and modulus. 6411 * 6412 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6413 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6414 */ 6415 /* binop/lit16 vA, vB, #+CCCC */ 6416 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6417 mov r2, rINST, lsr #12 @ r2<- B 6418 ubfx r9, rINST, #8, #4 @ r9<- A 6419 GET_VREG(r0, r2) @ r0<- vB 6420 .if 0 6421 cmp r1, #0 @ is second operand zero? 6422 beq common_errDivideByZero 6423 .endif 6424 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6425 6426 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6427 GET_INST_OPCODE(ip) @ extract opcode from rINST 6428 SET_VREG(r0, r9) @ vAA<- r0 6429 GOTO_OPCODE(ip) @ jump to next instruction 6430 /* 10-13 instructions */ 6431 6432 6433/* ------------------------------ */ 6434 .balign 64 6435.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6436/* File: armv6t2/OP_MUL_INT_LIT16.S */ 6437/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6438/* File: armv6t2/binopLit16.S */ 6439 /* 6440 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6441 * that specifies an instruction that performs "result = r0 op r1". 6442 * This could be an ARM instruction or a function call. (If the result 6443 * comes back in a register other than r0, you can override "result".) 6444 * 6445 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6446 * vCC (r1). Useful for integer division and modulus. 6447 * 6448 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6449 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6450 */ 6451 /* binop/lit16 vA, vB, #+CCCC */ 6452 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6453 mov r2, rINST, lsr #12 @ r2<- B 6454 ubfx r9, rINST, #8, #4 @ r9<- A 6455 GET_VREG(r0, r2) @ r0<- vB 6456 .if 0 6457 cmp r1, #0 @ is second operand zero? 6458 beq common_errDivideByZero 6459 .endif 6460 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6461 6462 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6463 GET_INST_OPCODE(ip) @ extract opcode from rINST 6464 SET_VREG(r0, r9) @ vAA<- r0 6465 GOTO_OPCODE(ip) @ jump to next instruction 6466 /* 10-13 instructions */ 6467 6468 6469/* ------------------------------ */ 6470 .balign 64 6471.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6472/* File: armv6t2/OP_DIV_INT_LIT16.S */ 6473/* File: armv6t2/binopLit16.S */ 6474 /* 6475 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6476 * that specifies an instruction that performs "result = r0 op r1". 6477 * This could be an ARM instruction or a function call. (If the result 6478 * comes back in a register other than r0, you can override "result".) 6479 * 6480 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6481 * vCC (r1). Useful for integer division and modulus. 6482 * 6483 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6484 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6485 */ 6486 /* binop/lit16 vA, vB, #+CCCC */ 6487 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6488 mov r2, rINST, lsr #12 @ r2<- B 6489 ubfx r9, rINST, #8, #4 @ r9<- A 6490 GET_VREG(r0, r2) @ r0<- vB 6491 .if 1 6492 cmp r1, #0 @ is second operand zero? 6493 beq common_errDivideByZero 6494 .endif 6495 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6496 6497 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6498 GET_INST_OPCODE(ip) @ extract opcode from rINST 6499 SET_VREG(r0, r9) @ vAA<- r0 6500 GOTO_OPCODE(ip) @ jump to next instruction 6501 /* 10-13 instructions */ 6502 6503 6504/* ------------------------------ */ 6505 .balign 64 6506.L_OP_REM_INT_LIT16: /* 0xd4 */ 6507/* File: armv6t2/OP_REM_INT_LIT16.S */ 6508/* idivmod returns quotient in r0 and remainder in r1 */ 6509/* File: armv6t2/binopLit16.S */ 6510 /* 6511 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6512 * that specifies an instruction that performs "result = r0 op r1". 6513 * This could be an ARM instruction or a function call. (If the result 6514 * comes back in a register other than r0, you can override "result".) 6515 * 6516 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6517 * vCC (r1). Useful for integer division and modulus. 6518 * 6519 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6520 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6521 */ 6522 /* binop/lit16 vA, vB, #+CCCC */ 6523 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6524 mov r2, rINST, lsr #12 @ r2<- B 6525 ubfx r9, rINST, #8, #4 @ r9<- A 6526 GET_VREG(r0, r2) @ r0<- vB 6527 .if 1 6528 cmp r1, #0 @ is second operand zero? 6529 beq common_errDivideByZero 6530 .endif 6531 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6532 6533 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6534 GET_INST_OPCODE(ip) @ extract opcode from rINST 6535 SET_VREG(r1, r9) @ vAA<- r1 6536 GOTO_OPCODE(ip) @ jump to next instruction 6537 /* 10-13 instructions */ 6538 6539 6540/* ------------------------------ */ 6541 .balign 64 6542.L_OP_AND_INT_LIT16: /* 0xd5 */ 6543/* File: armv6t2/OP_AND_INT_LIT16.S */ 6544/* File: armv6t2/binopLit16.S */ 6545 /* 6546 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6547 * that specifies an instruction that performs "result = r0 op r1". 6548 * This could be an ARM instruction or a function call. (If the result 6549 * comes back in a register other than r0, you can override "result".) 6550 * 6551 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6552 * vCC (r1). Useful for integer division and modulus. 6553 * 6554 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6555 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6556 */ 6557 /* binop/lit16 vA, vB, #+CCCC */ 6558 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6559 mov r2, rINST, lsr #12 @ r2<- B 6560 ubfx r9, rINST, #8, #4 @ r9<- A 6561 GET_VREG(r0, r2) @ r0<- vB 6562 .if 0 6563 cmp r1, #0 @ is second operand zero? 6564 beq common_errDivideByZero 6565 .endif 6566 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6567 6568 and r0, r0, r1 @ r0<- op, r0-r3 changed 6569 GET_INST_OPCODE(ip) @ extract opcode from rINST 6570 SET_VREG(r0, r9) @ vAA<- r0 6571 GOTO_OPCODE(ip) @ jump to next instruction 6572 /* 10-13 instructions */ 6573 6574 6575/* ------------------------------ */ 6576 .balign 64 6577.L_OP_OR_INT_LIT16: /* 0xd6 */ 6578/* File: armv6t2/OP_OR_INT_LIT16.S */ 6579/* File: armv6t2/binopLit16.S */ 6580 /* 6581 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6582 * that specifies an instruction that performs "result = r0 op r1". 6583 * This could be an ARM instruction or a function call. (If the result 6584 * comes back in a register other than r0, you can override "result".) 6585 * 6586 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6587 * vCC (r1). Useful for integer division and modulus. 6588 * 6589 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6590 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6591 */ 6592 /* binop/lit16 vA, vB, #+CCCC */ 6593 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6594 mov r2, rINST, lsr #12 @ r2<- B 6595 ubfx r9, rINST, #8, #4 @ r9<- A 6596 GET_VREG(r0, r2) @ r0<- vB 6597 .if 0 6598 cmp r1, #0 @ is second operand zero? 6599 beq common_errDivideByZero 6600 .endif 6601 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6602 6603 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6604 GET_INST_OPCODE(ip) @ extract opcode from rINST 6605 SET_VREG(r0, r9) @ vAA<- r0 6606 GOTO_OPCODE(ip) @ jump to next instruction 6607 /* 10-13 instructions */ 6608 6609 6610/* ------------------------------ */ 6611 .balign 64 6612.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6613/* File: armv6t2/OP_XOR_INT_LIT16.S */ 6614/* File: armv6t2/binopLit16.S */ 6615 /* 6616 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6617 * that specifies an instruction that performs "result = r0 op r1". 6618 * This could be an ARM instruction or a function call. (If the result 6619 * comes back in a register other than r0, you can override "result".) 6620 * 6621 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6622 * vCC (r1). Useful for integer division and modulus. 6623 * 6624 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6625 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6626 */ 6627 /* binop/lit16 vA, vB, #+CCCC */ 6628 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6629 mov r2, rINST, lsr #12 @ r2<- B 6630 ubfx r9, rINST, #8, #4 @ r9<- A 6631 GET_VREG(r0, r2) @ r0<- vB 6632 .if 0 6633 cmp r1, #0 @ is second operand zero? 6634 beq common_errDivideByZero 6635 .endif 6636 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6637 6638 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6639 GET_INST_OPCODE(ip) @ extract opcode from rINST 6640 SET_VREG(r0, r9) @ vAA<- r0 6641 GOTO_OPCODE(ip) @ jump to next instruction 6642 /* 10-13 instructions */ 6643 6644 6645/* ------------------------------ */ 6646 .balign 64 6647.L_OP_ADD_INT_LIT8: /* 0xd8 */ 6648/* File: armv5te/OP_ADD_INT_LIT8.S */ 6649/* File: armv5te/binopLit8.S */ 6650 /* 6651 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6652 * that specifies an instruction that performs "result = r0 op r1". 6653 * This could be an ARM instruction or a function call. (If the result 6654 * comes back in a register other than r0, you can override "result".) 6655 * 6656 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6657 * vCC (r1). Useful for integer division and modulus. 6658 * 6659 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6660 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6661 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6662 */ 6663 /* binop/lit8 vAA, vBB, #+CC */ 6664 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6665 mov r9, rINST, lsr #8 @ r9<- AA 6666 and r2, r3, #255 @ r2<- BB 6667 GET_VREG(r0, r2) @ r0<- vBB 6668 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6669 .if 0 6670 @cmp r1, #0 @ is second operand zero? 6671 beq common_errDivideByZero 6672 .endif 6673 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6674 6675 @ optional op; may set condition codes 6676 add r0, r0, r1 @ r0<- op, r0-r3 changed 6677 GET_INST_OPCODE(ip) @ extract opcode from rINST 6678 SET_VREG(r0, r9) @ vAA<- r0 6679 GOTO_OPCODE(ip) @ jump to next instruction 6680 /* 10-12 instructions */ 6681 6682 6683/* ------------------------------ */ 6684 .balign 64 6685.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 6686/* File: armv5te/OP_RSUB_INT_LIT8.S */ 6687/* File: armv5te/binopLit8.S */ 6688 /* 6689 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6690 * that specifies an instruction that performs "result = r0 op r1". 6691 * This could be an ARM instruction or a function call. (If the result 6692 * comes back in a register other than r0, you can override "result".) 6693 * 6694 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6695 * vCC (r1). Useful for integer division and modulus. 6696 * 6697 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6698 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6699 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6700 */ 6701 /* binop/lit8 vAA, vBB, #+CC */ 6702 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6703 mov r9, rINST, lsr #8 @ r9<- AA 6704 and r2, r3, #255 @ r2<- BB 6705 GET_VREG(r0, r2) @ r0<- vBB 6706 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6707 .if 0 6708 @cmp r1, #0 @ is second operand zero? 6709 beq common_errDivideByZero 6710 .endif 6711 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6712 6713 @ optional op; may set condition codes 6714 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6715 GET_INST_OPCODE(ip) @ extract opcode from rINST 6716 SET_VREG(r0, r9) @ vAA<- r0 6717 GOTO_OPCODE(ip) @ jump to next instruction 6718 /* 10-12 instructions */ 6719 6720 6721/* ------------------------------ */ 6722 .balign 64 6723.L_OP_MUL_INT_LIT8: /* 0xda */ 6724/* File: armv5te/OP_MUL_INT_LIT8.S */ 6725/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6726/* File: armv5te/binopLit8.S */ 6727 /* 6728 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6729 * that specifies an instruction that performs "result = r0 op r1". 6730 * This could be an ARM instruction or a function call. (If the result 6731 * comes back in a register other than r0, you can override "result".) 6732 * 6733 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6734 * vCC (r1). Useful for integer division and modulus. 6735 * 6736 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6737 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6738 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6739 */ 6740 /* binop/lit8 vAA, vBB, #+CC */ 6741 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6742 mov r9, rINST, lsr #8 @ r9<- AA 6743 and r2, r3, #255 @ r2<- BB 6744 GET_VREG(r0, r2) @ r0<- vBB 6745 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6746 .if 0 6747 @cmp r1, #0 @ is second operand zero? 6748 beq common_errDivideByZero 6749 .endif 6750 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6751 6752 @ optional op; may set condition codes 6753 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6754 GET_INST_OPCODE(ip) @ extract opcode from rINST 6755 SET_VREG(r0, r9) @ vAA<- r0 6756 GOTO_OPCODE(ip) @ jump to next instruction 6757 /* 10-12 instructions */ 6758 6759 6760/* ------------------------------ */ 6761 .balign 64 6762.L_OP_DIV_INT_LIT8: /* 0xdb */ 6763/* File: armv5te/OP_DIV_INT_LIT8.S */ 6764/* File: armv5te/binopLit8.S */ 6765 /* 6766 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6767 * that specifies an instruction that performs "result = r0 op r1". 6768 * This could be an ARM instruction or a function call. (If the result 6769 * comes back in a register other than r0, you can override "result".) 6770 * 6771 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6772 * vCC (r1). Useful for integer division and modulus. 6773 * 6774 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6775 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6776 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6777 */ 6778 /* binop/lit8 vAA, vBB, #+CC */ 6779 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6780 mov r9, rINST, lsr #8 @ r9<- AA 6781 and r2, r3, #255 @ r2<- BB 6782 GET_VREG(r0, r2) @ r0<- vBB 6783 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6784 .if 1 6785 @cmp r1, #0 @ is second operand zero? 6786 beq common_errDivideByZero 6787 .endif 6788 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6789 6790 @ optional op; may set condition codes 6791 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6792 GET_INST_OPCODE(ip) @ extract opcode from rINST 6793 SET_VREG(r0, r9) @ vAA<- r0 6794 GOTO_OPCODE(ip) @ jump to next instruction 6795 /* 10-12 instructions */ 6796 6797 6798/* ------------------------------ */ 6799 .balign 64 6800.L_OP_REM_INT_LIT8: /* 0xdc */ 6801/* File: armv5te/OP_REM_INT_LIT8.S */ 6802/* idivmod returns quotient in r0 and remainder in r1 */ 6803/* File: armv5te/binopLit8.S */ 6804 /* 6805 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6806 * that specifies an instruction that performs "result = r0 op r1". 6807 * This could be an ARM instruction or a function call. (If the result 6808 * comes back in a register other than r0, you can override "result".) 6809 * 6810 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6811 * vCC (r1). Useful for integer division and modulus. 6812 * 6813 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6814 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6815 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6816 */ 6817 /* binop/lit8 vAA, vBB, #+CC */ 6818 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6819 mov r9, rINST, lsr #8 @ r9<- AA 6820 and r2, r3, #255 @ r2<- BB 6821 GET_VREG(r0, r2) @ r0<- vBB 6822 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6823 .if 1 6824 @cmp r1, #0 @ is second operand zero? 6825 beq common_errDivideByZero 6826 .endif 6827 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6828 6829 @ optional op; may set condition codes 6830 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6831 GET_INST_OPCODE(ip) @ extract opcode from rINST 6832 SET_VREG(r1, r9) @ vAA<- r1 6833 GOTO_OPCODE(ip) @ jump to next instruction 6834 /* 10-12 instructions */ 6835 6836 6837/* ------------------------------ */ 6838 .balign 64 6839.L_OP_AND_INT_LIT8: /* 0xdd */ 6840/* File: armv5te/OP_AND_INT_LIT8.S */ 6841/* File: armv5te/binopLit8.S */ 6842 /* 6843 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6844 * that specifies an instruction that performs "result = r0 op r1". 6845 * This could be an ARM instruction or a function call. (If the result 6846 * comes back in a register other than r0, you can override "result".) 6847 * 6848 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6849 * vCC (r1). Useful for integer division and modulus. 6850 * 6851 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6852 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6853 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6854 */ 6855 /* binop/lit8 vAA, vBB, #+CC */ 6856 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6857 mov r9, rINST, lsr #8 @ r9<- AA 6858 and r2, r3, #255 @ r2<- BB 6859 GET_VREG(r0, r2) @ r0<- vBB 6860 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6861 .if 0 6862 @cmp r1, #0 @ is second operand zero? 6863 beq common_errDivideByZero 6864 .endif 6865 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6866 6867 @ optional op; may set condition codes 6868 and r0, r0, r1 @ r0<- op, r0-r3 changed 6869 GET_INST_OPCODE(ip) @ extract opcode from rINST 6870 SET_VREG(r0, r9) @ vAA<- r0 6871 GOTO_OPCODE(ip) @ jump to next instruction 6872 /* 10-12 instructions */ 6873 6874 6875/* ------------------------------ */ 6876 .balign 64 6877.L_OP_OR_INT_LIT8: /* 0xde */ 6878/* File: armv5te/OP_OR_INT_LIT8.S */ 6879/* File: armv5te/binopLit8.S */ 6880 /* 6881 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6882 * that specifies an instruction that performs "result = r0 op r1". 6883 * This could be an ARM instruction or a function call. (If the result 6884 * comes back in a register other than r0, you can override "result".) 6885 * 6886 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6887 * vCC (r1). Useful for integer division and modulus. 6888 * 6889 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6890 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6891 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6892 */ 6893 /* binop/lit8 vAA, vBB, #+CC */ 6894 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6895 mov r9, rINST, lsr #8 @ r9<- AA 6896 and r2, r3, #255 @ r2<- BB 6897 GET_VREG(r0, r2) @ r0<- vBB 6898 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6899 .if 0 6900 @cmp r1, #0 @ is second operand zero? 6901 beq common_errDivideByZero 6902 .endif 6903 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6904 6905 @ optional op; may set condition codes 6906 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6907 GET_INST_OPCODE(ip) @ extract opcode from rINST 6908 SET_VREG(r0, r9) @ vAA<- r0 6909 GOTO_OPCODE(ip) @ jump to next instruction 6910 /* 10-12 instructions */ 6911 6912 6913/* ------------------------------ */ 6914 .balign 64 6915.L_OP_XOR_INT_LIT8: /* 0xdf */ 6916/* File: armv5te/OP_XOR_INT_LIT8.S */ 6917/* File: armv5te/binopLit8.S */ 6918 /* 6919 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6920 * that specifies an instruction that performs "result = r0 op r1". 6921 * This could be an ARM instruction or a function call. (If the result 6922 * comes back in a register other than r0, you can override "result".) 6923 * 6924 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6925 * vCC (r1). Useful for integer division and modulus. 6926 * 6927 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6928 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6929 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6930 */ 6931 /* binop/lit8 vAA, vBB, #+CC */ 6932 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6933 mov r9, rINST, lsr #8 @ r9<- AA 6934 and r2, r3, #255 @ r2<- BB 6935 GET_VREG(r0, r2) @ r0<- vBB 6936 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6937 .if 0 6938 @cmp r1, #0 @ is second operand zero? 6939 beq common_errDivideByZero 6940 .endif 6941 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6942 6943 @ optional op; may set condition codes 6944 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6945 GET_INST_OPCODE(ip) @ extract opcode from rINST 6946 SET_VREG(r0, r9) @ vAA<- r0 6947 GOTO_OPCODE(ip) @ jump to next instruction 6948 /* 10-12 instructions */ 6949 6950 6951/* ------------------------------ */ 6952 .balign 64 6953.L_OP_SHL_INT_LIT8: /* 0xe0 */ 6954/* File: armv5te/OP_SHL_INT_LIT8.S */ 6955/* File: armv5te/binopLit8.S */ 6956 /* 6957 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6958 * that specifies an instruction that performs "result = r0 op r1". 6959 * This could be an ARM instruction or a function call. (If the result 6960 * comes back in a register other than r0, you can override "result".) 6961 * 6962 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6963 * vCC (r1). Useful for integer division and modulus. 6964 * 6965 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6966 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6967 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6968 */ 6969 /* binop/lit8 vAA, vBB, #+CC */ 6970 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6971 mov r9, rINST, lsr #8 @ r9<- AA 6972 and r2, r3, #255 @ r2<- BB 6973 GET_VREG(r0, r2) @ r0<- vBB 6974 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6975 .if 0 6976 @cmp r1, #0 @ is second operand zero? 6977 beq common_errDivideByZero 6978 .endif 6979 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6980 6981 and r1, r1, #31 @ optional op; may set condition codes 6982 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 6983 GET_INST_OPCODE(ip) @ extract opcode from rINST 6984 SET_VREG(r0, r9) @ vAA<- r0 6985 GOTO_OPCODE(ip) @ jump to next instruction 6986 /* 10-12 instructions */ 6987 6988 6989/* ------------------------------ */ 6990 .balign 64 6991.L_OP_SHR_INT_LIT8: /* 0xe1 */ 6992/* File: armv5te/OP_SHR_INT_LIT8.S */ 6993/* File: armv5te/binopLit8.S */ 6994 /* 6995 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6996 * that specifies an instruction that performs "result = r0 op r1". 6997 * This could be an ARM instruction or a function call. (If the result 6998 * comes back in a register other than r0, you can override "result".) 6999 * 7000 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7001 * vCC (r1). Useful for integer division and modulus. 7002 * 7003 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7004 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7005 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7006 */ 7007 /* binop/lit8 vAA, vBB, #+CC */ 7008 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7009 mov r9, rINST, lsr #8 @ r9<- AA 7010 and r2, r3, #255 @ r2<- BB 7011 GET_VREG(r0, r2) @ r0<- vBB 7012 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7013 .if 0 7014 @cmp r1, #0 @ is second operand zero? 7015 beq common_errDivideByZero 7016 .endif 7017 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7018 7019 and r1, r1, #31 @ optional op; may set condition codes 7020 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7021 GET_INST_OPCODE(ip) @ extract opcode from rINST 7022 SET_VREG(r0, r9) @ vAA<- r0 7023 GOTO_OPCODE(ip) @ jump to next instruction 7024 /* 10-12 instructions */ 7025 7026 7027/* ------------------------------ */ 7028 .balign 64 7029.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7030/* File: armv5te/OP_USHR_INT_LIT8.S */ 7031/* File: armv5te/binopLit8.S */ 7032 /* 7033 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7034 * that specifies an instruction that performs "result = r0 op r1". 7035 * This could be an ARM instruction or a function call. (If the result 7036 * comes back in a register other than r0, you can override "result".) 7037 * 7038 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7039 * vCC (r1). Useful for integer division and modulus. 7040 * 7041 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7042 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7043 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7044 */ 7045 /* binop/lit8 vAA, vBB, #+CC */ 7046 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7047 mov r9, rINST, lsr #8 @ r9<- AA 7048 and r2, r3, #255 @ r2<- BB 7049 GET_VREG(r0, r2) @ r0<- vBB 7050 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7051 .if 0 7052 @cmp r1, #0 @ is second operand zero? 7053 beq common_errDivideByZero 7054 .endif 7055 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7056 7057 and r1, r1, #31 @ optional op; may set condition codes 7058 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7059 GET_INST_OPCODE(ip) @ extract opcode from rINST 7060 SET_VREG(r0, r9) @ vAA<- r0 7061 GOTO_OPCODE(ip) @ jump to next instruction 7062 /* 10-12 instructions */ 7063 7064 7065/* ------------------------------ */ 7066 .balign 64 7067.L_OP_IGET_VOLATILE: /* 0xe3 */ 7068/* File: armv5te/OP_IGET_VOLATILE.S */ 7069/* File: armv5te/OP_IGET.S */ 7070 /* 7071 * General 32-bit instance field get. 7072 * 7073 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7074 */ 7075 /* op vA, vB, field@CCCC */ 7076 mov r0, rINST, lsr #12 @ r0<- B 7077 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7078 FETCH(r1, 1) @ r1<- field ref CCCC 7079 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7080 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7081 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7082 cmp r0, #0 @ is resolved entry null? 7083 bne .LOP_IGET_VOLATILE_finish @ no, already resolved 70848: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7085 EXPORT_PC() @ resolve() could throw 7086 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7087 bl dvmResolveInstField @ r0<- resolved InstField ptr 7088 cmp r0, #0 7089 bne .LOP_IGET_VOLATILE_finish 7090 b common_exceptionThrown 7091 7092 7093/* ------------------------------ */ 7094 .balign 64 7095.L_OP_IPUT_VOLATILE: /* 0xe4 */ 7096/* File: armv5te/OP_IPUT_VOLATILE.S */ 7097/* File: armv5te/OP_IPUT.S */ 7098 /* 7099 * General 32-bit instance field put. 7100 * 7101 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 7102 */ 7103 /* op vA, vB, field@CCCC */ 7104 mov r0, rINST, lsr #12 @ r0<- B 7105 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7106 FETCH(r1, 1) @ r1<- field ref CCCC 7107 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7108 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7109 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7110 cmp r0, #0 @ is resolved entry null? 7111 bne .LOP_IPUT_VOLATILE_finish @ no, already resolved 71128: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7113 EXPORT_PC() @ resolve() could throw 7114 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7115 bl dvmResolveInstField @ r0<- resolved InstField ptr 7116 cmp r0, #0 @ success? 7117 bne .LOP_IPUT_VOLATILE_finish @ yes, finish up 7118 b common_exceptionThrown 7119 7120 7121/* ------------------------------ */ 7122 .balign 64 7123.L_OP_SGET_VOLATILE: /* 0xe5 */ 7124/* File: armv5te/OP_SGET_VOLATILE.S */ 7125/* File: armv5te/OP_SGET.S */ 7126 /* 7127 * General 32-bit SGET handler. 7128 * 7129 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7130 */ 7131 /* op vAA, field@BBBB */ 7132 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7133 FETCH(r1, 1) @ r1<- field ref BBBB 7134 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7135 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7136 cmp r0, #0 @ is resolved entry null? 7137 beq .LOP_SGET_VOLATILE_resolve @ yes, do resolve 7138.LOP_SGET_VOLATILE_finish: @ field ptr in r0 7139 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7140 SMP_DMB @ acquiring load 7141 mov r2, rINST, lsr #8 @ r2<- AA 7142 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7143 SET_VREG(r1, r2) @ fp[AA]<- r1 7144 GET_INST_OPCODE(ip) @ extract opcode from rINST 7145 GOTO_OPCODE(ip) @ jump to next instruction 7146 7147 7148/* ------------------------------ */ 7149 .balign 64 7150.L_OP_SPUT_VOLATILE: /* 0xe6 */ 7151/* File: armv5te/OP_SPUT_VOLATILE.S */ 7152/* File: armv5te/OP_SPUT.S */ 7153 /* 7154 * General 32-bit SPUT handler. 7155 * 7156 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 7157 */ 7158 /* op vAA, field@BBBB */ 7159 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7160 FETCH(r1, 1) @ r1<- field ref BBBB 7161 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7162 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7163 cmp r0, #0 @ is resolved entry null? 7164 beq .LOP_SPUT_VOLATILE_resolve @ yes, do resolve 7165.LOP_SPUT_VOLATILE_finish: @ field ptr in r0 7166 mov r2, rINST, lsr #8 @ r2<- AA 7167 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7168 GET_VREG(r1, r2) @ r1<- fp[AA] 7169 GET_INST_OPCODE(ip) @ extract opcode from rINST 7170 SMP_DMB @ releasing store 7171 str r1, [r0, #offStaticField_value] @ field<- vAA 7172 GOTO_OPCODE(ip) @ jump to next instruction 7173 7174 7175/* ------------------------------ */ 7176 .balign 64 7177.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ 7178/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */ 7179/* File: armv5te/OP_IGET.S */ 7180 /* 7181 * General 32-bit instance field get. 7182 * 7183 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7184 */ 7185 /* op vA, vB, field@CCCC */ 7186 mov r0, rINST, lsr #12 @ r0<- B 7187 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7188 FETCH(r1, 1) @ r1<- field ref CCCC 7189 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7190 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7191 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7192 cmp r0, #0 @ is resolved entry null? 7193 bne .LOP_IGET_OBJECT_VOLATILE_finish @ no, already resolved 71948: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7195 EXPORT_PC() @ resolve() could throw 7196 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7197 bl dvmResolveInstField @ r0<- resolved InstField ptr 7198 cmp r0, #0 7199 bne .LOP_IGET_OBJECT_VOLATILE_finish 7200 b common_exceptionThrown 7201 7202 7203/* ------------------------------ */ 7204 .balign 64 7205.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */ 7206/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */ 7207/* File: armv5te/OP_IGET_WIDE.S */ 7208 /* 7209 * Wide 32-bit instance field get. 7210 */ 7211 /* iget-wide vA, vB, field@CCCC */ 7212 mov r0, rINST, lsr #12 @ r0<- B 7213 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7214 FETCH(r1, 1) @ r1<- field ref CCCC 7215 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7216 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7217 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7218 cmp r0, #0 @ is resolved entry null? 7219 bne .LOP_IGET_WIDE_VOLATILE_finish @ no, already resolved 72208: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7221 EXPORT_PC() @ resolve() could throw 7222 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7223 bl dvmResolveInstField @ r0<- resolved InstField ptr 7224 cmp r0, #0 7225 bne .LOP_IGET_WIDE_VOLATILE_finish 7226 b common_exceptionThrown 7227 7228 7229/* ------------------------------ */ 7230 .balign 64 7231.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */ 7232/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */ 7233/* File: armv5te/OP_IPUT_WIDE.S */ 7234 /* iput-wide vA, vB, field@CCCC */ 7235 mov r0, rINST, lsr #12 @ r0<- B 7236 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7237 FETCH(r1, 1) @ r1<- field ref CCCC 7238 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7239 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7240 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7241 cmp r0, #0 @ is resolved entry null? 7242 bne .LOP_IPUT_WIDE_VOLATILE_finish @ no, already resolved 72438: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7244 EXPORT_PC() @ resolve() could throw 7245 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7246 bl dvmResolveInstField @ r0<- resolved InstField ptr 7247 cmp r0, #0 @ success? 7248 bne .LOP_IPUT_WIDE_VOLATILE_finish @ yes, finish up 7249 b common_exceptionThrown 7250 7251 7252/* ------------------------------ */ 7253 .balign 64 7254.L_OP_SGET_WIDE_VOLATILE: /* 0xea */ 7255/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */ 7256/* File: armv5te/OP_SGET_WIDE.S */ 7257 /* 7258 * 64-bit SGET handler. 7259 */ 7260 /* sget-wide vAA, field@BBBB */ 7261 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7262 FETCH(r1, 1) @ r1<- field ref BBBB 7263 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7264 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7265 cmp r0, #0 @ is resolved entry null? 7266 beq .LOP_SGET_WIDE_VOLATILE_resolve @ yes, do resolve 7267.LOP_SGET_WIDE_VOLATILE_finish: 7268 mov r9, rINST, lsr #8 @ r9<- AA 7269 .if 1 7270 add r0, r0, #offStaticField_value @ r0<- pointer to data 7271 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 7272 .else 7273 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 7274 .endif 7275 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7276 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7277 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 7278 GET_INST_OPCODE(ip) @ extract opcode from rINST 7279 GOTO_OPCODE(ip) @ jump to next instruction 7280 7281 7282/* ------------------------------ */ 7283 .balign 64 7284.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */ 7285/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */ 7286/* File: armv5te/OP_SPUT_WIDE.S */ 7287 /* 7288 * 64-bit SPUT handler. 7289 */ 7290 /* sput-wide vAA, field@BBBB */ 7291 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 7292 FETCH(r1, 1) @ r1<- field ref BBBB 7293 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 7294 mov r9, rINST, lsr #8 @ r9<- AA 7295 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 7296 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7297 cmp r2, #0 @ is resolved entry null? 7298 beq .LOP_SPUT_WIDE_VOLATILE_resolve @ yes, do resolve 7299.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9 7300 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7301 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 7302 GET_INST_OPCODE(r10) @ extract opcode from rINST 7303 .if 1 7304 add r2, r2, #offStaticField_value @ r2<- pointer to data 7305 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 7306 .else 7307 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 7308 .endif 7309 GOTO_OPCODE(r10) @ jump to next instruction 7310 7311 7312/* ------------------------------ */ 7313 .balign 64 7314.L_OP_BREAKPOINT: /* 0xec */ 7315/* File: armv5te/OP_BREAKPOINT.S */ 7316/* File: armv5te/unused.S */ 7317 bl common_abort 7318 7319 7320/* ------------------------------ */ 7321 .balign 64 7322.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7323/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7324 /* 7325 * Handle a throw-verification-error instruction. This throws an 7326 * exception for an error discovered during verification. The 7327 * exception is indicated by AA, with some detail provided by BBBB. 7328 */ 7329 /* op AA, ref@BBBB */ 7330 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7331 FETCH(r2, 1) @ r2<- BBBB 7332 EXPORT_PC() @ export the PC 7333 mov r1, rINST, lsr #8 @ r1<- AA 7334 bl dvmThrowVerificationError @ always throws 7335 b common_exceptionThrown @ handle exception 7336 7337/* ------------------------------ */ 7338 .balign 64 7339.L_OP_EXECUTE_INLINE: /* 0xee */ 7340/* File: armv5te/OP_EXECUTE_INLINE.S */ 7341 /* 7342 * Execute a "native inline" instruction. 7343 * 7344 * We need to call an InlineOp4Func: 7345 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7346 * 7347 * The first four args are in r0-r3, pointer to return value storage 7348 * is on the stack. The function's return value is a flag that tells 7349 * us if an exception was thrown. 7350 */ 7351 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7352 FETCH(r10, 1) @ r10<- BBBB 7353 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7354 EXPORT_PC() @ can throw 7355 sub sp, sp, #8 @ make room for arg, +64 bit align 7356 mov r0, rINST, lsr #12 @ r0<- B 7357 str r1, [sp] @ push &glue->retval 7358 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7359 add sp, sp, #8 @ pop stack 7360 cmp r0, #0 @ test boolean result of inline 7361 beq common_exceptionThrown @ returned false, handle exception 7362 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7363 GET_INST_OPCODE(ip) @ extract opcode from rINST 7364 GOTO_OPCODE(ip) @ jump to next instruction 7365 7366/* ------------------------------ */ 7367 .balign 64 7368.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ 7369/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */ 7370 /* 7371 * Execute a "native inline" instruction, using "/range" semantics. 7372 * Same idea as execute-inline, but we get the args differently. 7373 * 7374 * We need to call an InlineOp4Func: 7375 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7376 * 7377 * The first four args are in r0-r3, pointer to return value storage 7378 * is on the stack. The function's return value is a flag that tells 7379 * us if an exception was thrown. 7380 */ 7381 /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */ 7382 FETCH(r10, 1) @ r10<- BBBB 7383 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7384 EXPORT_PC() @ can throw 7385 sub sp, sp, #8 @ make room for arg, +64 bit align 7386 mov r0, rINST, lsr #8 @ r0<- AA 7387 str r1, [sp] @ push &glue->retval 7388 bl .LOP_EXECUTE_INLINE_RANGE_continue @ make call; will return after 7389 add sp, sp, #8 @ pop stack 7390 cmp r0, #0 @ test boolean result of inline 7391 beq common_exceptionThrown @ returned false, handle exception 7392 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7393 GET_INST_OPCODE(ip) @ extract opcode from rINST 7394 GOTO_OPCODE(ip) @ jump to next instruction 7395 7396/* ------------------------------ */ 7397 .balign 64 7398.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7399/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7400 /* 7401 * invoke-direct-empty is a no-op in a "standard" interpreter. 7402 */ 7403 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7404 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7405 GOTO_OPCODE(ip) @ execute it 7406 7407/* ------------------------------ */ 7408 .balign 64 7409.L_OP_UNUSED_F1: /* 0xf1 */ 7410/* File: armv5te/OP_UNUSED_F1.S */ 7411/* File: armv5te/unused.S */ 7412 bl common_abort 7413 7414 7415/* ------------------------------ */ 7416 .balign 64 7417.L_OP_IGET_QUICK: /* 0xf2 */ 7418/* File: armv6t2/OP_IGET_QUICK.S */ 7419 /* For: iget-quick, iget-object-quick */ 7420 /* op vA, vB, offset@CCCC */ 7421 mov r2, rINST, lsr #12 @ r2<- B 7422 FETCH(r1, 1) @ r1<- field byte offset 7423 GET_VREG(r3, r2) @ r3<- object we're operating on 7424 ubfx r2, rINST, #8, #4 @ r2<- A 7425 cmp r3, #0 @ check object for null 7426 beq common_errNullObject @ object was null 7427 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7428 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7429 GET_INST_OPCODE(ip) @ extract opcode from rINST 7430 SET_VREG(r0, r2) @ fp[A]<- r0 7431 GOTO_OPCODE(ip) @ jump to next instruction 7432 7433/* ------------------------------ */ 7434 .balign 64 7435.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7436/* File: armv6t2/OP_IGET_WIDE_QUICK.S */ 7437 /* iget-wide-quick vA, vB, offset@CCCC */ 7438 mov r2, rINST, lsr #12 @ r2<- B 7439 FETCH(ip, 1) @ ip<- field byte offset 7440 GET_VREG(r3, r2) @ r3<- object we're operating on 7441 ubfx r2, rINST, #8, #4 @ r2<- A 7442 cmp r3, #0 @ check object for null 7443 beq common_errNullObject @ object was null 7444 ldrd r0, [r3, ip] @ r0<- obj.field (64 bits, aligned) 7445 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7446 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7447 GET_INST_OPCODE(ip) @ extract opcode from rINST 7448 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7449 GOTO_OPCODE(ip) @ jump to next instruction 7450 7451/* ------------------------------ */ 7452 .balign 64 7453.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7454/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7455/* File: armv5te/OP_IGET_QUICK.S */ 7456 /* For: iget-quick, iget-object-quick */ 7457 /* op vA, vB, offset@CCCC */ 7458 mov r2, rINST, lsr #12 @ r2<- B 7459 GET_VREG(r3, r2) @ r3<- object we're operating on 7460 FETCH(r1, 1) @ r1<- field byte offset 7461 cmp r3, #0 @ check object for null 7462 mov r2, rINST, lsr #8 @ r2<- A(+) 7463 beq common_errNullObject @ object was null 7464 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7465 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7466 and r2, r2, #15 7467 GET_INST_OPCODE(ip) @ extract opcode from rINST 7468 SET_VREG(r0, r2) @ fp[A]<- r0 7469 GOTO_OPCODE(ip) @ jump to next instruction 7470 7471 7472/* ------------------------------ */ 7473 .balign 64 7474.L_OP_IPUT_QUICK: /* 0xf5 */ 7475/* File: armv6t2/OP_IPUT_QUICK.S */ 7476 /* For: iput-quick, iput-object-quick */ 7477 /* op vA, vB, offset@CCCC */ 7478 mov r2, rINST, lsr #12 @ r2<- B 7479 FETCH(r1, 1) @ r1<- field byte offset 7480 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7481 ubfx r2, rINST, #8, #4 @ r2<- A 7482 cmp r3, #0 @ check object for null 7483 beq common_errNullObject @ object was null 7484 GET_VREG(r0, r2) @ r0<- fp[A] 7485 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7486 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7487 GET_INST_OPCODE(ip) @ extract opcode from rINST 7488 GOTO_OPCODE(ip) @ jump to next instruction 7489 7490/* ------------------------------ */ 7491 .balign 64 7492.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7493/* File: armv6t2/OP_IPUT_WIDE_QUICK.S */ 7494 /* iput-wide-quick vA, vB, offset@CCCC */ 7495 mov r1, rINST, lsr #12 @ r1<- B 7496 ubfx r0, rINST, #8, #4 @ r0<- A 7497 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7498 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7499 cmp r2, #0 @ check object for null 7500 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7501 beq common_errNullObject @ object was null 7502 FETCH(r3, 1) @ r3<- field byte offset 7503 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7504 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7505 GET_INST_OPCODE(ip) @ extract opcode from rINST 7506 GOTO_OPCODE(ip) @ jump to next instruction 7507 7508/* ------------------------------ */ 7509 .balign 64 7510.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7511/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7512 /* For: iput-object-quick */ 7513 /* op vA, vB, offset@CCCC */ 7514 mov r2, rINST, lsr #12 @ r2<- B 7515 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7516 FETCH(r1, 1) @ r1<- field byte offset 7517 cmp r3, #0 @ check object for null 7518 mov r2, rINST, lsr #8 @ r2<- A(+) 7519 beq common_errNullObject @ object was null 7520 and r2, r2, #15 7521 GET_VREG(r0, r2) @ r0<- fp[A] 7522 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 7523 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7524 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7525 cmp r0, #0 7526 strneb r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card on non-null store 7527 GET_INST_OPCODE(ip) @ extract opcode from rINST 7528 GOTO_OPCODE(ip) @ jump to next instruction 7529 7530/* ------------------------------ */ 7531 .balign 64 7532.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7533/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7534 /* 7535 * Handle an optimized virtual method call. 7536 * 7537 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7538 */ 7539 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7540 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7541 FETCH(r3, 2) @ r3<- FEDC or CCCC 7542 FETCH(r1, 1) @ r1<- BBBB 7543 .if (!0) 7544 and r3, r3, #15 @ r3<- C (or stays CCCC) 7545 .endif 7546 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7547 cmp r2, #0 @ is "this" null? 7548 beq common_errNullObject @ null "this", throw exception 7549 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7550 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7551 EXPORT_PC() @ invoke must export 7552 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7553 bl common_invokeMethodNoRange @ continue on 7554 7555/* ------------------------------ */ 7556 .balign 64 7557.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7558/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7559/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7560 /* 7561 * Handle an optimized virtual method call. 7562 * 7563 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7564 */ 7565 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7566 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7567 FETCH(r3, 2) @ r3<- FEDC or CCCC 7568 FETCH(r1, 1) @ r1<- BBBB 7569 .if (!1) 7570 and r3, r3, #15 @ r3<- C (or stays CCCC) 7571 .endif 7572 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7573 cmp r2, #0 @ is "this" null? 7574 beq common_errNullObject @ null "this", throw exception 7575 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7576 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7577 EXPORT_PC() @ invoke must export 7578 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7579 bl common_invokeMethodRange @ continue on 7580 7581 7582/* ------------------------------ */ 7583 .balign 64 7584.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7585/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7586 /* 7587 * Handle an optimized "super" method call. 7588 * 7589 * for: [opt] invoke-super-quick, invoke-super-quick/range 7590 */ 7591 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7592 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7593 FETCH(r10, 2) @ r10<- GFED or CCCC 7594 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7595 .if (!0) 7596 and r10, r10, #15 @ r10<- D (or stays CCCC) 7597 .endif 7598 FETCH(r1, 1) @ r1<- BBBB 7599 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7600 EXPORT_PC() @ must export for invoke 7601 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7602 GET_VREG(r3, r10) @ r3<- "this" 7603 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7604 cmp r3, #0 @ null "this" ref? 7605 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7606 beq common_errNullObject @ "this" is null, throw exception 7607 bl common_invokeMethodNoRange @ continue on 7608 7609/* ------------------------------ */ 7610 .balign 64 7611.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7612/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7613/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7614 /* 7615 * Handle an optimized "super" method call. 7616 * 7617 * for: [opt] invoke-super-quick, invoke-super-quick/range 7618 */ 7619 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7620 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7621 FETCH(r10, 2) @ r10<- GFED or CCCC 7622 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7623 .if (!1) 7624 and r10, r10, #15 @ r10<- D (or stays CCCC) 7625 .endif 7626 FETCH(r1, 1) @ r1<- BBBB 7627 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7628 EXPORT_PC() @ must export for invoke 7629 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7630 GET_VREG(r3, r10) @ r3<- "this" 7631 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7632 cmp r3, #0 @ null "this" ref? 7633 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7634 beq common_errNullObject @ "this" is null, throw exception 7635 bl common_invokeMethodRange @ continue on 7636 7637 7638/* ------------------------------ */ 7639 .balign 64 7640.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ 7641/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */ 7642/* File: armv5te/OP_IPUT_OBJECT.S */ 7643 /* 7644 * 32-bit instance field put. 7645 * 7646 * for: iput-object, iput-object-volatile 7647 */ 7648 /* op vA, vB, field@CCCC */ 7649 mov r0, rINST, lsr #12 @ r0<- B 7650 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7651 FETCH(r1, 1) @ r1<- field ref CCCC 7652 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7653 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7654 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7655 cmp r0, #0 @ is resolved entry null? 7656 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ no, already resolved 76578: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7658 EXPORT_PC() @ resolve() could throw 7659 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7660 bl dvmResolveInstField @ r0<- resolved InstField ptr 7661 cmp r0, #0 @ success? 7662 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ yes, finish up 7663 b common_exceptionThrown 7664 7665 7666/* ------------------------------ */ 7667 .balign 64 7668.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ 7669/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */ 7670/* File: armv5te/OP_SGET.S */ 7671 /* 7672 * General 32-bit SGET handler. 7673 * 7674 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7675 */ 7676 /* op vAA, field@BBBB */ 7677 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7678 FETCH(r1, 1) @ r1<- field ref BBBB 7679 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7680 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7681 cmp r0, #0 @ is resolved entry null? 7682 beq .LOP_SGET_OBJECT_VOLATILE_resolve @ yes, do resolve 7683.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0 7684 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7685 SMP_DMB @ acquiring load 7686 mov r2, rINST, lsr #8 @ r2<- AA 7687 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7688 SET_VREG(r1, r2) @ fp[AA]<- r1 7689 GET_INST_OPCODE(ip) @ extract opcode from rINST 7690 GOTO_OPCODE(ip) @ jump to next instruction 7691 7692 7693/* ------------------------------ */ 7694 .balign 64 7695.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ 7696/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */ 7697/* File: armv5te/OP_SPUT_OBJECT.S */ 7698 /* 7699 * 32-bit SPUT handler for objects 7700 * 7701 * for: sput-object, sput-object-volatile 7702 */ 7703 /* op vAA, field@BBBB */ 7704 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7705 FETCH(r1, 1) @ r1<- field ref BBBB 7706 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7707 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7708 cmp r0, #0 @ is resolved entry null? 7709 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ no, continue 7710 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7711 EXPORT_PC() @ resolve() could throw, so export now 7712 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7713 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 7714 cmp r0, #0 @ success? 7715 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish 7716 b common_exceptionThrown @ no, handle exception 7717 7718 7719 7720/* ------------------------------ */ 7721 .balign 64 7722.L_OP_UNUSED_FF: /* 0xff */ 7723/* File: armv5te/OP_UNUSED_FF.S */ 7724/* File: armv5te/unused.S */ 7725 bl common_abort 7726 7727 7728 7729 .balign 64 7730 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7731 .global dvmAsmInstructionEnd 7732dvmAsmInstructionEnd: 7733 7734/* 7735 * =========================================================================== 7736 * Sister implementations 7737 * =========================================================================== 7738 */ 7739 .global dvmAsmSisterStart 7740 .type dvmAsmSisterStart, %function 7741 .text 7742 .balign 4 7743dvmAsmSisterStart: 7744 7745/* continuation for OP_CONST_STRING */ 7746 7747 /* 7748 * Continuation if the String has not yet been resolved. 7749 * r1: BBBB (String ref) 7750 * r9: target register 7751 */ 7752.LOP_CONST_STRING_resolve: 7753 EXPORT_PC() 7754 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7755 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7756 bl dvmResolveString @ r0<- String reference 7757 cmp r0, #0 @ failed? 7758 beq common_exceptionThrown @ yup, handle the exception 7759 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7760 GET_INST_OPCODE(ip) @ extract opcode from rINST 7761 SET_VREG(r0, r9) @ vAA<- r0 7762 GOTO_OPCODE(ip) @ jump to next instruction 7763 7764/* continuation for OP_CONST_STRING_JUMBO */ 7765 7766 /* 7767 * Continuation if the String has not yet been resolved. 7768 * r1: BBBBBBBB (String ref) 7769 * r9: target register 7770 */ 7771.LOP_CONST_STRING_JUMBO_resolve: 7772 EXPORT_PC() 7773 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7774 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7775 bl dvmResolveString @ r0<- String reference 7776 cmp r0, #0 @ failed? 7777 beq common_exceptionThrown @ yup, handle the exception 7778 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7779 GET_INST_OPCODE(ip) @ extract opcode from rINST 7780 SET_VREG(r0, r9) @ vAA<- r0 7781 GOTO_OPCODE(ip) @ jump to next instruction 7782 7783/* continuation for OP_CONST_CLASS */ 7784 7785 /* 7786 * Continuation if the Class has not yet been resolved. 7787 * r1: BBBB (Class ref) 7788 * r9: target register 7789 */ 7790.LOP_CONST_CLASS_resolve: 7791 EXPORT_PC() 7792 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7793 mov r2, #1 @ r2<- true 7794 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7795 bl dvmResolveClass @ r0<- Class reference 7796 cmp r0, #0 @ failed? 7797 beq common_exceptionThrown @ yup, handle the exception 7798 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7799 GET_INST_OPCODE(ip) @ extract opcode from rINST 7800 SET_VREG(r0, r9) @ vAA<- r0 7801 GOTO_OPCODE(ip) @ jump to next instruction 7802 7803/* continuation for OP_CHECK_CAST */ 7804 7805 /* 7806 * Trivial test failed, need to perform full check. This is common. 7807 * r0 holds obj->clazz 7808 * r1 holds class resolved from BBBB 7809 * r9 holds object 7810 */ 7811.LOP_CHECK_CAST_fullcheck: 7812 bl dvmInstanceofNonTrivial @ r0<- boolean result 7813 cmp r0, #0 @ failed? 7814 bne .LOP_CHECK_CAST_okay @ no, success 7815 7816 @ A cast has failed. We need to throw a ClassCastException with the 7817 @ class of the object that failed to be cast. 7818 EXPORT_PC() @ about to throw 7819 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 7820 ldr r0, .LstrClassCastExceptionPtr 7821 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 7822 bl dvmThrowExceptionWithClassMessage 7823 b common_exceptionThrown 7824 7825 /* 7826 * Resolution required. This is the least-likely path. 7827 * 7828 * r2 holds BBBB 7829 * r9 holds object 7830 */ 7831.LOP_CHECK_CAST_resolve: 7832 EXPORT_PC() @ resolve() could throw 7833 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7834 mov r1, r2 @ r1<- BBBB 7835 mov r2, #0 @ r2<- false 7836 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7837 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7838 cmp r0, #0 @ got null? 7839 beq common_exceptionThrown @ yes, handle exception 7840 mov r1, r0 @ r1<- class resolved from BBB 7841 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7842 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7843 7844.LstrClassCastExceptionPtr: 7845 .word .LstrClassCastException 7846 7847/* continuation for OP_INSTANCE_OF */ 7848 7849 /* 7850 * Trivial test failed, need to perform full check. This is common. 7851 * r0 holds obj->clazz 7852 * r1 holds class resolved from BBBB 7853 * r9 holds A 7854 */ 7855.LOP_INSTANCE_OF_fullcheck: 7856 bl dvmInstanceofNonTrivial @ r0<- boolean result 7857 @ fall through to OP_INSTANCE_OF_store 7858 7859 /* 7860 * r0 holds boolean result 7861 * r9 holds A 7862 */ 7863.LOP_INSTANCE_OF_store: 7864 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7865 SET_VREG(r0, r9) @ vA<- r0 7866 GET_INST_OPCODE(ip) @ extract opcode from rINST 7867 GOTO_OPCODE(ip) @ jump to next instruction 7868 7869 /* 7870 * Trivial test succeeded, save and bail. 7871 * r9 holds A 7872 */ 7873.LOP_INSTANCE_OF_trivial: 7874 mov r0, #1 @ indicate success 7875 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7876 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7877 SET_VREG(r0, r9) @ vA<- r0 7878 GET_INST_OPCODE(ip) @ extract opcode from rINST 7879 GOTO_OPCODE(ip) @ jump to next instruction 7880 7881 /* 7882 * Resolution required. This is the least-likely path. 7883 * 7884 * r3 holds BBBB 7885 * r9 holds A 7886 */ 7887.LOP_INSTANCE_OF_resolve: 7888 EXPORT_PC() @ resolve() could throw 7889 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7890 mov r1, r3 @ r1<- BBBB 7891 mov r2, #1 @ r2<- true 7892 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7893 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7894 cmp r0, #0 @ got null? 7895 beq common_exceptionThrown @ yes, handle exception 7896 mov r1, r0 @ r1<- class resolved from BBB 7897 mov r3, rINST, lsr #12 @ r3<- B 7898 GET_VREG(r0, r3) @ r0<- vB (object) 7899 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7900 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7901 7902/* continuation for OP_NEW_INSTANCE */ 7903 7904 .balign 32 @ minimize cache lines 7905.LOP_NEW_INSTANCE_finish: @ r0=new object 7906 mov r3, rINST, lsr #8 @ r3<- AA 7907 cmp r0, #0 @ failed? 7908 beq common_exceptionThrown @ yes, handle the exception 7909 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7910 GET_INST_OPCODE(ip) @ extract opcode from rINST 7911 SET_VREG(r0, r3) @ vAA<- r0 7912 GOTO_OPCODE(ip) @ jump to next instruction 7913 7914 /* 7915 * Class initialization required. 7916 * 7917 * r0 holds class object 7918 */ 7919.LOP_NEW_INSTANCE_needinit: 7920 mov r9, r0 @ save r0 7921 bl dvmInitClass @ initialize class 7922 cmp r0, #0 @ check boolean result 7923 mov r0, r9 @ restore r0 7924 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7925 b common_exceptionThrown @ failed, deal with init exception 7926 7927 /* 7928 * Resolution required. This is the least-likely path. 7929 * 7930 * r1 holds BBBB 7931 */ 7932.LOP_NEW_INSTANCE_resolve: 7933 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7934 mov r2, #0 @ r2<- false 7935 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7936 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7937 cmp r0, #0 @ got null? 7938 bne .LOP_NEW_INSTANCE_resolved @ no, continue 7939 b common_exceptionThrown @ yes, handle exception 7940 7941.LstrInstantiationErrorPtr: 7942 .word .LstrInstantiationError 7943 7944/* continuation for OP_NEW_ARRAY */ 7945 7946 7947 /* 7948 * Resolve class. (This is an uncommon case.) 7949 * 7950 * r1 holds array length 7951 * r2 holds class ref CCCC 7952 */ 7953.LOP_NEW_ARRAY_resolve: 7954 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7955 mov r9, r1 @ r9<- length (save) 7956 mov r1, r2 @ r1<- CCCC 7957 mov r2, #0 @ r2<- false 7958 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7959 bl dvmResolveClass @ r0<- call(clazz, ref) 7960 cmp r0, #0 @ got null? 7961 mov r1, r9 @ r1<- length (restore) 7962 beq common_exceptionThrown @ yes, handle exception 7963 @ fall through to OP_NEW_ARRAY_finish 7964 7965 /* 7966 * Finish allocation. 7967 * 7968 * r0 holds class 7969 * r1 holds array length 7970 */ 7971.LOP_NEW_ARRAY_finish: 7972 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 7973 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 7974 cmp r0, #0 @ failed? 7975 mov r2, rINST, lsr #8 @ r2<- A+ 7976 beq common_exceptionThrown @ yes, handle the exception 7977 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7978 and r2, r2, #15 @ r2<- A 7979 GET_INST_OPCODE(ip) @ extract opcode from rINST 7980 SET_VREG(r0, r2) @ vA<- r0 7981 GOTO_OPCODE(ip) @ jump to next instruction 7982 7983/* continuation for OP_FILLED_NEW_ARRAY */ 7984 7985 /* 7986 * On entry: 7987 * r0 holds array class 7988 * r10 holds AA or BA 7989 */ 7990.LOP_FILLED_NEW_ARRAY_continue: 7991 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 7992 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 7993 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 7994 .if 0 7995 mov r1, r10 @ r1<- AA (length) 7996 .else 7997 mov r1, r10, lsr #4 @ r1<- B (length) 7998 .endif 7999 cmp rINST, #'I' @ array of ints? 8000 cmpne rINST, #'L' @ array of objects? 8001 cmpne rINST, #'[' @ array of arrays? 8002 mov r9, r1 @ save length in r9 8003 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 8004 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8005 cmp r0, #0 @ null return? 8006 beq common_exceptionThrown @ alloc failed, handle exception 8007 8008 FETCH(r1, 2) @ r1<- FEDC or CCCC 8009 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8010 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 8011 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8012 subs r9, r9, #1 @ length--, check for neg 8013 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8014 bmi 2f @ was zero, bail 8015 8016 @ copy values from registers into the array 8017 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8018 .if 0 8019 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 80201: ldr r3, [r2], #4 @ r3<- *r2++ 8021 subs r9, r9, #1 @ count-- 8022 str r3, [r0], #4 @ *contents++ = vX 8023 bpl 1b 8024 @ continue at 2 8025 .else 8026 cmp r9, #4 @ length was initially 5? 8027 and r2, r10, #15 @ r2<- A 8028 bne 1f @ <= 4 args, branch 8029 GET_VREG(r3, r2) @ r3<- vA 8030 sub r9, r9, #1 @ count-- 8031 str r3, [r0, #16] @ contents[4] = vA 80321: and r2, r1, #15 @ r2<- F/E/D/C 8033 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8034 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8035 subs r9, r9, #1 @ count-- 8036 str r3, [r0], #4 @ *contents++ = vX 8037 bpl 1b 8038 @ continue at 2 8039 .endif 8040 80412: 8042 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 8043 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 8044 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8045 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8046 cmp r1, #'I' @ Is int array? 8047 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card if not 8048 GOTO_OPCODE(ip) @ execute it 8049 8050 /* 8051 * Throw an exception indicating that we have not implemented this 8052 * mode of filled-new-array. 8053 */ 8054.LOP_FILLED_NEW_ARRAY_notimpl: 8055 ldr r0, .L_strInternalError 8056 ldr r1, .L_strFilledNewArrayNotImpl 8057 bl dvmThrowException 8058 b common_exceptionThrown 8059 8060 .if (!0) @ define in one or the other, not both 8061.L_strFilledNewArrayNotImpl: 8062 .word .LstrFilledNewArrayNotImpl 8063.L_strInternalError: 8064 .word .LstrInternalError 8065 .endif 8066 8067/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 8068 8069 /* 8070 * On entry: 8071 * r0 holds array class 8072 * r10 holds AA or BA 8073 */ 8074.LOP_FILLED_NEW_ARRAY_RANGE_continue: 8075 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8076 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8077 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 8078 .if 1 8079 mov r1, r10 @ r1<- AA (length) 8080 .else 8081 mov r1, r10, lsr #4 @ r1<- B (length) 8082 .endif 8083 cmp rINST, #'I' @ array of ints? 8084 cmpne rINST, #'L' @ array of objects? 8085 cmpne rINST, #'[' @ array of arrays? 8086 mov r9, r1 @ save length in r9 8087 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 8088 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8089 cmp r0, #0 @ null return? 8090 beq common_exceptionThrown @ alloc failed, handle exception 8091 8092 FETCH(r1, 2) @ r1<- FEDC or CCCC 8093 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8094 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 8095 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8096 subs r9, r9, #1 @ length--, check for neg 8097 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8098 bmi 2f @ was zero, bail 8099 8100 @ copy values from registers into the array 8101 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8102 .if 1 8103 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 81041: ldr r3, [r2], #4 @ r3<- *r2++ 8105 subs r9, r9, #1 @ count-- 8106 str r3, [r0], #4 @ *contents++ = vX 8107 bpl 1b 8108 @ continue at 2 8109 .else 8110 cmp r9, #4 @ length was initially 5? 8111 and r2, r10, #15 @ r2<- A 8112 bne 1f @ <= 4 args, branch 8113 GET_VREG(r3, r2) @ r3<- vA 8114 sub r9, r9, #1 @ count-- 8115 str r3, [r0, #16] @ contents[4] = vA 81161: and r2, r1, #15 @ r2<- F/E/D/C 8117 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8118 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8119 subs r9, r9, #1 @ count-- 8120 str r3, [r0], #4 @ *contents++ = vX 8121 bpl 1b 8122 @ continue at 2 8123 .endif 8124 81252: 8126 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 8127 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 8128 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8129 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8130 cmp r1, #'I' @ Is int array? 8131 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card if not 8132 GOTO_OPCODE(ip) @ execute it 8133 8134 /* 8135 * Throw an exception indicating that we have not implemented this 8136 * mode of filled-new-array. 8137 */ 8138.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8139 ldr r0, .L_strInternalError 8140 ldr r1, .L_strFilledNewArrayNotImpl 8141 bl dvmThrowException 8142 b common_exceptionThrown 8143 8144 .if (!1) @ define in one or the other, not both 8145.L_strFilledNewArrayNotImpl: 8146 .word .LstrFilledNewArrayNotImpl 8147.L_strInternalError: 8148 .word .LstrInternalError 8149 .endif 8150 8151/* continuation for OP_CMPL_FLOAT */ 8152.LOP_CMPL_FLOAT_finish: 8153 SET_VREG(r0, r9) @ vAA<- r0 8154 GOTO_OPCODE(ip) @ jump to next instruction 8155 8156/* continuation for OP_CMPG_FLOAT */ 8157.LOP_CMPG_FLOAT_finish: 8158 SET_VREG(r0, r9) @ vAA<- r0 8159 GOTO_OPCODE(ip) @ jump to next instruction 8160 8161/* continuation for OP_CMPL_DOUBLE */ 8162.LOP_CMPL_DOUBLE_finish: 8163 SET_VREG(r0, r9) @ vAA<- r0 8164 GOTO_OPCODE(ip) @ jump to next instruction 8165 8166/* continuation for OP_CMPG_DOUBLE */ 8167.LOP_CMPG_DOUBLE_finish: 8168 SET_VREG(r0, r9) @ vAA<- r0 8169 GOTO_OPCODE(ip) @ jump to next instruction 8170 8171/* continuation for OP_CMP_LONG */ 8172 8173.LOP_CMP_LONG_less: 8174 mvn r1, #0 @ r1<- -1 8175 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8176 @ instead, we just replicate the tail end. 8177 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8178 SET_VREG(r1, r9) @ vAA<- r1 8179 GET_INST_OPCODE(ip) @ extract opcode from rINST 8180 GOTO_OPCODE(ip) @ jump to next instruction 8181 8182.LOP_CMP_LONG_greater: 8183 mov r1, #1 @ r1<- 1 8184 @ fall through to _finish 8185 8186.LOP_CMP_LONG_finish: 8187 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8188 SET_VREG(r1, r9) @ vAA<- r1 8189 GET_INST_OPCODE(ip) @ extract opcode from rINST 8190 GOTO_OPCODE(ip) @ jump to next instruction 8191 8192/* continuation for OP_AGET_WIDE */ 8193 8194.LOP_AGET_WIDE_finish: 8195 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8196 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8197 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8198 GET_INST_OPCODE(ip) @ extract opcode from rINST 8199 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8200 GOTO_OPCODE(ip) @ jump to next instruction 8201 8202/* continuation for OP_APUT_WIDE */ 8203 8204.LOP_APUT_WIDE_finish: 8205 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8206 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8207 GET_INST_OPCODE(ip) @ extract opcode from rINST 8208 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8209 GOTO_OPCODE(ip) @ jump to next instruction 8210 8211/* continuation for OP_APUT_OBJECT */ 8212 /* 8213 * On entry: 8214 * r1 = vBB (arrayObj) 8215 * r9 = vAA (obj) 8216 * r10 = offset into array (vBB + vCC * width) 8217 */ 8218.LOP_APUT_OBJECT_finish: 8219 cmp r9, #0 @ storing null reference? 8220 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8221 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8222 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz 8223 bl dvmCanPutArrayElement @ test object type vs. array type 8224 cmp r0, #0 @ okay? 8225 beq common_errArrayStore @ no 8226 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8227 ldr r2, [rGLUE, #offGlue_cardTable] @ get biased CT base 8228 add r10, #offArrayObject_contents @ r0<- pointer to slot 8229 GET_INST_OPCODE(ip) @ extract opcode from rINST 8230 str r9, [r10] @ vBB[vCC]<- vAA 8231 strb r2, [r2, r10, lsr #GC_CARD_SHIFT] @ mark card 8232 GOTO_OPCODE(ip) @ jump to next instruction 8233.LOP_APUT_OBJECT_skip_check: 8234 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8235 GET_INST_OPCODE(ip) @ extract opcode from rINST 8236 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8237 GOTO_OPCODE(ip) @ jump to next instruction 8238 8239/* continuation for OP_IGET */ 8240 8241 /* 8242 * Currently: 8243 * r0 holds resolved field 8244 * r9 holds object 8245 */ 8246.LOP_IGET_finish: 8247 @bl common_squeak0 8248 cmp r9, #0 @ check object for null 8249 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8250 beq common_errNullObject @ object was null 8251 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8252 ubfx r2, rINST, #8, #4 @ r2<- A 8253 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8254 GET_INST_OPCODE(ip) @ extract opcode from rINST 8255 SET_VREG(r0, r2) @ fp[A]<- r0 8256 GOTO_OPCODE(ip) @ jump to next instruction 8257 8258/* continuation for OP_IGET_WIDE */ 8259 8260 /* 8261 * Currently: 8262 * r0 holds resolved field 8263 * r9 holds object 8264 */ 8265.LOP_IGET_WIDE_finish: 8266 cmp r9, #0 @ check object for null 8267 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8268 beq common_errNullObject @ object was null 8269 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8270 ubfx r2, rINST, #8, #4 @ r2<- A 8271 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8272 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8273 GET_INST_OPCODE(ip) @ extract opcode from rINST 8274 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8275 GOTO_OPCODE(ip) @ jump to next instruction 8276 8277/* continuation for OP_IGET_OBJECT */ 8278 8279 /* 8280 * Currently: 8281 * r0 holds resolved field 8282 * r9 holds object 8283 */ 8284.LOP_IGET_OBJECT_finish: 8285 @bl common_squeak0 8286 cmp r9, #0 @ check object for null 8287 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8288 beq common_errNullObject @ object was null 8289 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8290 @ no-op @ acquiring load 8291 mov r2, rINST, lsr #8 @ r2<- A+ 8292 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8293 and r2, r2, #15 @ r2<- A 8294 GET_INST_OPCODE(ip) @ extract opcode from rINST 8295 SET_VREG(r0, r2) @ fp[A]<- r0 8296 GOTO_OPCODE(ip) @ jump to next instruction 8297 8298/* continuation for OP_IGET_BOOLEAN */ 8299 8300 /* 8301 * Currently: 8302 * r0 holds resolved field 8303 * r9 holds object 8304 */ 8305.LOP_IGET_BOOLEAN_finish: 8306 @bl common_squeak1 8307 cmp r9, #0 @ check object for null 8308 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8309 beq common_errNullObject @ object was null 8310 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8311 @ no-op @ acquiring load 8312 mov r2, rINST, lsr #8 @ r2<- A+ 8313 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8314 and r2, r2, #15 @ r2<- A 8315 GET_INST_OPCODE(ip) @ extract opcode from rINST 8316 SET_VREG(r0, r2) @ fp[A]<- r0 8317 GOTO_OPCODE(ip) @ jump to next instruction 8318 8319/* continuation for OP_IGET_BYTE */ 8320 8321 /* 8322 * Currently: 8323 * r0 holds resolved field 8324 * r9 holds object 8325 */ 8326.LOP_IGET_BYTE_finish: 8327 @bl common_squeak2 8328 cmp r9, #0 @ check object for null 8329 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8330 beq common_errNullObject @ object was null 8331 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8332 @ no-op @ acquiring load 8333 mov r2, rINST, lsr #8 @ r2<- A+ 8334 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8335 and r2, r2, #15 @ r2<- A 8336 GET_INST_OPCODE(ip) @ extract opcode from rINST 8337 SET_VREG(r0, r2) @ fp[A]<- r0 8338 GOTO_OPCODE(ip) @ jump to next instruction 8339 8340/* continuation for OP_IGET_CHAR */ 8341 8342 /* 8343 * Currently: 8344 * r0 holds resolved field 8345 * r9 holds object 8346 */ 8347.LOP_IGET_CHAR_finish: 8348 @bl common_squeak3 8349 cmp r9, #0 @ check object for null 8350 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8351 beq common_errNullObject @ object was null 8352 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8353 @ no-op @ acquiring load 8354 mov r2, rINST, lsr #8 @ r2<- A+ 8355 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8356 and r2, r2, #15 @ r2<- A 8357 GET_INST_OPCODE(ip) @ extract opcode from rINST 8358 SET_VREG(r0, r2) @ fp[A]<- r0 8359 GOTO_OPCODE(ip) @ jump to next instruction 8360 8361/* continuation for OP_IGET_SHORT */ 8362 8363 /* 8364 * Currently: 8365 * r0 holds resolved field 8366 * r9 holds object 8367 */ 8368.LOP_IGET_SHORT_finish: 8369 @bl common_squeak4 8370 cmp r9, #0 @ check object for null 8371 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8372 beq common_errNullObject @ object was null 8373 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8374 @ no-op @ acquiring load 8375 mov r2, rINST, lsr #8 @ r2<- A+ 8376 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8377 and r2, r2, #15 @ r2<- A 8378 GET_INST_OPCODE(ip) @ extract opcode from rINST 8379 SET_VREG(r0, r2) @ fp[A]<- r0 8380 GOTO_OPCODE(ip) @ jump to next instruction 8381 8382/* continuation for OP_IPUT */ 8383 8384 /* 8385 * Currently: 8386 * r0 holds resolved field 8387 * r9 holds object 8388 */ 8389.LOP_IPUT_finish: 8390 @bl common_squeak0 8391 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8392 ubfx r1, rINST, #8, #4 @ r1<- A 8393 cmp r9, #0 @ check object for null 8394 GET_VREG(r0, r1) @ r0<- fp[A] 8395 beq common_errNullObject @ object was null 8396 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8397 GET_INST_OPCODE(ip) @ extract opcode from rINST 8398 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8399 GOTO_OPCODE(ip) @ jump to next instruction 8400 8401/* continuation for OP_IPUT_WIDE */ 8402 8403 /* 8404 * Currently: 8405 * r0 holds resolved field 8406 * r9 holds object 8407 */ 8408.LOP_IPUT_WIDE_finish: 8409 ubfx r2, rINST, #8, #4 @ r2<- A 8410 cmp r9, #0 @ check object for null 8411 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8412 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8413 beq common_errNullObject @ object was null 8414 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8415 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8416 GET_INST_OPCODE(ip) @ extract opcode from rINST 8417 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0 8418 GOTO_OPCODE(ip) @ jump to next instruction 8419 8420/* continuation for OP_IPUT_OBJECT */ 8421 8422 /* 8423 * Currently: 8424 * r0 holds resolved field 8425 * r9 holds object 8426 */ 8427.LOP_IPUT_OBJECT_finish: 8428 @bl common_squeak0 8429 mov r1, rINST, lsr #8 @ r1<- A+ 8430 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8431 and r1, r1, #15 @ r1<- A 8432 cmp r9, #0 @ check object for null 8433 GET_VREG(r0, r1) @ r0<- fp[A] 8434 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8435 beq common_errNullObject @ object was null 8436 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8437 add r9, r3 @ r9<- direct ptr to target location 8438 GET_INST_OPCODE(ip) @ extract opcode from rINST 8439 @ no-op @ releasing store 8440 str r0, [r9] @ obj.field (8/16/32 bits)<- r0 8441 cmp r0, #0 @ stored a null reference? 8442 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 8443 GOTO_OPCODE(ip) @ jump to next instruction 8444 8445/* continuation for OP_IPUT_BOOLEAN */ 8446 8447 /* 8448 * Currently: 8449 * r0 holds resolved field 8450 * r9 holds object 8451 */ 8452.LOP_IPUT_BOOLEAN_finish: 8453 @bl common_squeak1 8454 mov r1, rINST, lsr #8 @ r1<- A+ 8455 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8456 and r1, r1, #15 @ r1<- A 8457 cmp r9, #0 @ check object for null 8458 GET_VREG(r0, r1) @ r0<- fp[A] 8459 beq common_errNullObject @ object was null 8460 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8461 GET_INST_OPCODE(ip) @ extract opcode from rINST 8462 @ no-op @ releasing store 8463 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8464 GOTO_OPCODE(ip) @ jump to next instruction 8465 8466/* continuation for OP_IPUT_BYTE */ 8467 8468 /* 8469 * Currently: 8470 * r0 holds resolved field 8471 * r9 holds object 8472 */ 8473.LOP_IPUT_BYTE_finish: 8474 @bl common_squeak2 8475 mov r1, rINST, lsr #8 @ r1<- A+ 8476 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8477 and r1, r1, #15 @ r1<- A 8478 cmp r9, #0 @ check object for null 8479 GET_VREG(r0, r1) @ r0<- fp[A] 8480 beq common_errNullObject @ object was null 8481 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8482 GET_INST_OPCODE(ip) @ extract opcode from rINST 8483 @ no-op @ releasing store 8484 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8485 GOTO_OPCODE(ip) @ jump to next instruction 8486 8487/* continuation for OP_IPUT_CHAR */ 8488 8489 /* 8490 * Currently: 8491 * r0 holds resolved field 8492 * r9 holds object 8493 */ 8494.LOP_IPUT_CHAR_finish: 8495 @bl common_squeak3 8496 mov r1, rINST, lsr #8 @ r1<- A+ 8497 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8498 and r1, r1, #15 @ r1<- A 8499 cmp r9, #0 @ check object for null 8500 GET_VREG(r0, r1) @ r0<- fp[A] 8501 beq common_errNullObject @ object was null 8502 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8503 GET_INST_OPCODE(ip) @ extract opcode from rINST 8504 @ no-op @ releasing store 8505 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8506 GOTO_OPCODE(ip) @ jump to next instruction 8507 8508/* continuation for OP_IPUT_SHORT */ 8509 8510 /* 8511 * Currently: 8512 * r0 holds resolved field 8513 * r9 holds object 8514 */ 8515.LOP_IPUT_SHORT_finish: 8516 @bl common_squeak4 8517 mov r1, rINST, lsr #8 @ r1<- A+ 8518 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8519 and r1, r1, #15 @ r1<- A 8520 cmp r9, #0 @ check object for null 8521 GET_VREG(r0, r1) @ r0<- fp[A] 8522 beq common_errNullObject @ object was null 8523 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8524 GET_INST_OPCODE(ip) @ extract opcode from rINST 8525 @ no-op @ releasing store 8526 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8527 GOTO_OPCODE(ip) @ jump to next instruction 8528 8529/* continuation for OP_SGET */ 8530 8531 /* 8532 * Continuation if the field has not yet been resolved. 8533 * r1: BBBB field ref 8534 */ 8535.LOP_SGET_resolve: 8536 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8537 EXPORT_PC() @ resolve() could throw, so export now 8538 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8539 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8540 cmp r0, #0 @ success? 8541 bne .LOP_SGET_finish @ yes, finish 8542 b common_exceptionThrown @ no, handle exception 8543 8544/* continuation for OP_SGET_WIDE */ 8545 8546 /* 8547 * Continuation if the field has not yet been resolved. 8548 * r1: BBBB field ref 8549 * 8550 * Returns StaticField pointer in r0. 8551 */ 8552.LOP_SGET_WIDE_resolve: 8553 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8554 EXPORT_PC() @ resolve() could throw, so export now 8555 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8556 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8557 cmp r0, #0 @ success? 8558 bne .LOP_SGET_WIDE_finish @ yes, finish 8559 b common_exceptionThrown @ no, handle exception 8560 8561/* continuation for OP_SGET_OBJECT */ 8562 8563 /* 8564 * Continuation if the field has not yet been resolved. 8565 * r1: BBBB field ref 8566 */ 8567.LOP_SGET_OBJECT_resolve: 8568 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8569 EXPORT_PC() @ resolve() could throw, so export now 8570 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8571 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8572 cmp r0, #0 @ success? 8573 bne .LOP_SGET_OBJECT_finish @ yes, finish 8574 b common_exceptionThrown @ no, handle exception 8575 8576/* continuation for OP_SGET_BOOLEAN */ 8577 8578 /* 8579 * Continuation if the field has not yet been resolved. 8580 * r1: BBBB field ref 8581 */ 8582.LOP_SGET_BOOLEAN_resolve: 8583 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8584 EXPORT_PC() @ resolve() could throw, so export now 8585 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8586 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8587 cmp r0, #0 @ success? 8588 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8589 b common_exceptionThrown @ no, handle exception 8590 8591/* continuation for OP_SGET_BYTE */ 8592 8593 /* 8594 * Continuation if the field has not yet been resolved. 8595 * r1: BBBB field ref 8596 */ 8597.LOP_SGET_BYTE_resolve: 8598 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8599 EXPORT_PC() @ resolve() could throw, so export now 8600 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8601 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8602 cmp r0, #0 @ success? 8603 bne .LOP_SGET_BYTE_finish @ yes, finish 8604 b common_exceptionThrown @ no, handle exception 8605 8606/* continuation for OP_SGET_CHAR */ 8607 8608 /* 8609 * Continuation if the field has not yet been resolved. 8610 * r1: BBBB field ref 8611 */ 8612.LOP_SGET_CHAR_resolve: 8613 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8614 EXPORT_PC() @ resolve() could throw, so export now 8615 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8616 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8617 cmp r0, #0 @ success? 8618 bne .LOP_SGET_CHAR_finish @ yes, finish 8619 b common_exceptionThrown @ no, handle exception 8620 8621/* continuation for OP_SGET_SHORT */ 8622 8623 /* 8624 * Continuation if the field has not yet been resolved. 8625 * r1: BBBB field ref 8626 */ 8627.LOP_SGET_SHORT_resolve: 8628 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8629 EXPORT_PC() @ resolve() could throw, so export now 8630 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8631 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8632 cmp r0, #0 @ success? 8633 bne .LOP_SGET_SHORT_finish @ yes, finish 8634 b common_exceptionThrown @ no, handle exception 8635 8636/* continuation for OP_SPUT */ 8637 8638 /* 8639 * Continuation if the field has not yet been resolved. 8640 * r1: BBBB field ref 8641 */ 8642.LOP_SPUT_resolve: 8643 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8644 EXPORT_PC() @ resolve() could throw, so export now 8645 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8646 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8647 cmp r0, #0 @ success? 8648 bne .LOP_SPUT_finish @ yes, finish 8649 b common_exceptionThrown @ no, handle exception 8650 8651/* continuation for OP_SPUT_WIDE */ 8652 8653 /* 8654 * Continuation if the field has not yet been resolved. 8655 * r1: BBBB field ref 8656 * r9: &fp[AA] 8657 * 8658 * Returns StaticField pointer in r2. 8659 */ 8660.LOP_SPUT_WIDE_resolve: 8661 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8662 EXPORT_PC() @ resolve() could throw, so export now 8663 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8664 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8665 cmp r0, #0 @ success? 8666 mov r2, r0 @ copy to r2 8667 bne .LOP_SPUT_WIDE_finish @ yes, finish 8668 b common_exceptionThrown @ no, handle exception 8669 8670/* continuation for OP_SPUT_OBJECT */ 8671.LOP_SPUT_OBJECT_finish: @ field ptr in r0 8672 mov r2, rINST, lsr #8 @ r2<- AA 8673 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8674 GET_VREG(r1, r2) @ r1<- fp[AA] 8675 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8676 GET_INST_OPCODE(ip) @ extract opcode from rINST 8677 add r0, #offStaticField_value @ r0<- pointer to store target 8678 @ no-op @ releasing store 8679 str r1, [r0] @ field<- vAA 8680 cmp r1, #0 @ stored a null object? 8681 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ mark card if not 8682 GOTO_OPCODE(ip) @ jump to next instruction 8683 8684/* continuation for OP_SPUT_BOOLEAN */ 8685 8686 /* 8687 * Continuation if the field has not yet been resolved. 8688 * r1: BBBB field ref 8689 */ 8690.LOP_SPUT_BOOLEAN_resolve: 8691 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8692 EXPORT_PC() @ resolve() could throw, so export now 8693 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8694 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8695 cmp r0, #0 @ success? 8696 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 8697 b common_exceptionThrown @ no, handle exception 8698 8699/* continuation for OP_SPUT_BYTE */ 8700 8701 /* 8702 * Continuation if the field has not yet been resolved. 8703 * r1: BBBB field ref 8704 */ 8705.LOP_SPUT_BYTE_resolve: 8706 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8707 EXPORT_PC() @ resolve() could throw, so export now 8708 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8709 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8710 cmp r0, #0 @ success? 8711 bne .LOP_SPUT_BYTE_finish @ yes, finish 8712 b common_exceptionThrown @ no, handle exception 8713 8714/* continuation for OP_SPUT_CHAR */ 8715 8716 /* 8717 * Continuation if the field has not yet been resolved. 8718 * r1: BBBB field ref 8719 */ 8720.LOP_SPUT_CHAR_resolve: 8721 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8722 EXPORT_PC() @ resolve() could throw, so export now 8723 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8724 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8725 cmp r0, #0 @ success? 8726 bne .LOP_SPUT_CHAR_finish @ yes, finish 8727 b common_exceptionThrown @ no, handle exception 8728 8729/* continuation for OP_SPUT_SHORT */ 8730 8731 /* 8732 * Continuation if the field has not yet been resolved. 8733 * r1: BBBB field ref 8734 */ 8735.LOP_SPUT_SHORT_resolve: 8736 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8737 EXPORT_PC() @ resolve() could throw, so export now 8738 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8739 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8740 cmp r0, #0 @ success? 8741 bne .LOP_SPUT_SHORT_finish @ yes, finish 8742 b common_exceptionThrown @ no, handle exception 8743 8744/* continuation for OP_INVOKE_VIRTUAL */ 8745 8746 /* 8747 * At this point: 8748 * r0 = resolved base method 8749 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8750 */ 8751.LOP_INVOKE_VIRTUAL_continue: 8752 GET_VREG(r1, r10) @ r1<- "this" ptr 8753 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8754 cmp r1, #0 @ is "this" null? 8755 beq common_errNullObject @ null "this", throw exception 8756 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8757 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8758 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8759 bl common_invokeMethodNoRange @ continue on 8760 8761/* continuation for OP_INVOKE_SUPER */ 8762 8763 /* 8764 * At this point: 8765 * r0 = resolved base method 8766 * r9 = method->clazz 8767 */ 8768.LOP_INVOKE_SUPER_continue: 8769 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8770 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8771 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8772 EXPORT_PC() @ must export for invoke 8773 cmp r2, r3 @ compare (methodIndex, vtableCount) 8774 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 8775 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8776 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8777 bl common_invokeMethodNoRange @ continue on 8778 8779.LOP_INVOKE_SUPER_resolve: 8780 mov r0, r9 @ r0<- method->clazz 8781 mov r2, #METHOD_VIRTUAL @ resolver method type 8782 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8783 cmp r0, #0 @ got null? 8784 bne .LOP_INVOKE_SUPER_continue @ no, continue 8785 b common_exceptionThrown @ yes, handle exception 8786 8787 /* 8788 * Throw a NoSuchMethodError with the method name as the message. 8789 * r0 = resolved base method 8790 */ 8791.LOP_INVOKE_SUPER_nsm: 8792 ldr r1, [r0, #offMethod_name] @ r1<- method name 8793 b common_errNoSuchMethod 8794 8795/* continuation for OP_INVOKE_DIRECT */ 8796 8797 /* 8798 * On entry: 8799 * r1 = reference (BBBB or CCCC) 8800 * r10 = "this" register 8801 */ 8802.LOP_INVOKE_DIRECT_resolve: 8803 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8804 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8805 mov r2, #METHOD_DIRECT @ resolver method type 8806 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8807 cmp r0, #0 @ got null? 8808 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8809 bne .LOP_INVOKE_DIRECT_finish @ no, continue 8810 b common_exceptionThrown @ yes, handle exception 8811 8812/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 8813 8814 /* 8815 * At this point: 8816 * r0 = resolved base method 8817 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8818 */ 8819.LOP_INVOKE_VIRTUAL_RANGE_continue: 8820 GET_VREG(r1, r10) @ r1<- "this" ptr 8821 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8822 cmp r1, #0 @ is "this" null? 8823 beq common_errNullObject @ null "this", throw exception 8824 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8825 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8826 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8827 bl common_invokeMethodRange @ continue on 8828 8829/* continuation for OP_INVOKE_SUPER_RANGE */ 8830 8831 /* 8832 * At this point: 8833 * r0 = resolved base method 8834 * r9 = method->clazz 8835 */ 8836.LOP_INVOKE_SUPER_RANGE_continue: 8837 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8838 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8839 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8840 EXPORT_PC() @ must export for invoke 8841 cmp r2, r3 @ compare (methodIndex, vtableCount) 8842 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 8843 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8844 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8845 bl common_invokeMethodRange @ continue on 8846 8847.LOP_INVOKE_SUPER_RANGE_resolve: 8848 mov r0, r9 @ r0<- method->clazz 8849 mov r2, #METHOD_VIRTUAL @ resolver method type 8850 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8851 cmp r0, #0 @ got null? 8852 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 8853 b common_exceptionThrown @ yes, handle exception 8854 8855 /* 8856 * Throw a NoSuchMethodError with the method name as the message. 8857 * r0 = resolved base method 8858 */ 8859.LOP_INVOKE_SUPER_RANGE_nsm: 8860 ldr r1, [r0, #offMethod_name] @ r1<- method name 8861 b common_errNoSuchMethod 8862 8863/* continuation for OP_INVOKE_DIRECT_RANGE */ 8864 8865 /* 8866 * On entry: 8867 * r1 = reference (BBBB or CCCC) 8868 * r10 = "this" register 8869 */ 8870.LOP_INVOKE_DIRECT_RANGE_resolve: 8871 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8872 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8873 mov r2, #METHOD_DIRECT @ resolver method type 8874 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8875 cmp r0, #0 @ got null? 8876 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8877 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 8878 b common_exceptionThrown @ yes, handle exception 8879 8880/* continuation for OP_FLOAT_TO_LONG */ 8881/* 8882 * Convert the float in r0 to a long in r0/r1. 8883 * 8884 * We have to clip values to long min/max per the specification. The 8885 * expected common case is a "reasonable" value that converts directly 8886 * to modest integer. The EABI convert function isn't doing this for us. 8887 */ 8888f2l_doconv: 8889 stmfd sp!, {r4, lr} 8890 mov r1, #0x5f000000 @ (float)maxlong 8891 mov r4, r0 8892 bl __aeabi_fcmpge @ is arg >= maxlong? 8893 cmp r0, #0 @ nonzero == yes 8894 mvnne r0, #0 @ return maxlong (7fffffff) 8895 mvnne r1, #0x80000000 8896 ldmnefd sp!, {r4, pc} 8897 8898 mov r0, r4 @ recover arg 8899 mov r1, #0xdf000000 @ (float)minlong 8900 bl __aeabi_fcmple @ is arg <= minlong? 8901 cmp r0, #0 @ nonzero == yes 8902 movne r0, #0 @ return minlong (80000000) 8903 movne r1, #0x80000000 8904 ldmnefd sp!, {r4, pc} 8905 8906 mov r0, r4 @ recover arg 8907 mov r1, r4 8908 bl __aeabi_fcmpeq @ is arg == self? 8909 cmp r0, #0 @ zero == no 8910 moveq r1, #0 @ return zero for NaN 8911 ldmeqfd sp!, {r4, pc} 8912 8913 mov r0, r4 @ recover arg 8914 bl __aeabi_f2lz @ convert float to long 8915 ldmfd sp!, {r4, pc} 8916 8917/* continuation for OP_DOUBLE_TO_LONG */ 8918/* 8919 * Convert the double in r0/r1 to a long in r0/r1. 8920 * 8921 * We have to clip values to long min/max per the specification. The 8922 * expected common case is a "reasonable" value that converts directly 8923 * to modest integer. The EABI convert function isn't doing this for us. 8924 */ 8925d2l_doconv: 8926 stmfd sp!, {r4, r5, lr} @ save regs 8927 mov r3, #0x43000000 @ maxlong, as a double (high word) 8928 add r3, #0x00e00000 @ 0x43e00000 8929 mov r2, #0 @ maxlong, as a double (low word) 8930 sub sp, sp, #4 @ align for EABI 8931 mov r4, r0 @ save a copy of r0 8932 mov r5, r1 @ and r1 8933 bl __aeabi_dcmpge @ is arg >= maxlong? 8934 cmp r0, #0 @ nonzero == yes 8935 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 8936 mvnne r1, #0x80000000 8937 bne 1f 8938 8939 mov r0, r4 @ recover arg 8940 mov r1, r5 8941 mov r3, #0xc3000000 @ minlong, as a double (high word) 8942 add r3, #0x00e00000 @ 0xc3e00000 8943 mov r2, #0 @ minlong, as a double (low word) 8944 bl __aeabi_dcmple @ is arg <= minlong? 8945 cmp r0, #0 @ nonzero == yes 8946 movne r0, #0 @ return minlong (8000000000000000) 8947 movne r1, #0x80000000 8948 bne 1f 8949 8950 mov r0, r4 @ recover arg 8951 mov r1, r5 8952 mov r2, r4 @ compare against self 8953 mov r3, r5 8954 bl __aeabi_dcmpeq @ is arg == self? 8955 cmp r0, #0 @ zero == no 8956 moveq r1, #0 @ return zero for NaN 8957 beq 1f 8958 8959 mov r0, r4 @ recover arg 8960 mov r1, r5 8961 bl __aeabi_d2lz @ convert double to long 8962 89631: 8964 add sp, sp, #4 8965 ldmfd sp!, {r4, r5, pc} 8966 8967/* continuation for OP_MUL_LONG */ 8968 8969.LOP_MUL_LONG_finish: 8970 GET_INST_OPCODE(ip) @ extract opcode from rINST 8971 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 8972 GOTO_OPCODE(ip) @ jump to next instruction 8973 8974/* continuation for OP_SHL_LONG */ 8975 8976.LOP_SHL_LONG_finish: 8977 mov r0, r0, asl r2 @ r0<- r0 << r2 8978 GET_INST_OPCODE(ip) @ extract opcode from rINST 8979 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8980 GOTO_OPCODE(ip) @ jump to next instruction 8981 8982/* continuation for OP_SHR_LONG */ 8983 8984.LOP_SHR_LONG_finish: 8985 mov r1, r1, asr r2 @ r1<- r1 >> r2 8986 GET_INST_OPCODE(ip) @ extract opcode from rINST 8987 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8988 GOTO_OPCODE(ip) @ jump to next instruction 8989 8990/* continuation for OP_USHR_LONG */ 8991 8992.LOP_USHR_LONG_finish: 8993 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 8994 GET_INST_OPCODE(ip) @ extract opcode from rINST 8995 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8996 GOTO_OPCODE(ip) @ jump to next instruction 8997 8998/* continuation for OP_SHL_LONG_2ADDR */ 8999 9000.LOP_SHL_LONG_2ADDR_finish: 9001 GET_INST_OPCODE(ip) @ extract opcode from rINST 9002 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9003 GOTO_OPCODE(ip) @ jump to next instruction 9004 9005/* continuation for OP_SHR_LONG_2ADDR */ 9006 9007.LOP_SHR_LONG_2ADDR_finish: 9008 GET_INST_OPCODE(ip) @ extract opcode from rINST 9009 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9010 GOTO_OPCODE(ip) @ jump to next instruction 9011 9012/* continuation for OP_USHR_LONG_2ADDR */ 9013 9014.LOP_USHR_LONG_2ADDR_finish: 9015 GET_INST_OPCODE(ip) @ extract opcode from rINST 9016 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9017 GOTO_OPCODE(ip) @ jump to next instruction 9018 9019/* continuation for OP_IGET_VOLATILE */ 9020 9021 /* 9022 * Currently: 9023 * r0 holds resolved field 9024 * r9 holds object 9025 */ 9026.LOP_IGET_VOLATILE_finish: 9027 @bl common_squeak0 9028 cmp r9, #0 @ check object for null 9029 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9030 beq common_errNullObject @ object was null 9031 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9032 SMP_DMB @ acquiring load 9033 mov r2, rINST, lsr #8 @ r2<- A+ 9034 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9035 and r2, r2, #15 @ r2<- A 9036 GET_INST_OPCODE(ip) @ extract opcode from rINST 9037 SET_VREG(r0, r2) @ fp[A]<- r0 9038 GOTO_OPCODE(ip) @ jump to next instruction 9039 9040/* continuation for OP_IPUT_VOLATILE */ 9041 9042 /* 9043 * Currently: 9044 * r0 holds resolved field 9045 * r9 holds object 9046 */ 9047.LOP_IPUT_VOLATILE_finish: 9048 @bl common_squeak0 9049 mov r1, rINST, lsr #8 @ r1<- A+ 9050 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9051 and r1, r1, #15 @ r1<- A 9052 cmp r9, #0 @ check object for null 9053 GET_VREG(r0, r1) @ r0<- fp[A] 9054 beq common_errNullObject @ object was null 9055 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9056 GET_INST_OPCODE(ip) @ extract opcode from rINST 9057 SMP_DMB @ releasing store 9058 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 9059 GOTO_OPCODE(ip) @ jump to next instruction 9060 9061/* continuation for OP_SGET_VOLATILE */ 9062 9063 /* 9064 * Continuation if the field has not yet been resolved. 9065 * r1: BBBB field ref 9066 */ 9067.LOP_SGET_VOLATILE_resolve: 9068 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9069 EXPORT_PC() @ resolve() could throw, so export now 9070 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9071 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9072 cmp r0, #0 @ success? 9073 bne .LOP_SGET_VOLATILE_finish @ yes, finish 9074 b common_exceptionThrown @ no, handle exception 9075 9076/* continuation for OP_SPUT_VOLATILE */ 9077 9078 /* 9079 * Continuation if the field has not yet been resolved. 9080 * r1: BBBB field ref 9081 */ 9082.LOP_SPUT_VOLATILE_resolve: 9083 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9084 EXPORT_PC() @ resolve() could throw, so export now 9085 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9086 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9087 cmp r0, #0 @ success? 9088 bne .LOP_SPUT_VOLATILE_finish @ yes, finish 9089 b common_exceptionThrown @ no, handle exception 9090 9091/* continuation for OP_IGET_OBJECT_VOLATILE */ 9092 9093 /* 9094 * Currently: 9095 * r0 holds resolved field 9096 * r9 holds object 9097 */ 9098.LOP_IGET_OBJECT_VOLATILE_finish: 9099 @bl common_squeak0 9100 cmp r9, #0 @ check object for null 9101 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9102 beq common_errNullObject @ object was null 9103 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9104 SMP_DMB @ acquiring load 9105 mov r2, rINST, lsr #8 @ r2<- A+ 9106 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9107 and r2, r2, #15 @ r2<- A 9108 GET_INST_OPCODE(ip) @ extract opcode from rINST 9109 SET_VREG(r0, r2) @ fp[A]<- r0 9110 GOTO_OPCODE(ip) @ jump to next instruction 9111 9112/* continuation for OP_IGET_WIDE_VOLATILE */ 9113 9114 /* 9115 * Currently: 9116 * r0 holds resolved field 9117 * r9 holds object 9118 */ 9119.LOP_IGET_WIDE_VOLATILE_finish: 9120 cmp r9, #0 @ check object for null 9121 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9122 beq common_errNullObject @ object was null 9123 .if 1 9124 add r0, r9, r3 @ r0<- address of field 9125 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 9126 .else 9127 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 9128 .endif 9129 mov r2, rINST, lsr #8 @ r2<- A+ 9130 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9131 and r2, r2, #15 @ r2<- A 9132 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 9133 GET_INST_OPCODE(ip) @ extract opcode from rINST 9134 stmia r3, {r0-r1} @ fp[A]<- r0/r1 9135 GOTO_OPCODE(ip) @ jump to next instruction 9136 9137/* continuation for OP_IPUT_WIDE_VOLATILE */ 9138 9139 /* 9140 * Currently: 9141 * r0 holds resolved field 9142 * r9 holds object 9143 */ 9144.LOP_IPUT_WIDE_VOLATILE_finish: 9145 mov r2, rINST, lsr #8 @ r2<- A+ 9146 cmp r9, #0 @ check object for null 9147 and r2, r2, #15 @ r2<- A 9148 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9149 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 9150 beq common_errNullObject @ object was null 9151 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9152 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 9153 GET_INST_OPCODE(r10) @ extract opcode from rINST 9154 .if 1 9155 add r2, r9, r3 @ r2<- target address 9156 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 9157 .else 9158 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 9159 .endif 9160 GOTO_OPCODE(r10) @ jump to next instruction 9161 9162/* continuation for OP_SGET_WIDE_VOLATILE */ 9163 9164 /* 9165 * Continuation if the field has not yet been resolved. 9166 * r1: BBBB field ref 9167 * 9168 * Returns StaticField pointer in r0. 9169 */ 9170.LOP_SGET_WIDE_VOLATILE_resolve: 9171 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9172 EXPORT_PC() @ resolve() could throw, so export now 9173 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9174 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9175 cmp r0, #0 @ success? 9176 bne .LOP_SGET_WIDE_VOLATILE_finish @ yes, finish 9177 b common_exceptionThrown @ no, handle exception 9178 9179/* continuation for OP_SPUT_WIDE_VOLATILE */ 9180 9181 /* 9182 * Continuation if the field has not yet been resolved. 9183 * r1: BBBB field ref 9184 * r9: &fp[AA] 9185 * 9186 * Returns StaticField pointer in r2. 9187 */ 9188.LOP_SPUT_WIDE_VOLATILE_resolve: 9189 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9190 EXPORT_PC() @ resolve() could throw, so export now 9191 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9192 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9193 cmp r0, #0 @ success? 9194 mov r2, r0 @ copy to r2 9195 bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish 9196 b common_exceptionThrown @ no, handle exception 9197 9198/* continuation for OP_EXECUTE_INLINE */ 9199 9200 /* 9201 * Extract args, call function. 9202 * r0 = #of args (0-4) 9203 * r10 = call index 9204 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9205 * 9206 * Other ideas: 9207 * - Use a jump table from the main piece to jump directly into the 9208 * AND/LDR pairs. Costs a data load, saves a branch. 9209 * - Have five separate pieces that do the loading, so we can work the 9210 * interleave a little better. Increases code size. 9211 */ 9212.LOP_EXECUTE_INLINE_continue: 9213 rsb r0, r0, #4 @ r0<- 4-r0 9214 FETCH(r9, 2) @ r9<- FEDC 9215 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9216 bl common_abort @ (skipped due to ARM prefetch) 92174: and ip, r9, #0xf000 @ isolate F 9218 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 92193: and ip, r9, #0x0f00 @ isolate E 9220 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 92212: and ip, r9, #0x00f0 @ isolate D 9222 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 92231: and ip, r9, #0x000f @ isolate C 9224 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 92250: 9226 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 9227 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9228 @ (not reached) 9229 9230.LOP_EXECUTE_INLINE_table: 9231 .word gDvmInlineOpsTable 9232 9233/* continuation for OP_EXECUTE_INLINE_RANGE */ 9234 9235 /* 9236 * Extract args, call function. 9237 * r0 = #of args (0-4) 9238 * r10 = call index 9239 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9240 */ 9241.LOP_EXECUTE_INLINE_RANGE_continue: 9242 rsb r0, r0, #4 @ r0<- 4-r0 9243 FETCH(r9, 2) @ r9<- CCCC 9244 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9245 bl common_abort @ (skipped due to ARM prefetch) 92464: add ip, r9, #3 @ base+3 9247 GET_VREG(r3, ip) @ r3<- vBase[3] 92483: add ip, r9, #2 @ base+2 9249 GET_VREG(r2, ip) @ r2<- vBase[2] 92502: add ip, r9, #1 @ base+1 9251 GET_VREG(r1, ip) @ r1<- vBase[1] 92521: add ip, r9, #0 @ (nop) 9253 GET_VREG(r0, ip) @ r0<- vBase[0] 92540: 9255 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation 9256 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9257 @ (not reached) 9258 9259.LOP_EXECUTE_INLINE_RANGE_table: 9260 .word gDvmInlineOpsTable 9261 9262/* continuation for OP_IPUT_OBJECT_VOLATILE */ 9263 9264 /* 9265 * Currently: 9266 * r0 holds resolved field 9267 * r9 holds object 9268 */ 9269.LOP_IPUT_OBJECT_VOLATILE_finish: 9270 @bl common_squeak0 9271 mov r1, rINST, lsr #8 @ r1<- A+ 9272 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9273 and r1, r1, #15 @ r1<- A 9274 cmp r9, #0 @ check object for null 9275 GET_VREG(r0, r1) @ r0<- fp[A] 9276 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 9277 beq common_errNullObject @ object was null 9278 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9279 add r9, r3 @ r9<- direct ptr to target location 9280 GET_INST_OPCODE(ip) @ extract opcode from rINST 9281 SMP_DMB @ releasing store 9282 str r0, [r9] @ obj.field (8/16/32 bits)<- r0 9283 cmp r0, #0 @ stored a null reference? 9284 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 9285 GOTO_OPCODE(ip) @ jump to next instruction 9286 9287/* continuation for OP_SGET_OBJECT_VOLATILE */ 9288 9289 /* 9290 * Continuation if the field has not yet been resolved. 9291 * r1: BBBB field ref 9292 */ 9293.LOP_SGET_OBJECT_VOLATILE_resolve: 9294 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9295 EXPORT_PC() @ resolve() could throw, so export now 9296 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9297 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9298 cmp r0, #0 @ success? 9299 bne .LOP_SGET_OBJECT_VOLATILE_finish @ yes, finish 9300 b common_exceptionThrown @ no, handle exception 9301 9302/* continuation for OP_SPUT_OBJECT_VOLATILE */ 9303.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0 9304 mov r2, rINST, lsr #8 @ r2<- AA 9305 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9306 GET_VREG(r1, r2) @ r1<- fp[AA] 9307 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 9308 GET_INST_OPCODE(ip) @ extract opcode from rINST 9309 add r0, #offStaticField_value @ r0<- pointer to store target 9310 SMP_DMB @ releasing store 9311 str r1, [r0] @ field<- vAA 9312 cmp r1, #0 @ stored a null object? 9313 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ mark card if not 9314 GOTO_OPCODE(ip) @ jump to next instruction 9315 9316 .size dvmAsmSisterStart, .-dvmAsmSisterStart 9317 .global dvmAsmSisterEnd 9318dvmAsmSisterEnd: 9319 9320/* File: armv5te/footer.S */ 9321 9322/* 9323 * =========================================================================== 9324 * Common subroutines and data 9325 * =========================================================================== 9326 */ 9327 9328 9329 9330 .text 9331 .align 2 9332 9333#if defined(WITH_JIT) 9334#if defined(WITH_SELF_VERIFICATION) 9335 .global dvmJitToInterpPunt 9336dvmJitToInterpPunt: 9337 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9338 mov r2,#kSVSPunt @ r2<- interpreter entry point 9339 mov r3, #0 9340 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9341 b jitSVShadowRunEnd @ doesn't return 9342 9343 .global dvmJitToInterpSingleStep 9344dvmJitToInterpSingleStep: 9345 str lr,[rGLUE,#offGlue_jitResumeNPC] 9346 str r1,[rGLUE,#offGlue_jitResumeDPC] 9347 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 9348 b jitSVShadowRunEnd @ doesn't return 9349 9350 .global dvmJitToInterpNoChainNoProfile 9351dvmJitToInterpNoChainNoProfile: 9352 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9353 mov r0,rPC @ pass our target PC 9354 mov r2,#kSVSNoProfile @ r2<- interpreter entry point 9355 mov r3, #0 @ 0 means !inJitCodeCache 9356 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land 9357 b jitSVShadowRunEnd @ doesn't return 9358 9359 .global dvmJitToInterpTraceSelectNoChain 9360dvmJitToInterpTraceSelectNoChain: 9361 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9362 mov r0,rPC @ pass our target PC 9363 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9364 mov r3, #0 @ 0 means !inJitCodeCache 9365 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9366 b jitSVShadowRunEnd @ doesn't return 9367 9368 .global dvmJitToInterpTraceSelect 9369dvmJitToInterpTraceSelect: 9370 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9371 ldr r0,[lr, #-1] @ pass our target PC 9372 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9373 mov r3, #0 @ 0 means !inJitCodeCache 9374 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9375 b jitSVShadowRunEnd @ doesn't return 9376 9377 .global dvmJitToInterpBackwardBranch 9378dvmJitToInterpBackwardBranch: 9379 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9380 ldr r0,[lr, #-1] @ pass our target PC 9381 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 9382 mov r3, #0 @ 0 means !inJitCodeCache 9383 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9384 b jitSVShadowRunEnd @ doesn't return 9385 9386 .global dvmJitToInterpNormal 9387dvmJitToInterpNormal: 9388 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9389 ldr r0,[lr, #-1] @ pass our target PC 9390 mov r2,#kSVSNormal @ r2<- interpreter entry point 9391 mov r3, #0 @ 0 means !inJitCodeCache 9392 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9393 b jitSVShadowRunEnd @ doesn't return 9394 9395 .global dvmJitToInterpNoChain 9396dvmJitToInterpNoChain: 9397 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9398 mov r0,rPC @ pass our target PC 9399 mov r2,#kSVSNoChain @ r2<- interpreter entry point 9400 mov r3, #0 @ 0 means !inJitCodeCache 9401 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9402 b jitSVShadowRunEnd @ doesn't return 9403#else 9404/* 9405 * Return from the translation cache to the interpreter when the compiler is 9406 * having issues translating/executing a Dalvik instruction. We have to skip 9407 * the code cache lookup otherwise it is possible to indefinitely bouce 9408 * between the interpreter and the code cache if the instruction that fails 9409 * to be compiled happens to be at a trace start. 9410 */ 9411 .global dvmJitToInterpPunt 9412dvmJitToInterpPunt: 9413 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9414 mov rPC, r0 9415#if defined(WITH_JIT_TUNING) 9416 mov r0,lr 9417 bl dvmBumpPunt; 9418#endif 9419 EXPORT_PC() 9420 mov r0, #0 9421 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9422 adrl rIBASE, dvmAsmInstructionStart 9423 FETCH_INST() 9424 GET_INST_OPCODE(ip) 9425 GOTO_OPCODE(ip) 9426 9427/* 9428 * Return to the interpreter to handle a single instruction. 9429 * On entry: 9430 * r0 <= PC 9431 * r1 <= PC of resume instruction 9432 * lr <= resume point in translation 9433 */ 9434 .global dvmJitToInterpSingleStep 9435dvmJitToInterpSingleStep: 9436 str lr,[rGLUE,#offGlue_jitResumeNPC] 9437 str r1,[rGLUE,#offGlue_jitResumeDPC] 9438 mov r1,#kInterpEntryInstr 9439 @ enum is 4 byte in aapcs-EABI 9440 str r1, [rGLUE, #offGlue_entryPoint] 9441 mov rPC,r0 9442 EXPORT_PC() 9443 9444 adrl rIBASE, dvmAsmInstructionStart 9445 mov r2,#kJitSingleStep @ Ask for single step and then revert 9446 str r2,[rGLUE,#offGlue_jitState] 9447 mov r1,#1 @ set changeInterp to bail to debug interp 9448 b common_gotoBail 9449 9450/* 9451 * Return from the translation cache and immediately request 9452 * a translation for the exit target. Commonly used for callees. 9453 */ 9454 .global dvmJitToInterpTraceSelectNoChain 9455dvmJitToInterpTraceSelectNoChain: 9456#if defined(WITH_JIT_TUNING) 9457 bl dvmBumpNoChain 9458#endif 9459 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9460 mov r0,rPC 9461 bl dvmJitGetCodeAddr @ Is there a translation? 9462 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9463 mov r1, rPC @ arg1 of translation may need this 9464 mov lr, #0 @ in case target is HANDLER_INTERPRET 9465 cmp r0,#0 @ !0 means translation exists 9466 bxne r0 @ continue native execution if so 9467 b 2f @ branch over to use the interpreter 9468 9469/* 9470 * Return from the translation cache and immediately request 9471 * a translation for the exit target. Commonly used following 9472 * invokes. 9473 */ 9474 .global dvmJitToInterpTraceSelect 9475dvmJitToInterpTraceSelect: 9476 ldr rPC,[lr, #-1] @ get our target PC 9477 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9478 add rINST,lr,#-5 @ save start of chain branch 9479 add rINST, #-4 @ .. which is 9 bytes back 9480 mov r0,rPC 9481 bl dvmJitGetCodeAddr @ Is there a translation? 9482 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9483 cmp r0,#0 9484 beq 2f 9485 mov r1,rINST 9486 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9487 mov r1, rPC @ arg1 of translation may need this 9488 mov lr, #0 @ in case target is HANDLER_INTERPRET 9489 cmp r0,#0 @ successful chain? 9490 bxne r0 @ continue native execution 9491 b toInterpreter @ didn't chain - resume with interpreter 9492 9493/* No translation, so request one if profiling isn't disabled*/ 94942: 9495 adrl rIBASE, dvmAsmInstructionStart 9496 GET_JIT_PROF_TABLE(r0) 9497 FETCH_INST() 9498 cmp r0, #0 9499 movne r2,#kJitTSelectRequestHot @ ask for trace selection 9500 bne common_selectTrace 9501 GET_INST_OPCODE(ip) 9502 GOTO_OPCODE(ip) 9503 9504/* 9505 * Return from the translation cache to the interpreter. 9506 * The return was done with a BLX from thumb mode, and 9507 * the following 32-bit word contains the target rPC value. 9508 * Note that lr (r14) will have its low-order bit set to denote 9509 * its thumb-mode origin. 9510 * 9511 * We'll need to stash our lr origin away, recover the new 9512 * target and then check to see if there is a translation available 9513 * for our new target. If so, we do a translation chain and 9514 * go back to native execution. Otherwise, it's back to the 9515 * interpreter (after treating this entry as a potential 9516 * trace start). 9517 */ 9518 .global dvmJitToInterpNormal 9519dvmJitToInterpNormal: 9520 ldr rPC,[lr, #-1] @ get our target PC 9521 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9522 add rINST,lr,#-5 @ save start of chain branch 9523 add rINST,#-4 @ .. which is 9 bytes back 9524#if defined(WITH_JIT_TUNING) 9525 bl dvmBumpNormal 9526#endif 9527 mov r0,rPC 9528 bl dvmJitGetCodeAddr @ Is there a translation? 9529 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9530 cmp r0,#0 9531 beq toInterpreter @ go if not, otherwise do chain 9532 mov r1,rINST 9533 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9534 mov r1, rPC @ arg1 of translation may need this 9535 mov lr, #0 @ in case target is HANDLER_INTERPRET 9536 cmp r0,#0 @ successful chain? 9537 bxne r0 @ continue native execution 9538 b toInterpreter @ didn't chain - resume with interpreter 9539 9540/* 9541 * Return from the translation cache to the interpreter to do method invocation. 9542 * Check if translation exists for the callee, but don't chain to it. 9543 */ 9544 .global dvmJitToInterpNoChainNoProfile 9545dvmJitToInterpNoChainNoProfile: 9546#if defined(WITH_JIT_TUNING) 9547 bl dvmBumpNoChain 9548#endif 9549 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9550 mov r0,rPC 9551 bl dvmJitGetCodeAddr @ Is there a translation? 9552 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9553 mov r1, rPC @ arg1 of translation may need this 9554 mov lr, #0 @ in case target is HANDLER_INTERPRET 9555 cmp r0,#0 9556 bxne r0 @ continue native execution if so 9557 EXPORT_PC() 9558 adrl rIBASE, dvmAsmInstructionStart 9559 FETCH_INST() 9560 GET_INST_OPCODE(ip) @ extract opcode from rINST 9561 GOTO_OPCODE(ip) @ jump to next instruction 9562 9563/* 9564 * Return from the translation cache to the interpreter to do method invocation. 9565 * Check if translation exists for the callee, but don't chain to it. 9566 */ 9567 .global dvmJitToInterpNoChain 9568dvmJitToInterpNoChain: 9569#if defined(WITH_JIT_TUNING) 9570 bl dvmBumpNoChain 9571#endif 9572 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9573 mov r0,rPC 9574 bl dvmJitGetCodeAddr @ Is there a translation? 9575 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9576 mov r1, rPC @ arg1 of translation may need this 9577 mov lr, #0 @ in case target is HANDLER_INTERPRET 9578 cmp r0,#0 9579 bxne r0 @ continue native execution if so 9580#endif 9581 9582/* 9583 * No translation, restore interpreter regs and start interpreting. 9584 * rGLUE & rFP were preserved in the translated code, and rPC has 9585 * already been restored by the time we get here. We'll need to set 9586 * up rIBASE & rINST, and load the address of the JitTable into r0. 9587 */ 9588toInterpreter: 9589 EXPORT_PC() 9590 adrl rIBASE, dvmAsmInstructionStart 9591 FETCH_INST() 9592 GET_JIT_PROF_TABLE(r0) 9593 @ NOTE: intended fallthrough 9594 9595/* 9596 * Common code to update potential trace start counter, and initiate 9597 * a trace-build if appropriate. On entry, rPC should point to the 9598 * next instruction to execute, and rINST should be already loaded with 9599 * the next opcode word, and r0 holds a pointer to the jit profile 9600 * table (pJitProfTable). 9601 */ 9602common_testUpdateProfile: 9603 cmp r0,#0 9604 GET_INST_OPCODE(ip) 9605 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 9606 9607common_updateProfile: 9608 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 9609 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits 9610 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter 9611 GET_INST_OPCODE(ip) 9612 subs r1,r1,#1 @ decrement counter 9613 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it 9614 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 9615 9616/* 9617 * Here, we switch to the debug interpreter to request 9618 * trace selection. First, though, check to see if there 9619 * is already a native translation in place (and, if so, 9620 * jump to it now). 9621 */ 9622 GET_JIT_THRESHOLD(r1) 9623 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9624 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter 9625 EXPORT_PC() 9626 mov r0,rPC 9627 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC) 9628 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9629 mov r1, rPC @ arg1 of translation may need this 9630 mov lr, #0 @ in case target is HANDLER_INTERPRET 9631 cmp r0,#0 9632#if !defined(WITH_SELF_VERIFICATION) 9633 bxne r0 @ jump to the translation 9634 mov r2,#kJitTSelectRequest @ ask for trace selection 9635 @ fall-through to common_selectTrace 9636#else 9637 moveq r2,#kJitTSelectRequest @ ask for trace selection 9638 beq common_selectTrace 9639 /* 9640 * At this point, we have a target translation. However, if 9641 * that translation is actually the interpret-only pseudo-translation 9642 * we want to treat it the same as no translation. 9643 */ 9644 mov r10, r0 @ save target 9645 bl dvmCompilerGetInterpretTemplate 9646 cmp r0, r10 @ special case? 9647 bne jitSVShadowRunStart @ set up self verification shadow space 9648 GET_INST_OPCODE(ip) 9649 GOTO_OPCODE(ip) 9650 /* no return */ 9651#endif 9652 9653/* 9654 * On entry: 9655 * r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot 9656 */ 9657common_selectTrace: 9658 str r2,[rGLUE,#offGlue_jitState] 9659 mov r2,#kInterpEntryInstr @ normal entry reason 9660 str r2,[rGLUE,#offGlue_entryPoint] 9661 mov r1,#1 @ set changeInterp 9662 b common_gotoBail 9663 9664#if defined(WITH_SELF_VERIFICATION) 9665/* 9666 * Save PC and registers to shadow memory for self verification mode 9667 * before jumping to native translation. 9668 * On entry: 9669 * rPC, rFP, rGLUE: the values that they should contain 9670 * r10: the address of the target translation. 9671 */ 9672jitSVShadowRunStart: 9673 mov r0,rPC @ r0<- program counter 9674 mov r1,rFP @ r1<- frame pointer 9675 mov r2,rGLUE @ r2<- InterpState pointer 9676 mov r3,r10 @ r3<- target translation 9677 bl dvmSelfVerificationSaveState @ save registers to shadow space 9678 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 9679 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 9680 bx r10 @ jump to the translation 9681 9682/* 9683 * Restore PC, registers, and interpState to original values 9684 * before jumping back to the interpreter. 9685 */ 9686jitSVShadowRunEnd: 9687 mov r1,rFP @ pass ending fp 9688 bl dvmSelfVerificationRestoreState @ restore pc and fp values 9689 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 9690 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 9691 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 9692 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 9693 cmp r1,#0 @ check for punt condition 9694 beq 1f 9695 mov r2,#kJitSelfVerification @ ask for self verification 9696 str r2,[rGLUE,#offGlue_jitState] 9697 mov r2,#kInterpEntryInstr @ normal entry reason 9698 str r2,[rGLUE,#offGlue_entryPoint] 9699 mov r1,#1 @ set changeInterp 9700 b common_gotoBail 9701 97021: @ exit to interpreter without check 9703 EXPORT_PC() 9704 adrl rIBASE, dvmAsmInstructionStart 9705 FETCH_INST() 9706 GET_INST_OPCODE(ip) 9707 GOTO_OPCODE(ip) 9708#endif 9709 9710#endif 9711 9712/* 9713 * Common code when a backward branch is taken. 9714 * 9715 * TODO: we could avoid a branch by just setting r0 and falling through 9716 * into the common_periodicChecks code, and having a test on r0 at the 9717 * end determine if we should return to the caller or update & branch to 9718 * the next instr. 9719 * 9720 * On entry: 9721 * r9 is PC adjustment *in bytes* 9722 */ 9723common_backwardBranch: 9724 mov r0, #kInterpEntryInstr 9725 bl common_periodicChecks 9726#if defined(WITH_JIT) 9727 GET_JIT_PROF_TABLE(r0) 9728 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9729 cmp r0,#0 9730 bne common_updateProfile 9731 GET_INST_OPCODE(ip) 9732 GOTO_OPCODE(ip) 9733#else 9734 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9735 GET_INST_OPCODE(ip) @ extract opcode from rINST 9736 GOTO_OPCODE(ip) @ jump to next instruction 9737#endif 9738 9739 9740/* 9741 * Need to see if the thread needs to be suspended or debugger/profiler 9742 * activity has begun. If so, we suspend the thread or side-exit to 9743 * the debug interpreter as appropriate. 9744 * 9745 * The common case is no activity on any of these, so we want to figure 9746 * that out quickly. If something is up, we can then sort out what. 9747 * 9748 * We want to be fast if the VM was built without debugger or profiler 9749 * support, but we also need to recognize that the system is usually 9750 * shipped with both of these enabled. 9751 * 9752 * TODO: reduce this so we're just checking a single location. 9753 * 9754 * On entry: 9755 * r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling) 9756 * r9 is trampoline PC adjustment *in bytes* 9757 */ 9758common_periodicChecks: 9759 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9760 9761 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9762 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9763 9764 ldr ip, [r3] @ ip<- suspendCount (int) 9765 9766 cmp r1, #0 @ debugger enabled? 9767 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9768 ldr r2, [r2] @ r2<- activeProfilers (int) 9769 orrnes ip, ip, r1 @ ip<- suspendCount | debuggerActive 9770 /* 9771 * Don't switch the interpreter in the libdvm_traceview build even if the 9772 * profiler is active. 9773 * The code here is opted for less intrusion instead of performance. 9774 * That is, *pActiveProfilers is still loaded into r2 even though it is not 9775 * used when WITH_INLINE_PROFILING is defined. 9776 */ 9777#if !defined(WITH_INLINE_PROFILING) 9778 orrs ip, ip, r2 @ ip<- suspend|debugger|profiler; set Z 9779#endif 9780 9781 9782 bxeq lr @ all zero, return 9783 9784 /* 9785 * One or more interesting events have happened. Figure out what. 9786 * 9787 * If debugging or profiling are compiled in, we need to disambiguate. 9788 * 9789 * r0 still holds the reentry type. 9790 */ 9791 ldr ip, [r3] @ ip<- suspendCount (int) 9792 cmp ip, #0 @ want suspend? 9793 beq 1f @ no, must be debugger/profiler 9794 9795 stmfd sp!, {r0, lr} @ preserve r0 and lr 9796#if defined(WITH_JIT) 9797 /* 9798 * Refresh the Jit's cached copy of profile table pointer. This pointer 9799 * doubles as the Jit's on/off switch. 9800 */ 9801 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable 9802 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9803 ldr r3, [r3] @ r3 <- pJitProfTable 9804 EXPORT_PC() @ need for precise GC 9805 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch 9806#else 9807 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9808 EXPORT_PC() @ need for precise GC 9809#endif 9810 bl dvmCheckSuspendPending @ do full check, suspend if necessary 9811 ldmfd sp!, {r0, lr} @ restore r0 and lr 9812 9813 /* 9814 * Reload the debugger/profiler enable flags. We're checking to see 9815 * if either of these got set while we were suspended. 9816 * 9817 * If WITH_INLINE_PROFILING is configured, don't check whether the profiler 9818 * is enabled or not as the profiling will be done inline. 9819 */ 9820 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9821 cmp r1, #0 @ debugger enabled? 9822 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9823 9824#if !defined(WITH_INLINE_PROFILING) 9825 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9826 ldr r2, [r2] @ r2<- activeProfilers (int) 9827 orrs r1, r1, r2 9828#else 9829 cmp r1, #0 @ only consult the debuggerActive flag 9830#endif 9831 9832 beq 2f 9833 98341: @ debugger/profiler enabled, bail out; glue->entryPoint was set above 9835 str r0, [rGLUE, #offGlue_entryPoint] @ store r0, need for debug/prof 9836 add rPC, rPC, r9 @ update rPC 9837 mov r1, #1 @ "want switch" = true 9838 b common_gotoBail @ side exit 9839 98402: 9841 bx lr @ nothing to do, return 9842 9843 9844/* 9845 * The equivalent of "goto bail", this calls through the "bail handler". 9846 * 9847 * State registers will be saved to the "glue" area before bailing. 9848 * 9849 * On entry: 9850 * r1 is "bool changeInterp", indicating if we want to switch to the 9851 * other interpreter or just bail all the way out 9852 */ 9853common_gotoBail: 9854 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9855 mov r0, rGLUE @ r0<- glue ptr 9856 b dvmMterpStdBail @ call(glue, changeInterp) 9857 9858 @add r1, r1, #1 @ using (boolean+1) 9859 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9860 @bl _longjmp @ does not return 9861 @bl common_abort 9862 9863 9864/* 9865 * Common code for method invocation with range. 9866 * 9867 * On entry: 9868 * r0 is "Method* methodToCall", the method we're trying to call 9869 */ 9870common_invokeMethodRange: 9871.LinvokeNewRange: 9872 @ prepare to copy args to "outs" area of current frame 9873 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9874 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9875 beq .LinvokeArgsDone @ if no args, skip the rest 9876 FETCH(r1, 2) @ r1<- CCCC 9877 9878 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9879 @ (very few methods have > 10 args; could unroll for common cases) 9880 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9881 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9882 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 98831: ldr r1, [r3], #4 @ val = *fp++ 9884 subs r2, r2, #1 @ count-- 9885 str r1, [r10], #4 @ *outs++ = val 9886 bne 1b @ ...while count != 0 9887 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9888 b .LinvokeArgsDone 9889 9890/* 9891 * Common code for method invocation without range. 9892 * 9893 * On entry: 9894 * r0 is "Method* methodToCall", the method we're trying to call 9895 */ 9896common_invokeMethodNoRange: 9897.LinvokeNewNoRange: 9898 @ prepare to copy args to "outs" area of current frame 9899 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9900 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9901 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9902 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9903 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9904 beq .LinvokeArgsDone 9905 9906 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9907.LinvokeNonRange: 9908 rsb r2, r2, #5 @ r2<- 5-r2 9909 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9910 bl common_abort @ (skipped due to ARM prefetch) 99115: and ip, rINST, #0x0f00 @ isolate A 9912 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 9913 mov r0, r0 @ nop 9914 str r2, [r10, #-4]! @ *--outs = vA 99154: and ip, r1, #0xf000 @ isolate G 9916 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 9917 mov r0, r0 @ nop 9918 str r2, [r10, #-4]! @ *--outs = vG 99193: and ip, r1, #0x0f00 @ isolate F 9920 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 9921 mov r0, r0 @ nop 9922 str r2, [r10, #-4]! @ *--outs = vF 99232: and ip, r1, #0x00f0 @ isolate E 9924 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 9925 mov r0, r0 @ nop 9926 str r2, [r10, #-4]! @ *--outs = vE 99271: and ip, r1, #0x000f @ isolate D 9928 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 9929 mov r0, r0 @ nop 9930 str r2, [r10, #-4]! @ *--outs = vD 99310: @ fall through to .LinvokeArgsDone 9932 9933.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 9934 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 9935 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 9936 @ find space for the new stack frame, check for overflow 9937 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 9938 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 9939 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 9940@ bl common_dumpRegs 9941 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 9942 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 9943 cmp r3, r9 @ bottom < interpStackEnd? 9944 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 9945 blo .LstackOverflow @ yes, this frame will overflow stack 9946 9947 @ set up newSaveArea 9948#ifdef EASY_GDB 9949 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 9950 str ip, [r10, #offStackSaveArea_prevSave] 9951#endif 9952 str rFP, [r10, #offStackSaveArea_prevFrame] 9953 str rPC, [r10, #offStackSaveArea_savedPc] 9954#if defined(WITH_JIT) 9955 mov r9, #0 9956 str r9, [r10, #offStackSaveArea_returnAddr] 9957#endif 9958#if defined(WITH_INLINE_PROFILING) 9959 stmfd sp!, {r0-r3} @ preserve r0-r3 9960 mov r1, r6 9961 @ r0=methodToCall, r1=rGlue 9962 bl dvmFastMethodTraceEnter 9963 ldmfd sp!, {r0-r3} @ restore r0-r3 9964#endif 9965 str r0, [r10, #offStackSaveArea_method] 9966 tst r3, #ACC_NATIVE 9967 bne .LinvokeNative 9968 9969 /* 9970 stmfd sp!, {r0-r3} 9971 bl common_printNewline 9972 mov r0, rFP 9973 mov r1, #0 9974 bl dvmDumpFp 9975 ldmfd sp!, {r0-r3} 9976 stmfd sp!, {r0-r3} 9977 mov r0, r1 9978 mov r1, r10 9979 bl dvmDumpFp 9980 bl common_printNewline 9981 ldmfd sp!, {r0-r3} 9982 */ 9983 9984 ldrh r9, [r2] @ r9 <- load INST from new PC 9985 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 9986 mov rPC, r2 @ publish new rPC 9987 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 9988 9989 @ Update "glue" values for the new method 9990 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 9991 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 9992 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 9993#if defined(WITH_JIT) 9994 GET_JIT_PROF_TABLE(r0) 9995 mov rFP, r1 @ fp = newFp 9996 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9997 mov rINST, r9 @ publish new rINST 9998 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9999 cmp r0,#0 10000 bne common_updateProfile 10001 GOTO_OPCODE(ip) @ jump to next instruction 10002#else 10003 mov rFP, r1 @ fp = newFp 10004 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 10005 mov rINST, r9 @ publish new rINST 10006 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 10007 GOTO_OPCODE(ip) @ jump to next instruction 10008#endif 10009 10010.LinvokeNative: 10011 @ Prep for the native call 10012 @ r0=methodToCall, r1=newFp, r10=newSaveArea 10013 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10014 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 10015 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 10016 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 10017 mov r9, r3 @ r9<- glue->self (preserve) 10018 10019 mov r2, r0 @ r2<- methodToCall 10020 mov r0, r1 @ r0<- newFp (points to args) 10021 add r1, rGLUE, #offGlue_retval @ r1<- &retval 10022 10023#ifdef ASSIST_DEBUGGER 10024 /* insert fake function header to help gdb find the stack frame */ 10025 b .Lskip 10026 .type dalvik_mterp, %function 10027dalvik_mterp: 10028 .fnstart 10029 MTERP_ENTRY1 10030 MTERP_ENTRY2 10031.Lskip: 10032#endif 10033 10034#if defined(WITH_INLINE_PROFILING) 10035 @ r2=JNIMethod, r6=rGLUE 10036 stmfd sp!, {r2,r6} 10037#endif 10038 10039 @mov lr, pc @ set return addr 10040 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 10041 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 10042 10043#if defined(WITH_INLINE_PROFILING) 10044 @ r0=JNIMethod, r1=rGLUE 10045 ldmfd sp!, {r0-r1} 10046 bl dvmFastNativeMethodTraceExit 10047#endif 10048 10049#if defined(WITH_JIT) 10050 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status 10051#endif 10052 10053 @ native return; r9=self, r10=newSaveArea 10054 @ equivalent to dvmPopJniLocals 10055 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 10056 ldr r1, [r9, #offThread_exception] @ check for exception 10057#if defined(WITH_JIT) 10058 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable 10059#endif 10060 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 10061 cmp r1, #0 @ null? 10062 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 10063#if defined(WITH_JIT) 10064 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch 10065#endif 10066 bne common_exceptionThrown @ no, handle exception 10067 10068 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 10069 GET_INST_OPCODE(ip) @ extract opcode from rINST 10070 GOTO_OPCODE(ip) @ jump to next instruction 10071 10072.LstackOverflow: @ r0=methodToCall 10073 mov r1, r0 @ r1<- methodToCall 10074 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 10075 bl dvmHandleStackOverflow 10076 b common_exceptionThrown 10077#ifdef ASSIST_DEBUGGER 10078 .fnend 10079#endif 10080 10081 10082 /* 10083 * Common code for method invocation, calling through "glue code". 10084 * 10085 * TODO: now that we have range and non-range invoke handlers, this 10086 * needs to be split into two. Maybe just create entry points 10087 * that set r9 and jump here? 10088 * 10089 * On entry: 10090 * r0 is "Method* methodToCall", the method we're trying to call 10091 * r9 is "bool methodCallRange", indicating if this is a /range variant 10092 */ 10093 .if 0 10094.LinvokeOld: 10095 sub sp, sp, #8 @ space for args + pad 10096 FETCH(ip, 2) @ ip<- FEDC or CCCC 10097 mov r2, r0 @ A2<- methodToCall 10098 mov r0, rGLUE @ A0<- glue 10099 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 10100 mov r1, r9 @ A1<- methodCallRange 10101 mov r3, rINST, lsr #8 @ A3<- AA 10102 str ip, [sp, #0] @ A4<- ip 10103 bl dvmMterp_invokeMethod @ call the C invokeMethod 10104 add sp, sp, #8 @ remove arg area 10105 b common_resumeAfterGlueCall @ continue to next instruction 10106 .endif 10107 10108 10109 10110/* 10111 * Common code for handling a return instruction. 10112 * 10113 * This does not return. 10114 */ 10115common_returnFromMethod: 10116.LreturnNew: 10117 mov r0, #kInterpEntryReturn 10118 mov r9, #0 10119 bl common_periodicChecks 10120 10121#if defined(WITH_INLINE_PROFILING) 10122 stmfd sp!, {r0-r3} @ preserve r0-r3 10123 mov r0, r6 10124 @ r0=rGlue 10125 bl dvmFastJavaMethodTraceExit 10126 ldmfd sp!, {r0-r3} @ restore r0-r3 10127#endif 10128 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 10129 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 10130 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 10131 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 10132 @ r2<- method we're returning to 10133 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10134 cmp r2, #0 @ is this a break frame? 10135 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 10136 mov r1, #0 @ "want switch" = false 10137 beq common_gotoBail @ break frame, bail out completely 10138 10139 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 10140 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 10141 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 10142 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 10143#if defined(WITH_JIT) 10144 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr 10145 mov rPC, r9 @ publish new rPC 10146 str r1, [rGLUE, #offGlue_methodClassDex] 10147 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land 10148 cmp r10, #0 @ caller is compiled code 10149 blxne r10 10150 GET_INST_OPCODE(ip) @ extract opcode from rINST 10151 GOTO_OPCODE(ip) @ jump to next instruction 10152#else 10153 GET_INST_OPCODE(ip) @ extract opcode from rINST 10154 mov rPC, r9 @ publish new rPC 10155 str r1, [rGLUE, #offGlue_methodClassDex] 10156 GOTO_OPCODE(ip) @ jump to next instruction 10157#endif 10158 10159 /* 10160 * Return handling, calls through "glue code". 10161 */ 10162 .if 0 10163.LreturnOld: 10164 SAVE_PC_FP_TO_GLUE() @ export state 10165 mov r0, rGLUE @ arg to function 10166 bl dvmMterp_returnFromMethod 10167 b common_resumeAfterGlueCall 10168 .endif 10169 10170 10171/* 10172 * Somebody has thrown an exception. Handle it. 10173 * 10174 * If the exception processing code returns to us (instead of falling 10175 * out of the interpreter), continue with whatever the next instruction 10176 * now happens to be. 10177 * 10178 * This does not return. 10179 */ 10180 .global dvmMterpCommonExceptionThrown 10181dvmMterpCommonExceptionThrown: 10182common_exceptionThrown: 10183.LexceptionNew: 10184 mov r0, #kInterpEntryThrow 10185 mov r9, #0 10186 bl common_periodicChecks 10187 10188 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 10189 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 10190 mov r1, r10 @ r1<- self 10191 mov r0, r9 @ r0<- exception 10192 bl dvmAddTrackedAlloc @ don't let the exception be GCed 10193 mov r3, #0 @ r3<- NULL 10194 str r3, [r10, #offThread_exception] @ self->exception = NULL 10195 10196 /* set up args and a local for "&fp" */ 10197 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 10198 str rFP, [sp, #-4]! @ *--sp = fp 10199 mov ip, sp @ ip<- &fp 10200 mov r3, #0 @ r3<- false 10201 str ip, [sp, #-4]! @ *--sp = &fp 10202 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 10203 mov r0, r10 @ r0<- self 10204 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 10205 mov r2, r9 @ r2<- exception 10206 sub r1, rPC, r1 @ r1<- pc - method->insns 10207 mov r1, r1, asr #1 @ r1<- offset in code units 10208 10209 /* call, r0 gets catchRelPc (a code-unit offset) */ 10210 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 10211 10212 /* fix earlier stack overflow if necessary; may trash rFP */ 10213 ldrb r1, [r10, #offThread_stackOverflowed] 10214 cmp r1, #0 @ did we overflow earlier? 10215 beq 1f @ no, skip ahead 10216 mov rFP, r0 @ save relPc result in rFP 10217 mov r0, r10 @ r0<- self 10218 mov r1, r9 @ r1<- exception 10219 bl dvmCleanupStackOverflow @ call(self) 10220 mov r0, rFP @ restore result 102211: 10222 10223 /* update frame pointer and check result from dvmFindCatchBlock */ 10224 ldr rFP, [sp, #4] @ retrieve the updated rFP 10225 cmp r0, #0 @ is catchRelPc < 0? 10226 add sp, sp, #8 @ restore stack 10227 bmi .LnotCaughtLocally 10228 10229 /* adjust locals to match self->curFrame and updated PC */ 10230 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 10231 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 10232 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 10233 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 10234 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 10235 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 10236 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 10237 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 10238 10239 /* release the tracked alloc on the exception */ 10240 mov r0, r9 @ r0<- exception 10241 mov r1, r10 @ r1<- self 10242 bl dvmReleaseTrackedAlloc @ release the exception 10243 10244 /* restore the exception if the handler wants it */ 10245 FETCH_INST() @ load rINST from rPC 10246 GET_INST_OPCODE(ip) @ extract opcode from rINST 10247 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 10248 streq r9, [r10, #offThread_exception] @ yes, restore the exception 10249 GOTO_OPCODE(ip) @ jump to next instruction 10250 10251.LnotCaughtLocally: @ r9=exception, r10=self 10252 /* fix stack overflow if necessary */ 10253 ldrb r1, [r10, #offThread_stackOverflowed] 10254 cmp r1, #0 @ did we overflow earlier? 10255 movne r0, r10 @ if yes: r0<- self 10256 movne r1, r9 @ if yes: r1<- exception 10257 blne dvmCleanupStackOverflow @ if yes: call(self) 10258 10259 @ may want to show "not caught locally" debug messages here 10260#if DVM_SHOW_EXCEPTION >= 2 10261 /* call __android_log_print(prio, tag, format, ...) */ 10262 /* "Exception %s from %s:%d not caught locally" */ 10263 @ dvmLineNumFromPC(method, pc - method->insns) 10264 ldr r0, [rGLUE, #offGlue_method] 10265 ldr r1, [r0, #offMethod_insns] 10266 sub r1, rPC, r1 10267 asr r1, r1, #1 10268 bl dvmLineNumFromPC 10269 str r0, [sp, #-4]! 10270 @ dvmGetMethodSourceFile(method) 10271 ldr r0, [rGLUE, #offGlue_method] 10272 bl dvmGetMethodSourceFile 10273 str r0, [sp, #-4]! 10274 @ exception->clazz->descriptor 10275 ldr r3, [r9, #offObject_clazz] 10276 ldr r3, [r3, #offClassObject_descriptor] 10277 @ 10278 ldr r2, strExceptionNotCaughtLocally 10279 ldr r1, strLogTag 10280 mov r0, #3 @ LOG_DEBUG 10281 bl __android_log_print 10282#endif 10283 str r9, [r10, #offThread_exception] @ restore exception 10284 mov r0, r9 @ r0<- exception 10285 mov r1, r10 @ r1<- self 10286 bl dvmReleaseTrackedAlloc @ release the exception 10287 mov r1, #0 @ "want switch" = false 10288 b common_gotoBail @ bail out 10289 10290 10291 /* 10292 * Exception handling, calls through "glue code". 10293 */ 10294 .if 0 10295.LexceptionOld: 10296 SAVE_PC_FP_TO_GLUE() @ export state 10297 mov r0, rGLUE @ arg to function 10298 bl dvmMterp_exceptionThrown 10299 b common_resumeAfterGlueCall 10300 .endif 10301 10302 10303/* 10304 * After returning from a "glued" function, pull out the updated 10305 * values and start executing at the next instruction. 10306 */ 10307common_resumeAfterGlueCall: 10308 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 10309 FETCH_INST() @ load rINST from rPC 10310 GET_INST_OPCODE(ip) @ extract opcode from rINST 10311 GOTO_OPCODE(ip) @ jump to next instruction 10312 10313/* 10314 * Invalid array index. 10315 */ 10316common_errArrayIndex: 10317 EXPORT_PC() 10318 ldr r0, strArrayIndexException 10319 mov r1, #0 10320 bl dvmThrowException 10321 b common_exceptionThrown 10322 10323/* 10324 * Invalid array value. 10325 */ 10326common_errArrayStore: 10327 EXPORT_PC() 10328 ldr r0, strArrayStoreException 10329 mov r1, #0 10330 bl dvmThrowException 10331 b common_exceptionThrown 10332 10333/* 10334 * Integer divide or mod by zero. 10335 */ 10336common_errDivideByZero: 10337 EXPORT_PC() 10338 ldr r0, strArithmeticException 10339 ldr r1, strDivideByZero 10340 bl dvmThrowException 10341 b common_exceptionThrown 10342 10343/* 10344 * Attempt to allocate an array with a negative size. 10345 */ 10346common_errNegativeArraySize: 10347 EXPORT_PC() 10348 ldr r0, strNegativeArraySizeException 10349 mov r1, #0 10350 bl dvmThrowException 10351 b common_exceptionThrown 10352 10353/* 10354 * Invocation of a non-existent method. 10355 */ 10356common_errNoSuchMethod: 10357 EXPORT_PC() 10358 ldr r0, strNoSuchMethodError 10359 mov r1, #0 10360 bl dvmThrowException 10361 b common_exceptionThrown 10362 10363/* 10364 * We encountered a null object when we weren't expecting one. We 10365 * export the PC, throw a NullPointerException, and goto the exception 10366 * processing code. 10367 */ 10368common_errNullObject: 10369 EXPORT_PC() 10370 ldr r0, strNullPointerException 10371 mov r1, #0 10372 bl dvmThrowException 10373 b common_exceptionThrown 10374 10375/* 10376 * For debugging, cause an immediate fault. The source address will 10377 * be in lr (use a bl instruction to jump here). 10378 */ 10379common_abort: 10380 ldr pc, .LdeadFood 10381.LdeadFood: 10382 .word 0xdeadf00d 10383 10384/* 10385 * Spit out a "we were here", preserving all registers. (The attempt 10386 * to save ip won't work, but we need to save an even number of 10387 * registers for EABI 64-bit stack alignment.) 10388 */ 10389 .macro SQUEAK num 10390common_squeak\num: 10391 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10392 ldr r0, strSqueak 10393 mov r1, #\num 10394 bl printf 10395 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10396 bx lr 10397 .endm 10398 10399 SQUEAK 0 10400 SQUEAK 1 10401 SQUEAK 2 10402 SQUEAK 3 10403 SQUEAK 4 10404 SQUEAK 5 10405 10406/* 10407 * Spit out the number in r0, preserving registers. 10408 */ 10409common_printNum: 10410 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10411 mov r1, r0 10412 ldr r0, strSqueak 10413 bl printf 10414 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10415 bx lr 10416 10417/* 10418 * Print a newline, preserving registers. 10419 */ 10420common_printNewline: 10421 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10422 ldr r0, strNewline 10423 bl printf 10424 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10425 bx lr 10426 10427 /* 10428 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 10429 */ 10430common_printHex: 10431 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10432 mov r1, r0 10433 ldr r0, strPrintHex 10434 bl printf 10435 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10436 bx lr 10437 10438/* 10439 * Print the 64-bit quantity in r0-r1, preserving registers. 10440 */ 10441common_printLong: 10442 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10443 mov r3, r1 10444 mov r2, r0 10445 ldr r0, strPrintLong 10446 bl printf 10447 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10448 bx lr 10449 10450/* 10451 * Print full method info. Pass the Method* in r0. Preserves regs. 10452 */ 10453common_printMethod: 10454 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10455 bl dvmMterpPrintMethod 10456 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10457 bx lr 10458 10459/* 10460 * Call a C helper function that dumps regs and possibly some 10461 * additional info. Requires the C function to be compiled in. 10462 */ 10463 .if 0 10464common_dumpRegs: 10465 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10466 bl dvmMterpDumpArmRegs 10467 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10468 bx lr 10469 .endif 10470 10471#if 0 10472/* 10473 * Experiment on VFP mode. 10474 * 10475 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 10476 * 10477 * Updates the bits specified by "mask", setting them to the values in "val". 10478 */ 10479setFPSCR: 10480 and r0, r0, r1 @ make sure no stray bits are set 10481 fmrx r2, fpscr @ get VFP reg 10482 mvn r1, r1 @ bit-invert mask 10483 and r2, r2, r1 @ clear masked bits 10484 orr r2, r2, r0 @ set specified bits 10485 fmxr fpscr, r2 @ set VFP reg 10486 mov r0, r2 @ return new value 10487 bx lr 10488 10489 .align 2 10490 .global dvmConfigureFP 10491 .type dvmConfigureFP, %function 10492dvmConfigureFP: 10493 stmfd sp!, {ip, lr} 10494 /* 0x03000000 sets DN/FZ */ 10495 /* 0x00009f00 clears the six exception enable flags */ 10496 bl common_squeak0 10497 mov r0, #0x03000000 @ r0<- 0x03000000 10498 add r1, r0, #0x9f00 @ r1<- 0x03009f00 10499 bl setFPSCR 10500 ldmfd sp!, {ip, pc} 10501#endif 10502 10503 10504/* 10505 * String references, must be close to the code that uses them. 10506 */ 10507 .align 2 10508strArithmeticException: 10509 .word .LstrArithmeticException 10510strArrayIndexException: 10511 .word .LstrArrayIndexException 10512strArrayStoreException: 10513 .word .LstrArrayStoreException 10514strDivideByZero: 10515 .word .LstrDivideByZero 10516strNegativeArraySizeException: 10517 .word .LstrNegativeArraySizeException 10518strNoSuchMethodError: 10519 .word .LstrNoSuchMethodError 10520strNullPointerException: 10521 .word .LstrNullPointerException 10522 10523strLogTag: 10524 .word .LstrLogTag 10525strExceptionNotCaughtLocally: 10526 .word .LstrExceptionNotCaughtLocally 10527 10528strNewline: 10529 .word .LstrNewline 10530strSqueak: 10531 .word .LstrSqueak 10532strPrintHex: 10533 .word .LstrPrintHex 10534strPrintLong: 10535 .word .LstrPrintLong 10536 10537/* 10538 * Zero-terminated ASCII string data. 10539 * 10540 * On ARM we have two choices: do like gcc does, and LDR from a .word 10541 * with the address, or use an ADR pseudo-op to get the address 10542 * directly. ADR saves 4 bytes and an indirection, but it's using a 10543 * PC-relative addressing mode and hence has a limited range, which 10544 * makes it not work well with mergeable string sections. 10545 */ 10546 .section .rodata.str1.4,"aMS",%progbits,1 10547 10548.LstrBadEntryPoint: 10549 .asciz "Bad entry point %d\n" 10550.LstrArithmeticException: 10551 .asciz "Ljava/lang/ArithmeticException;" 10552.LstrArrayIndexException: 10553 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 10554.LstrArrayStoreException: 10555 .asciz "Ljava/lang/ArrayStoreException;" 10556.LstrClassCastException: 10557 .asciz "Ljava/lang/ClassCastException;" 10558.LstrDivideByZero: 10559 .asciz "divide by zero" 10560.LstrFilledNewArrayNotImpl: 10561 .asciz "filled-new-array only implemented for objects and 'int'" 10562.LstrInternalError: 10563 .asciz "Ljava/lang/InternalError;" 10564.LstrInstantiationError: 10565 .asciz "Ljava/lang/InstantiationError;" 10566.LstrNegativeArraySizeException: 10567 .asciz "Ljava/lang/NegativeArraySizeException;" 10568.LstrNoSuchMethodError: 10569 .asciz "Ljava/lang/NoSuchMethodError;" 10570.LstrNullPointerException: 10571 .asciz "Ljava/lang/NullPointerException;" 10572 10573.LstrLogTag: 10574 .asciz "mterp" 10575.LstrExceptionNotCaughtLocally: 10576 .asciz "Exception %s from %s:%d not caught locally\n" 10577 10578.LstrNewline: 10579 .asciz "\n" 10580.LstrSqueak: 10581 .asciz "<%d>" 10582.LstrPrintHex: 10583 .asciz "<0x%x>" 10584.LstrPrintLong: 10585 .asciz "<%lld>" 10586 10587