InterpAsm-armv7-a.S revision c95e0fbce4f77b2b08eb48205e405793de0d4248
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 * ARMv5 definitions and declarations. 25 */ 26 27/* 28ARM EABI general notes: 29 30r0-r3 hold first 4 args to a method; they are not preserved across method calls 31r4-r8 are available for general use 32r9 is given special treatment in some situations, but not for us 33r10 (sl) seems to be generally available 34r11 (fp) is used by gcc (unless -fomit-frame-pointer is set) 35r12 (ip) is scratch -- not preserved across method calls 36r13 (sp) should be managed carefully in case a signal arrives 37r14 (lr) must be preserved 38r15 (pc) can be tinkered with directly 39 40r0 holds returns of <= 4 bytes 41r0-r1 hold returns of 8 bytes, low word in r0 42 43Callee must save/restore r4+ (except r12) if it modifies them. If VFP 44is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved, 45s0-s15 (d0-d7, q0-a3) do not need to be. 46 47Stack is "full descending". Only the arguments that don't fit in the first 4 48registers are placed on the stack. "sp" points at the first stacked argument 49(i.e. the 5th arg). 50 51VFP: single-precision results in s0, double-precision results in d0. 52 53In the EABI, "sp" must be 64-bit aligned on entry to a function, and any 5464-bit quantities (long long, double) must be 64-bit aligned. 55*/ 56 57/* 58Mterp and ARM notes: 59 60The following registers have fixed assignments: 61 62 reg nick purpose 63 r4 rPC interpreted program counter, used for fetching instructions 64 r5 rFP interpreted frame pointer, used for accessing locals and args 65 r6 rGLUE MterpGlue pointer 66 r7 rINST first 16-bit code unit of current instruction 67 r8 rIBASE interpreted instruction base pointer, used for computed goto 68 69Macros are provided for common operations. Each macro MUST emit only 70one instruction to make instruction-counting easier. They MUST NOT alter 71unspecified registers or condition codes. 72*/ 73 74/* single-purpose registers, given names for clarity */ 75#define rPC r4 76#define rFP r5 77#define rGLUE r6 78#define rINST r7 79#define rIBASE r8 80 81/* save/restore the PC and/or FP from the glue struct */ 82#define LOAD_PC_FROM_GLUE() ldr rPC, [rGLUE, #offGlue_pc] 83#define SAVE_PC_TO_GLUE() str rPC, [rGLUE, #offGlue_pc] 84#define LOAD_FP_FROM_GLUE() ldr rFP, [rGLUE, #offGlue_fp] 85#define SAVE_FP_TO_GLUE() str rFP, [rGLUE, #offGlue_fp] 86#define LOAD_PC_FP_FROM_GLUE() ldmia rGLUE, {rPC, rFP} 87#define SAVE_PC_FP_TO_GLUE() stmia rGLUE, {rPC, rFP} 88 89/* 90 * "export" the PC to the stack frame, f/b/o future exception objects. Must 91 * be done *before* something calls dvmThrowException. 92 * 93 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e. 94 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc) 95 * 96 * It's okay to do this more than once. 97 */ 98#define EXPORT_PC() \ 99 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)] 100 101/* 102 * Given a frame pointer, find the stack save area. 103 * 104 * In C this is "((StackSaveArea*)(_fp) -1)". 105 */ 106#define SAVEAREA_FROM_FP(_reg, _fpreg) \ 107 sub _reg, _fpreg, #sizeofStackSaveArea 108 109/* 110 * Fetch the next instruction from rPC into rINST. Does not advance rPC. 111 */ 112#define FETCH_INST() ldrh rINST, [rPC] 113 114/* 115 * Fetch the next instruction from the specified offset. Advances rPC 116 * to point to the next instruction. "_count" is in 16-bit code units. 117 * 118 * Because of the limited size of immediate constants on ARM, this is only 119 * suitable for small forward movements (i.e. don't try to implement "goto" 120 * with this). 121 * 122 * This must come AFTER anything that can throw an exception, or the 123 * exception catch may miss. (This also implies that it must come after 124 * EXPORT_PC().) 125 */ 126#define FETCH_ADVANCE_INST(_count) ldrh rINST, [rPC, #(_count*2)]! 127 128/* 129 * The operation performed here is similar to FETCH_ADVANCE_INST, except the 130 * src and dest registers are parameterized (not hard-wired to rPC and rINST). 131 */ 132#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \ 133 ldrh _dreg, [_sreg, #(_count*2)]! 134 135/* 136 * Fetch the next instruction from an offset specified by _reg. Updates 137 * rPC to point to the next instruction. "_reg" must specify the distance 138 * in bytes, *not* 16-bit code units, and may be a signed value. 139 * 140 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the 141 * bits that hold the shift distance are used for the half/byte/sign flags. 142 * In some cases we can pre-double _reg for free, so we require a byte offset 143 * here. 144 */ 145#define FETCH_ADVANCE_INST_RB(_reg) ldrh rINST, [rPC, _reg]! 146 147/* 148 * Fetch a half-word code unit from an offset past the current PC. The 149 * "_count" value is in 16-bit code units. Does not advance rPC. 150 * 151 * The "_S" variant works the same but treats the value as signed. 152 */ 153#define FETCH(_reg, _count) ldrh _reg, [rPC, #(_count*2)] 154#define FETCH_S(_reg, _count) ldrsh _reg, [rPC, #(_count*2)] 155 156/* 157 * Fetch one byte from an offset past the current PC. Pass in the same 158 * "_count" as you would for FETCH, and an additional 0/1 indicating which 159 * byte of the halfword you want (lo/hi). 160 */ 161#define FETCH_B(_reg, _count, _byte) ldrb _reg, [rPC, #(_count*2+_byte)] 162 163/* 164 * Put the instruction's opcode field into the specified register. 165 */ 166#define GET_INST_OPCODE(_reg) and _reg, rINST, #255 167 168/* 169 * Put the prefetched instruction's opcode field into the specified register. 170 */ 171#define GET_PREFETCHED_OPCODE(_oreg, _ireg) and _oreg, _ireg, #255 172 173/* 174 * Begin executing the opcode in _reg. Because this only jumps within the 175 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork. 176 */ 177#define GOTO_OPCODE(_reg) add pc, rIBASE, _reg, lsl #6 178#define GOTO_OPCODE_IFEQ(_reg) addeq pc, rIBASE, _reg, lsl #6 179#define GOTO_OPCODE_IFNE(_reg) addne pc, rIBASE, _reg, lsl #6 180 181/* 182 * Get/set the 32-bit value from a Dalvik register. 183 */ 184#define GET_VREG(_reg, _vreg) ldr _reg, [rFP, _vreg, lsl #2] 185#define SET_VREG(_reg, _vreg) str _reg, [rFP, _vreg, lsl #2] 186 187#if defined(WITH_JIT) 188#define GET_JIT_PROF_TABLE(_reg) ldr _reg,[rGLUE,#offGlue_pJitProfTable] 189#define GET_JIT_THRESHOLD(_reg) ldr _reg,[rGLUE,#offGlue_jitThreshold] 190#endif 191 192/* 193 * Convert a virtual register index into an address. 194 */ 195#define VREG_INDEX_TO_ADDR(_reg, _vreg) \ 196 add _reg, rFP, _vreg, lsl #2 197 198/* 199 * This is a #include, not a %include, because we want the C pre-processor 200 * to expand the macros into assembler assignment statements. 201 */ 202#include "../common/asm-constants.h" 203 204#if defined(WITH_JIT) 205#include "../common/jit-config.h" 206#endif 207 208/* File: armv5te/platform.S */ 209/* 210 * =========================================================================== 211 * CPU-version-specific defines 212 * =========================================================================== 213 */ 214 215/* 216 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5. Essentially a 217 * one-way branch. 218 * 219 * May modify IP. Does not modify LR. 220 */ 221.macro LDR_PC source 222 ldr pc, \source 223.endm 224 225/* 226 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5. 227 * Jump to subroutine. 228 * 229 * May modify IP and LR. 230 */ 231.macro LDR_PC_LR source 232 mov lr, pc 233 ldr pc, \source 234.endm 235 236/* 237 * Macro for "LDMFD SP!, {...regs...,PC}". 238 * 239 * May modify IP and LR. 240 */ 241.macro LDMFD_PC regs 242 ldmfd sp!, {\regs,pc} 243.endm 244 245 246/* File: armv5te/entry.S */ 247/* 248 * Copyright (C) 2008 The Android Open Source Project 249 * 250 * Licensed under the Apache License, Version 2.0 (the "License"); 251 * you may not use this file except in compliance with the License. 252 * You may obtain a copy of the License at 253 * 254 * http://www.apache.org/licenses/LICENSE-2.0 255 * 256 * Unless required by applicable law or agreed to in writing, software 257 * distributed under the License is distributed on an "AS IS" BASIS, 258 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 259 * See the License for the specific language governing permissions and 260 * limitations under the License. 261 */ 262/* 263 * Interpreter entry point. 264 */ 265 266/* 267 * We don't have formal stack frames, so gdb scans upward in the code 268 * to find the start of the function (a label with the %function type), 269 * and then looks at the next few instructions to figure out what 270 * got pushed onto the stack. From this it figures out how to restore 271 * the registers, including PC, for the previous stack frame. If gdb 272 * sees a non-function label, it stops scanning, so either we need to 273 * have nothing but assembler-local labels between the entry point and 274 * the break, or we need to fake it out. 275 * 276 * When this is defined, we add some stuff to make gdb less confused. 277 */ 278#define ASSIST_DEBUGGER 1 279 280 .text 281 .align 2 282 .global dvmMterpStdRun 283 .type dvmMterpStdRun, %function 284 285/* 286 * On entry: 287 * r0 MterpGlue* glue 288 * 289 * This function returns a boolean "changeInterp" value. The return comes 290 * via a call to dvmMterpStdBail(). 291 */ 292dvmMterpStdRun: 293#define MTERP_ENTRY1 \ 294 .save {r4-r10,fp,lr}; \ 295 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs 296#define MTERP_ENTRY2 \ 297 .pad #4; \ 298 sub sp, sp, #4 @ align 64 299 300 .fnstart 301 MTERP_ENTRY1 302 MTERP_ENTRY2 303 304 /* save stack pointer, add magic word for debuggerd */ 305 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return 306 307 /* set up "named" registers, figure out entry point */ 308 mov rGLUE, r0 @ set rGLUE 309 ldr r1, [r0, #offGlue_entryPoint] @ enum is 4 bytes in aapcs-EABI 310 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue" 311 adr rIBASE, dvmAsmInstructionStart @ set rIBASE 312 cmp r1, #kInterpEntryInstr @ usual case? 313 bne .Lnot_instr @ no, handle it 314 315#if defined(WITH_JIT) 316.LentryInstr: 317 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 318 /* Entry is always a possible trace start */ 319 GET_JIT_PROF_TABLE(r0) 320 FETCH_INST() 321 mov r1, #0 @ prepare the value for the new state 322 str r1, [r10, #offThread_inJitCodeCache] @ back to the interp land 323 cmp r0,#0 324 bne common_updateProfile 325 GET_INST_OPCODE(ip) 326 GOTO_OPCODE(ip) 327#else 328 /* start executing the instruction at rPC */ 329 FETCH_INST() @ load rINST from rPC 330 GET_INST_OPCODE(ip) @ extract opcode from rINST 331 GOTO_OPCODE(ip) @ jump to next instruction 332#endif 333 334.Lnot_instr: 335 cmp r1, #kInterpEntryReturn @ were we returning from a method? 336 beq common_returnFromMethod 337 338.Lnot_return: 339 cmp r1, #kInterpEntryThrow @ were we throwing an exception? 340 beq common_exceptionThrown 341 342#if defined(WITH_JIT) 343.Lnot_throw: 344 ldr r10,[rGLUE, #offGlue_jitResumeNPC] 345 ldr r2,[rGLUE, #offGlue_jitResumeDPC] 346 cmp r1, #kInterpEntryResume @ resuming after Jit single-step? 347 bne .Lbad_arg 348 cmp rPC,r2 349 bne .LentryInstr @ must have branched, don't resume 350#if defined(WITH_SELF_VERIFICATION) 351 @ glue->entryPoint will be set in dvmSelfVerificationSaveState 352 b jitSVShadowRunStart @ re-enter the translation after the 353 @ single-stepped instruction 354 @noreturn 355#endif 356 mov r1, #kInterpEntryInstr 357 str r1, [rGLUE, #offGlue_entryPoint] 358 bx r10 @ re-enter the translation 359#endif 360 361.Lbad_arg: 362 ldr r0, strBadEntryPoint 363 @ r1 holds value of entryPoint 364 bl printf 365 bl dvmAbort 366 .fnend 367 368 369 .global dvmMterpStdBail 370 .type dvmMterpStdBail, %function 371 372/* 373 * Restore the stack pointer and PC from the save point established on entry. 374 * This is essentially the same as a longjmp, but should be cheaper. The 375 * last instruction causes us to return to whoever called dvmMterpStdRun. 376 * 377 * We pushed some registers on the stack in dvmMterpStdRun, then saved 378 * SP and LR. Here we restore SP, restore the registers, and then restore 379 * LR to PC. 380 * 381 * On entry: 382 * r0 MterpGlue* glue 383 * r1 bool changeInterp 384 */ 385dvmMterpStdBail: 386 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 387 mov r0, r1 @ return the changeInterp value 388 add sp, sp, #4 @ un-align 64 389 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return 390 391 392/* 393 * String references. 394 */ 395strBadEntryPoint: 396 .word .LstrBadEntryPoint 397 398 399 400 .global dvmAsmInstructionStart 401 .type dvmAsmInstructionStart, %function 402dvmAsmInstructionStart = .L_OP_NOP 403 .text 404 405/* ------------------------------ */ 406 .balign 64 407.L_OP_NOP: /* 0x00 */ 408/* File: armv5te/OP_NOP.S */ 409 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST 410 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 411 GOTO_OPCODE(ip) @ execute it 412 413#ifdef ASSIST_DEBUGGER 414 /* insert fake function header to help gdb find the stack frame */ 415 .type dalvik_inst, %function 416dalvik_inst: 417 .fnstart 418 MTERP_ENTRY1 419 MTERP_ENTRY2 420 .fnend 421#endif 422 423 424/* ------------------------------ */ 425 .balign 64 426.L_OP_MOVE: /* 0x01 */ 427/* File: armv6t2/OP_MOVE.S */ 428 /* for move, move-object, long-to-int */ 429 /* op vA, vB */ 430 mov r1, rINST, lsr #12 @ r1<- B from 15:12 431 ubfx r0, rINST, #8, #4 @ r0<- A from 11:8 432 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 433 GET_VREG(r2, r1) @ r2<- fp[B] 434 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 435 SET_VREG(r2, r0) @ fp[A]<- r2 436 GOTO_OPCODE(ip) @ execute next instruction 437 438 439/* ------------------------------ */ 440 .balign 64 441.L_OP_MOVE_FROM16: /* 0x02 */ 442/* File: armv5te/OP_MOVE_FROM16.S */ 443 /* for: move/from16, move-object/from16 */ 444 /* op vAA, vBBBB */ 445 FETCH(r1, 1) @ r1<- BBBB 446 mov r0, rINST, lsr #8 @ r0<- AA 447 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 448 GET_VREG(r2, r1) @ r2<- fp[BBBB] 449 GET_INST_OPCODE(ip) @ extract opcode from rINST 450 SET_VREG(r2, r0) @ fp[AA]<- r2 451 GOTO_OPCODE(ip) @ jump to next instruction 452 453 454/* ------------------------------ */ 455 .balign 64 456.L_OP_MOVE_16: /* 0x03 */ 457/* File: armv5te/OP_MOVE_16.S */ 458 /* for: move/16, move-object/16 */ 459 /* op vAAAA, vBBBB */ 460 FETCH(r1, 2) @ r1<- BBBB 461 FETCH(r0, 1) @ r0<- AAAA 462 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 463 GET_VREG(r2, r1) @ r2<- fp[BBBB] 464 GET_INST_OPCODE(ip) @ extract opcode from rINST 465 SET_VREG(r2, r0) @ fp[AAAA]<- r2 466 GOTO_OPCODE(ip) @ jump to next instruction 467 468 469/* ------------------------------ */ 470 .balign 64 471.L_OP_MOVE_WIDE: /* 0x04 */ 472/* File: armv6t2/OP_MOVE_WIDE.S */ 473 /* move-wide vA, vB */ 474 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 475 mov r3, rINST, lsr #12 @ r3<- B 476 ubfx r2, rINST, #8, #4 @ r2<- A 477 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 478 add r2, rFP, r2, lsl #2 @ r2<- &fp[A] 479 ldmia r3, {r0-r1} @ r0/r1<- fp[B] 480 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 481 GET_INST_OPCODE(ip) @ extract opcode from rINST 482 stmia r2, {r0-r1} @ fp[A]<- r0/r1 483 GOTO_OPCODE(ip) @ jump to next instruction 484 485 486/* ------------------------------ */ 487 .balign 64 488.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 489/* File: armv5te/OP_MOVE_WIDE_FROM16.S */ 490 /* move-wide/from16 vAA, vBBBB */ 491 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 492 FETCH(r3, 1) @ r3<- BBBB 493 mov r2, rINST, lsr #8 @ r2<- AA 494 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 495 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 496 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 497 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 498 GET_INST_OPCODE(ip) @ extract opcode from rINST 499 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 500 GOTO_OPCODE(ip) @ jump to next instruction 501 502 503/* ------------------------------ */ 504 .balign 64 505.L_OP_MOVE_WIDE_16: /* 0x06 */ 506/* File: armv5te/OP_MOVE_WIDE_16.S */ 507 /* move-wide/16 vAAAA, vBBBB */ 508 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 509 FETCH(r3, 2) @ r3<- BBBB 510 FETCH(r2, 1) @ r2<- AAAA 511 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 512 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA] 513 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 514 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 515 GET_INST_OPCODE(ip) @ extract opcode from rINST 516 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1 517 GOTO_OPCODE(ip) @ jump to next instruction 518 519 520/* ------------------------------ */ 521 .balign 64 522.L_OP_MOVE_OBJECT: /* 0x07 */ 523/* File: armv5te/OP_MOVE_OBJECT.S */ 524/* File: armv5te/OP_MOVE.S */ 525 /* for move, move-object, long-to-int */ 526 /* op vA, vB */ 527 mov r1, rINST, lsr #12 @ r1<- B from 15:12 528 mov r0, rINST, lsr #8 @ r0<- A from 11:8 529 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 530 GET_VREG(r2, r1) @ r2<- fp[B] 531 and r0, r0, #15 532 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 533 SET_VREG(r2, r0) @ fp[A]<- r2 534 GOTO_OPCODE(ip) @ execute next instruction 535 536 537 538/* ------------------------------ */ 539 .balign 64 540.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 541/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */ 542/* File: armv5te/OP_MOVE_FROM16.S */ 543 /* for: move/from16, move-object/from16 */ 544 /* op vAA, vBBBB */ 545 FETCH(r1, 1) @ r1<- BBBB 546 mov r0, rINST, lsr #8 @ r0<- AA 547 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 548 GET_VREG(r2, r1) @ r2<- fp[BBBB] 549 GET_INST_OPCODE(ip) @ extract opcode from rINST 550 SET_VREG(r2, r0) @ fp[AA]<- r2 551 GOTO_OPCODE(ip) @ jump to next instruction 552 553 554 555/* ------------------------------ */ 556 .balign 64 557.L_OP_MOVE_OBJECT_16: /* 0x09 */ 558/* File: armv5te/OP_MOVE_OBJECT_16.S */ 559/* File: armv5te/OP_MOVE_16.S */ 560 /* for: move/16, move-object/16 */ 561 /* op vAAAA, vBBBB */ 562 FETCH(r1, 2) @ r1<- BBBB 563 FETCH(r0, 1) @ r0<- AAAA 564 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 565 GET_VREG(r2, r1) @ r2<- fp[BBBB] 566 GET_INST_OPCODE(ip) @ extract opcode from rINST 567 SET_VREG(r2, r0) @ fp[AAAA]<- r2 568 GOTO_OPCODE(ip) @ jump to next instruction 569 570 571 572/* ------------------------------ */ 573 .balign 64 574.L_OP_MOVE_RESULT: /* 0x0a */ 575/* File: armv5te/OP_MOVE_RESULT.S */ 576 /* for: move-result, move-result-object */ 577 /* op vAA */ 578 mov r2, rINST, lsr #8 @ r2<- AA 579 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 580 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 581 GET_INST_OPCODE(ip) @ extract opcode from rINST 582 SET_VREG(r0, r2) @ fp[AA]<- r0 583 GOTO_OPCODE(ip) @ jump to next instruction 584 585 586/* ------------------------------ */ 587 .balign 64 588.L_OP_MOVE_RESULT_WIDE: /* 0x0b */ 589/* File: armv5te/OP_MOVE_RESULT_WIDE.S */ 590 /* move-result-wide vAA */ 591 mov r2, rINST, lsr #8 @ r2<- AA 592 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 593 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 594 ldmia r3, {r0-r1} @ r0/r1<- retval.j 595 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 596 GET_INST_OPCODE(ip) @ extract opcode from rINST 597 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 598 GOTO_OPCODE(ip) @ jump to next instruction 599 600 601/* ------------------------------ */ 602 .balign 64 603.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 604/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */ 605/* File: armv5te/OP_MOVE_RESULT.S */ 606 /* for: move-result, move-result-object */ 607 /* op vAA */ 608 mov r2, rINST, lsr #8 @ r2<- AA 609 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 610 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 611 GET_INST_OPCODE(ip) @ extract opcode from rINST 612 SET_VREG(r0, r2) @ fp[AA]<- r0 613 GOTO_OPCODE(ip) @ jump to next instruction 614 615 616 617/* ------------------------------ */ 618 .balign 64 619.L_OP_MOVE_EXCEPTION: /* 0x0d */ 620/* File: armv5te/OP_MOVE_EXCEPTION.S */ 621 /* move-exception vAA */ 622 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 623 mov r2, rINST, lsr #8 @ r2<- AA 624 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass 625 mov r1, #0 @ r1<- 0 626 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 627 SET_VREG(r3, r2) @ fp[AA]<- exception obj 628 GET_INST_OPCODE(ip) @ extract opcode from rINST 629 str r1, [r0, #offThread_exception] @ dvmClearException bypass 630 GOTO_OPCODE(ip) @ jump to next instruction 631 632 633/* ------------------------------ */ 634 .balign 64 635.L_OP_RETURN_VOID: /* 0x0e */ 636/* File: armv5te/OP_RETURN_VOID.S */ 637 b common_returnFromMethod 638 639 640/* ------------------------------ */ 641 .balign 64 642.L_OP_RETURN: /* 0x0f */ 643/* File: armv5te/OP_RETURN.S */ 644 /* 645 * Return a 32-bit value. Copies the return value into the "glue" 646 * structure, then jumps to the return handler. 647 * 648 * for: return, return-object 649 */ 650 /* op vAA */ 651 mov r2, rINST, lsr #8 @ r2<- AA 652 GET_VREG(r0, r2) @ r0<- vAA 653 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 654 b common_returnFromMethod 655 656 657/* ------------------------------ */ 658 .balign 64 659.L_OP_RETURN_WIDE: /* 0x10 */ 660/* File: armv5te/OP_RETURN_WIDE.S */ 661 /* 662 * Return a 64-bit value. Copies the return value into the "glue" 663 * structure, then jumps to the return handler. 664 */ 665 /* return-wide vAA */ 666 mov r2, rINST, lsr #8 @ r2<- AA 667 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 668 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 669 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1 670 stmia r3, {r0-r1} @ retval<- r0/r1 671 b common_returnFromMethod 672 673 674/* ------------------------------ */ 675 .balign 64 676.L_OP_RETURN_OBJECT: /* 0x11 */ 677/* File: armv5te/OP_RETURN_OBJECT.S */ 678/* File: armv5te/OP_RETURN.S */ 679 /* 680 * Return a 32-bit value. Copies the return value into the "glue" 681 * structure, then jumps to the return handler. 682 * 683 * for: return, return-object 684 */ 685 /* op vAA */ 686 mov r2, rINST, lsr #8 @ r2<- AA 687 GET_VREG(r0, r2) @ r0<- vAA 688 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 689 b common_returnFromMethod 690 691 692 693/* ------------------------------ */ 694 .balign 64 695.L_OP_CONST_4: /* 0x12 */ 696/* File: armv6t2/OP_CONST_4.S */ 697 /* const/4 vA, #+B */ 698 mov r1, rINST, lsl #16 @ r1<- Bxxx0000 699 ubfx r0, rINST, #8, #4 @ r0<- A 700 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 701 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended) 702 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 703 SET_VREG(r1, r0) @ fp[A]<- r1 704 GOTO_OPCODE(ip) @ execute next instruction 705 706 707/* ------------------------------ */ 708 .balign 64 709.L_OP_CONST_16: /* 0x13 */ 710/* File: armv5te/OP_CONST_16.S */ 711 /* const/16 vAA, #+BBBB */ 712 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 713 mov r3, rINST, lsr #8 @ r3<- AA 714 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 715 SET_VREG(r0, r3) @ vAA<- r0 716 GET_INST_OPCODE(ip) @ extract opcode from rINST 717 GOTO_OPCODE(ip) @ jump to next instruction 718 719 720/* ------------------------------ */ 721 .balign 64 722.L_OP_CONST: /* 0x14 */ 723/* File: armv5te/OP_CONST.S */ 724 /* const vAA, #+BBBBbbbb */ 725 mov r3, rINST, lsr #8 @ r3<- AA 726 FETCH(r0, 1) @ r0<- bbbb (low) 727 FETCH(r1, 2) @ r1<- BBBB (high) 728 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 729 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 730 GET_INST_OPCODE(ip) @ extract opcode from rINST 731 SET_VREG(r0, r3) @ vAA<- r0 732 GOTO_OPCODE(ip) @ jump to next instruction 733 734 735/* ------------------------------ */ 736 .balign 64 737.L_OP_CONST_HIGH16: /* 0x15 */ 738/* File: armv5te/OP_CONST_HIGH16.S */ 739 /* const/high16 vAA, #+BBBB0000 */ 740 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended) 741 mov r3, rINST, lsr #8 @ r3<- AA 742 mov r0, r0, lsl #16 @ r0<- BBBB0000 743 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 744 SET_VREG(r0, r3) @ vAA<- r0 745 GET_INST_OPCODE(ip) @ extract opcode from rINST 746 GOTO_OPCODE(ip) @ jump to next instruction 747 748 749/* ------------------------------ */ 750 .balign 64 751.L_OP_CONST_WIDE_16: /* 0x16 */ 752/* File: armv5te/OP_CONST_WIDE_16.S */ 753 /* const-wide/16 vAA, #+BBBB */ 754 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 755 mov r3, rINST, lsr #8 @ r3<- AA 756 mov r1, r0, asr #31 @ r1<- ssssssss 757 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 758 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 759 GET_INST_OPCODE(ip) @ extract opcode from rINST 760 stmia r3, {r0-r1} @ vAA<- r0/r1 761 GOTO_OPCODE(ip) @ jump to next instruction 762 763 764/* ------------------------------ */ 765 .balign 64 766.L_OP_CONST_WIDE_32: /* 0x17 */ 767/* File: armv5te/OP_CONST_WIDE_32.S */ 768 /* const-wide/32 vAA, #+BBBBbbbb */ 769 FETCH(r0, 1) @ r0<- 0000bbbb (low) 770 mov r3, rINST, lsr #8 @ r3<- AA 771 FETCH_S(r2, 2) @ r2<- ssssBBBB (high) 772 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 773 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb 774 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 775 mov r1, r0, asr #31 @ r1<- ssssssss 776 GET_INST_OPCODE(ip) @ extract opcode from rINST 777 stmia r3, {r0-r1} @ vAA<- r0/r1 778 GOTO_OPCODE(ip) @ jump to next instruction 779 780 781/* ------------------------------ */ 782 .balign 64 783.L_OP_CONST_WIDE: /* 0x18 */ 784/* File: armv5te/OP_CONST_WIDE.S */ 785 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 786 FETCH(r0, 1) @ r0<- bbbb (low) 787 FETCH(r1, 2) @ r1<- BBBB (low middle) 788 FETCH(r2, 3) @ r2<- hhhh (high middle) 789 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word) 790 FETCH(r3, 4) @ r3<- HHHH (high) 791 mov r9, rINST, lsr #8 @ r9<- AA 792 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word) 793 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 794 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 795 GET_INST_OPCODE(ip) @ extract opcode from rINST 796 stmia r9, {r0-r1} @ vAA<- r0/r1 797 GOTO_OPCODE(ip) @ jump to next instruction 798 799 800/* ------------------------------ */ 801 .balign 64 802.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 803/* File: armv5te/OP_CONST_WIDE_HIGH16.S */ 804 /* const-wide/high16 vAA, #+BBBB000000000000 */ 805 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended) 806 mov r3, rINST, lsr #8 @ r3<- AA 807 mov r0, #0 @ r0<- 00000000 808 mov r1, r1, lsl #16 @ r1<- BBBB0000 809 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 810 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 811 GET_INST_OPCODE(ip) @ extract opcode from rINST 812 stmia r3, {r0-r1} @ vAA<- r0/r1 813 GOTO_OPCODE(ip) @ jump to next instruction 814 815 816/* ------------------------------ */ 817 .balign 64 818.L_OP_CONST_STRING: /* 0x1a */ 819/* File: armv5te/OP_CONST_STRING.S */ 820 /* const/string vAA, String@BBBB */ 821 FETCH(r1, 1) @ r1<- BBBB 822 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 823 mov r9, rINST, lsr #8 @ r9<- AA 824 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 825 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 826 cmp r0, #0 @ not yet resolved? 827 beq .LOP_CONST_STRING_resolve 828 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 829 GET_INST_OPCODE(ip) @ extract opcode from rINST 830 SET_VREG(r0, r9) @ vAA<- r0 831 GOTO_OPCODE(ip) @ jump to next instruction 832 833/* ------------------------------ */ 834 .balign 64 835.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 836/* File: armv5te/OP_CONST_STRING_JUMBO.S */ 837 /* const/string vAA, String@BBBBBBBB */ 838 FETCH(r0, 1) @ r0<- bbbb (low) 839 FETCH(r1, 2) @ r1<- BBBB (high) 840 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 841 mov r9, rINST, lsr #8 @ r9<- AA 842 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 843 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 844 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 845 cmp r0, #0 846 beq .LOP_CONST_STRING_JUMBO_resolve 847 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 848 GET_INST_OPCODE(ip) @ extract opcode from rINST 849 SET_VREG(r0, r9) @ vAA<- r0 850 GOTO_OPCODE(ip) @ jump to next instruction 851 852/* ------------------------------ */ 853 .balign 64 854.L_OP_CONST_CLASS: /* 0x1c */ 855/* File: armv5te/OP_CONST_CLASS.S */ 856 /* const/class vAA, Class@BBBB */ 857 FETCH(r1, 1) @ r1<- BBBB 858 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 859 mov r9, rINST, lsr #8 @ r9<- AA 860 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 861 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB] 862 cmp r0, #0 @ not yet resolved? 863 beq .LOP_CONST_CLASS_resolve 864 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 865 GET_INST_OPCODE(ip) @ extract opcode from rINST 866 SET_VREG(r0, r9) @ vAA<- r0 867 GOTO_OPCODE(ip) @ jump to next instruction 868 869/* ------------------------------ */ 870 .balign 64 871.L_OP_MONITOR_ENTER: /* 0x1d */ 872/* File: armv5te/OP_MONITOR_ENTER.S */ 873 /* 874 * Synchronize on an object. 875 */ 876 /* monitor-enter vAA */ 877 mov r2, rINST, lsr #8 @ r2<- AA 878 GET_VREG(r1, r2) @ r1<- vAA (object) 879 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 880 cmp r1, #0 @ null object? 881 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING 882 beq common_errNullObject @ null object, throw an exception 883 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 884 bl dvmLockObject @ call(self, obj) 885#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ 886 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 887 ldr r1, [r0, #offThread_exception] @ check for exception 888 cmp r1, #0 889 bne common_exceptionThrown @ exception raised, bail out 890#endif 891 GET_INST_OPCODE(ip) @ extract opcode from rINST 892 GOTO_OPCODE(ip) @ jump to next instruction 893 894 895/* ------------------------------ */ 896 .balign 64 897.L_OP_MONITOR_EXIT: /* 0x1e */ 898/* File: armv5te/OP_MONITOR_EXIT.S */ 899 /* 900 * Unlock an object. 901 * 902 * Exceptions that occur when unlocking a monitor need to appear as 903 * if they happened at the following instruction. See the Dalvik 904 * instruction spec. 905 */ 906 /* monitor-exit vAA */ 907 mov r2, rINST, lsr #8 @ r2<- AA 908 EXPORT_PC() @ before fetch: export the PC 909 GET_VREG(r1, r2) @ r1<- vAA (object) 910 cmp r1, #0 @ null object? 911 beq 1f @ yes 912 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 913 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 914 cmp r0, #0 @ failed? 915 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 916 beq common_exceptionThrown @ yes, exception is pending 917 GET_INST_OPCODE(ip) @ extract opcode from rINST 918 GOTO_OPCODE(ip) @ jump to next instruction 9191: 920 FETCH_ADVANCE_INST(1) @ advance before throw 921 b common_errNullObject 922 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/* ------------------------------ */ 1000 .balign 64 1001.L_OP_NEW_INSTANCE: /* 0x22 */ 1002/* File: armv5te/OP_NEW_INSTANCE.S */ 1003 /* 1004 * Create a new instance of a class. 1005 */ 1006 /* new-instance vAA, class@BBBB */ 1007 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1008 FETCH(r1, 1) @ r1<- BBBB 1009 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1010 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1011 EXPORT_PC() @ req'd for init, resolve, alloc 1012 cmp r0, #0 @ already resolved? 1013 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 1014.LOP_NEW_INSTANCE_resolved: @ r0=class 1015 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 1016 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 1017 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 1018.LOP_NEW_INSTANCE_initialized: @ r0=class 1019 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 1020 bl dvmAllocObject @ r0<- new object 1021 b .LOP_NEW_INSTANCE_finish @ continue 1022 1023/* ------------------------------ */ 1024 .balign 64 1025.L_OP_NEW_ARRAY: /* 0x23 */ 1026/* File: armv5te/OP_NEW_ARRAY.S */ 1027 /* 1028 * Allocate an array of objects, specified with the array class 1029 * and a count. 1030 * 1031 * The verifier guarantees that this is an array class, so we don't 1032 * check for it here. 1033 */ 1034 /* new-array vA, vB, class@CCCC */ 1035 mov r0, rINST, lsr #12 @ r0<- B 1036 FETCH(r2, 1) @ r2<- CCCC 1037 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1038 GET_VREG(r1, r0) @ r1<- vB (array length) 1039 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1040 cmp r1, #0 @ check length 1041 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 1042 bmi common_errNegativeArraySize @ negative length, bail 1043 cmp r0, #0 @ already resolved? 1044 EXPORT_PC() @ req'd for resolve, alloc 1045 bne .LOP_NEW_ARRAY_finish @ resolved, continue 1046 b .LOP_NEW_ARRAY_resolve @ do resolve now 1047 1048/* ------------------------------ */ 1049 .balign 64 1050.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1051/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1052 /* 1053 * Create a new array with elements filled from registers. 1054 * 1055 * for: filled-new-array, filled-new-array/range 1056 */ 1057 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1058 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1059 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1060 FETCH(r1, 1) @ r1<- BBBB 1061 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1062 EXPORT_PC() @ need for resolve and alloc 1063 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1064 mov r10, rINST, lsr #8 @ r10<- AA or BA 1065 cmp r0, #0 @ already resolved? 1066 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10678: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1068 mov r2, #0 @ r2<- false 1069 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1070 bl dvmResolveClass @ r0<- call(clazz, ref) 1071 cmp r0, #0 @ got null? 1072 beq common_exceptionThrown @ yes, handle exception 1073 b .LOP_FILLED_NEW_ARRAY_continue 1074 1075/* ------------------------------ */ 1076 .balign 64 1077.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1078/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1079/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1080 /* 1081 * Create a new array with elements filled from registers. 1082 * 1083 * for: filled-new-array, filled-new-array/range 1084 */ 1085 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1086 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1087 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1088 FETCH(r1, 1) @ r1<- BBBB 1089 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1090 EXPORT_PC() @ need for resolve and alloc 1091 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1092 mov r10, rINST, lsr #8 @ r10<- AA or BA 1093 cmp r0, #0 @ already resolved? 1094 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10958: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1096 mov r2, #0 @ r2<- false 1097 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1098 bl dvmResolveClass @ r0<- call(clazz, ref) 1099 cmp r0, #0 @ got null? 1100 beq common_exceptionThrown @ yes, handle exception 1101 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1102 1103 1104/* ------------------------------ */ 1105 .balign 64 1106.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1107/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1108 /* fill-array-data vAA, +BBBBBBBB */ 1109 FETCH(r0, 1) @ r0<- bbbb (lo) 1110 FETCH(r1, 2) @ r1<- BBBB (hi) 1111 mov r3, rINST, lsr #8 @ r3<- AA 1112 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1113 GET_VREG(r0, r3) @ r0<- vAA (array object) 1114 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1115 EXPORT_PC(); 1116 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1117 cmp r0, #0 @ 0 means an exception is thrown 1118 beq common_exceptionThrown @ has exception 1119 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1120 GET_INST_OPCODE(ip) @ extract opcode from rINST 1121 GOTO_OPCODE(ip) @ jump to next instruction 1122 1123/* ------------------------------ */ 1124 .balign 64 1125.L_OP_THROW: /* 0x27 */ 1126/* File: armv5te/OP_THROW.S */ 1127 /* 1128 * Throw an exception object in the current thread. 1129 */ 1130 /* throw vAA */ 1131 mov r2, rINST, lsr #8 @ r2<- AA 1132 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1133 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 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/* ------------------------------ */ 1142 .balign 64 1143.L_OP_GOTO: /* 0x28 */ 1144/* File: armv5te/OP_GOTO.S */ 1145 /* 1146 * Unconditional branch, 8-bit offset. 1147 * 1148 * The branch distance is a signed code-unit offset, which we need to 1149 * double to get a byte offset. 1150 */ 1151 /* goto +AA */ 1152 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1153 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1154 mov r9, r9, lsl #1 @ r9<- byte offset 1155 bmi common_backwardBranch @ backward branch, do periodic checks 1156#if defined(WITH_JIT) 1157 GET_JIT_PROF_TABLE(r0) 1158 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1159 cmp r0,#0 1160 bne common_updateProfile 1161 GET_INST_OPCODE(ip) @ extract opcode from rINST 1162 GOTO_OPCODE(ip) @ jump to next instruction 1163#else 1164 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1165 GET_INST_OPCODE(ip) @ extract opcode from rINST 1166 GOTO_OPCODE(ip) @ jump to next instruction 1167#endif 1168 1169/* ------------------------------ */ 1170 .balign 64 1171.L_OP_GOTO_16: /* 0x29 */ 1172/* File: armv5te/OP_GOTO_16.S */ 1173 /* 1174 * Unconditional branch, 16-bit offset. 1175 * 1176 * The branch distance is a signed code-unit offset, which we need to 1177 * double to get a byte offset. 1178 */ 1179 /* goto/16 +AAAA */ 1180 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1181 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1182 bmi common_backwardBranch @ backward branch, do periodic checks 1183#if defined(WITH_JIT) 1184 GET_JIT_PROF_TABLE(r0) 1185 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1186 cmp r0,#0 1187 bne common_updateProfile 1188 GET_INST_OPCODE(ip) @ extract opcode from rINST 1189 GOTO_OPCODE(ip) @ jump to next instruction 1190#else 1191 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1192 GET_INST_OPCODE(ip) @ extract opcode from rINST 1193 GOTO_OPCODE(ip) @ jump to next instruction 1194#endif 1195 1196 1197/* ------------------------------ */ 1198 .balign 64 1199.L_OP_GOTO_32: /* 0x2a */ 1200/* File: armv5te/OP_GOTO_32.S */ 1201 /* 1202 * Unconditional branch, 32-bit offset. 1203 * 1204 * The branch distance is a signed code-unit offset, which we need to 1205 * double to get a byte offset. 1206 * 1207 * Unlike most opcodes, this one is allowed to branch to itself, so 1208 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1209 * instruction doesn't affect the V flag, so we need to clear it 1210 * explicitly. 1211 */ 1212 /* goto/32 +AAAAAAAA */ 1213 FETCH(r0, 1) @ r0<- aaaa (lo) 1214 FETCH(r1, 2) @ r1<- AAAA (hi) 1215 cmp ip, ip @ (clear V flag during stall) 1216 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1217 mov r9, r0, asl #1 @ r9<- byte offset 1218 ble common_backwardBranch @ backward branch, do periodic checks 1219#if defined(WITH_JIT) 1220 GET_JIT_PROF_TABLE(r0) 1221 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1222 cmp r0,#0 1223 bne common_updateProfile 1224 GET_INST_OPCODE(ip) @ extract opcode from rINST 1225 GOTO_OPCODE(ip) @ jump to next instruction 1226#else 1227 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1228 GET_INST_OPCODE(ip) @ extract opcode from rINST 1229 GOTO_OPCODE(ip) @ jump to next instruction 1230#endif 1231 1232/* ------------------------------ */ 1233 .balign 64 1234.L_OP_PACKED_SWITCH: /* 0x2b */ 1235/* File: armv5te/OP_PACKED_SWITCH.S */ 1236 /* 1237 * Handle a packed-switch or sparse-switch instruction. In both cases 1238 * we decode it and hand it off to a helper function. 1239 * 1240 * We don't really expect backward branches in a switch statement, but 1241 * they're perfectly legal, so we check for them here. 1242 * 1243 * for: packed-switch, sparse-switch 1244 */ 1245 /* op vAA, +BBBB */ 1246 FETCH(r0, 1) @ r0<- bbbb (lo) 1247 FETCH(r1, 2) @ r1<- BBBB (hi) 1248 mov r3, rINST, lsr #8 @ r3<- AA 1249 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1250 GET_VREG(r1, r3) @ r1<- vAA 1251 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1252 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1253 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1254 bmi common_backwardBranch @ backward branch, do periodic checks 1255 beq common_backwardBranch @ (want to use BLE but V is unknown) 1256#if defined(WITH_JIT) 1257 GET_JIT_PROF_TABLE(r0) 1258 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1259 cmp r0,#0 1260 bne common_updateProfile 1261 GET_INST_OPCODE(ip) @ extract opcode from rINST 1262 GOTO_OPCODE(ip) @ jump to next instruction 1263#else 1264 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1265 GET_INST_OPCODE(ip) @ extract opcode from rINST 1266 GOTO_OPCODE(ip) @ jump to next instruction 1267#endif 1268 1269 1270/* ------------------------------ */ 1271 .balign 64 1272.L_OP_SPARSE_SWITCH: /* 0x2c */ 1273/* File: armv5te/OP_SPARSE_SWITCH.S */ 1274/* File: armv5te/OP_PACKED_SWITCH.S */ 1275 /* 1276 * Handle a packed-switch or sparse-switch instruction. In both cases 1277 * we decode it and hand it off to a helper function. 1278 * 1279 * We don't really expect backward branches in a switch statement, but 1280 * they're perfectly legal, so we check for them here. 1281 * 1282 * for: packed-switch, sparse-switch 1283 */ 1284 /* op vAA, +BBBB */ 1285 FETCH(r0, 1) @ r0<- bbbb (lo) 1286 FETCH(r1, 2) @ r1<- BBBB (hi) 1287 mov r3, rINST, lsr #8 @ r3<- AA 1288 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1289 GET_VREG(r1, r3) @ r1<- vAA 1290 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1291 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1292 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1293 bmi common_backwardBranch @ backward branch, do periodic checks 1294 beq common_backwardBranch @ (want to use BLE but V is unknown) 1295#if defined(WITH_JIT) 1296 GET_JIT_PROF_TABLE(r0) 1297 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1298 cmp r0,#0 1299 bne common_updateProfile 1300 GET_INST_OPCODE(ip) @ extract opcode from rINST 1301 GOTO_OPCODE(ip) @ jump to next instruction 1302#else 1303 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1304 GET_INST_OPCODE(ip) @ extract opcode from rINST 1305 GOTO_OPCODE(ip) @ jump to next instruction 1306#endif 1307 1308 1309 1310/* ------------------------------ */ 1311 .balign 64 1312.L_OP_CMPL_FLOAT: /* 0x2d */ 1313/* File: arm-vfp/OP_CMPL_FLOAT.S */ 1314 /* 1315 * Compare two floating-point values. Puts 0, 1, or -1 into the 1316 * destination register based on the results of the comparison. 1317 * 1318 * int compare(x, y) { 1319 * if (x == y) { 1320 * return 0; 1321 * } else if (x > y) { 1322 * return 1; 1323 * } else if (x < y) { 1324 * return -1; 1325 * } else { 1326 * return -1; 1327 * } 1328 * } 1329 */ 1330 /* op vAA, vBB, vCC */ 1331 FETCH(r0, 1) @ r0<- CCBB 1332 mov r9, rINST, lsr #8 @ r9<- AA 1333 and r2, r0, #255 @ r2<- BB 1334 mov r3, r0, lsr #8 @ r3<- CC 1335 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1336 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1337 flds s0, [r2] @ s0<- vBB 1338 flds s1, [r3] @ s1<- vCC 1339 fcmpes s0, s1 @ compare (vBB, vCC) 1340 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1341 mvn r0, #0 @ r0<- -1 (default) 1342 GET_INST_OPCODE(ip) @ extract opcode from rINST 1343 fmstat @ export status flags 1344 movgt r0, #1 @ (greater than) r1<- 1 1345 moveq r0, #0 @ (equal) r1<- 0 1346 b .LOP_CMPL_FLOAT_finish @ argh 1347 1348 1349/* ------------------------------ */ 1350 .balign 64 1351.L_OP_CMPG_FLOAT: /* 0x2e */ 1352/* File: arm-vfp/OP_CMPG_FLOAT.S */ 1353 /* 1354 * Compare two floating-point values. Puts 0, 1, or -1 into the 1355 * destination register based on the results of the comparison. 1356 * 1357 * int compare(x, y) { 1358 * if (x == y) { 1359 * return 0; 1360 * } else if (x < y) { 1361 * return -1; 1362 * } else if (x > y) { 1363 * return 1; 1364 * } else { 1365 * return 1; 1366 * } 1367 * } 1368 */ 1369 /* op vAA, vBB, vCC */ 1370 FETCH(r0, 1) @ r0<- CCBB 1371 mov r9, rINST, lsr #8 @ r9<- AA 1372 and r2, r0, #255 @ r2<- BB 1373 mov r3, r0, lsr #8 @ r3<- CC 1374 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1375 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1376 flds s0, [r2] @ s0<- vBB 1377 flds s1, [r3] @ s1<- vCC 1378 fcmpes s0, s1 @ compare (vBB, vCC) 1379 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1380 mov r0, #1 @ r0<- 1 (default) 1381 GET_INST_OPCODE(ip) @ extract opcode from rINST 1382 fmstat @ export status flags 1383 mvnmi r0, #0 @ (less than) r1<- -1 1384 moveq r0, #0 @ (equal) r1<- 0 1385 b .LOP_CMPG_FLOAT_finish @ argh 1386 1387 1388/* ------------------------------ */ 1389 .balign 64 1390.L_OP_CMPL_DOUBLE: /* 0x2f */ 1391/* File: arm-vfp/OP_CMPL_DOUBLE.S */ 1392 /* 1393 * Compare two floating-point values. Puts 0, 1, or -1 into the 1394 * destination register based on the results of the comparison. 1395 * 1396 * int compare(x, y) { 1397 * if (x == y) { 1398 * return 0; 1399 * } else if (x > y) { 1400 * return 1; 1401 * } else if (x < y) { 1402 * return -1; 1403 * } else { 1404 * return -1; 1405 * } 1406 * } 1407 */ 1408 /* op vAA, vBB, vCC */ 1409 FETCH(r0, 1) @ r0<- CCBB 1410 mov r9, rINST, lsr #8 @ r9<- AA 1411 and r2, r0, #255 @ r2<- BB 1412 mov r3, r0, lsr #8 @ r3<- CC 1413 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1414 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1415 fldd d0, [r2] @ d0<- vBB 1416 fldd d1, [r3] @ d1<- vCC 1417 fcmped d0, d1 @ compare (vBB, vCC) 1418 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1419 mvn r0, #0 @ r0<- -1 (default) 1420 GET_INST_OPCODE(ip) @ extract opcode from rINST 1421 fmstat @ export status flags 1422 movgt r0, #1 @ (greater than) r1<- 1 1423 moveq r0, #0 @ (equal) r1<- 0 1424 b .LOP_CMPL_DOUBLE_finish @ argh 1425 1426 1427/* ------------------------------ */ 1428 .balign 64 1429.L_OP_CMPG_DOUBLE: /* 0x30 */ 1430/* File: arm-vfp/OP_CMPG_DOUBLE.S */ 1431 /* 1432 * Compare two floating-point values. Puts 0, 1, or -1 into the 1433 * destination register based on the results of the comparison. 1434 * 1435 * int compare(x, y) { 1436 * if (x == y) { 1437 * return 0; 1438 * } else if (x < y) { 1439 * return -1; 1440 * } else if (x > y) { 1441 * return 1; 1442 * } else { 1443 * return 1; 1444 * } 1445 * } 1446 */ 1447 /* op vAA, vBB, vCC */ 1448 FETCH(r0, 1) @ r0<- CCBB 1449 mov r9, rINST, lsr #8 @ r9<- AA 1450 and r2, r0, #255 @ r2<- BB 1451 mov r3, r0, lsr #8 @ r3<- CC 1452 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1453 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1454 fldd d0, [r2] @ d0<- vBB 1455 fldd d1, [r3] @ d1<- vCC 1456 fcmped d0, d1 @ compare (vBB, vCC) 1457 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1458 mov r0, #1 @ r0<- 1 (default) 1459 GET_INST_OPCODE(ip) @ extract opcode from rINST 1460 fmstat @ export status flags 1461 mvnmi r0, #0 @ (less than) r1<- -1 1462 moveq r0, #0 @ (equal) r1<- 0 1463 b .LOP_CMPG_DOUBLE_finish @ argh 1464 1465 1466/* ------------------------------ */ 1467 .balign 64 1468.L_OP_CMP_LONG: /* 0x31 */ 1469/* File: armv5te/OP_CMP_LONG.S */ 1470 /* 1471 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1472 * register based on the results of the comparison. 1473 * 1474 * We load the full values with LDM, but in practice many values could 1475 * be resolved by only looking at the high word. This could be made 1476 * faster or slower by splitting the LDM into a pair of LDRs. 1477 * 1478 * If we just wanted to set condition flags, we could do this: 1479 * subs ip, r0, r2 1480 * sbcs ip, r1, r3 1481 * subeqs ip, r0, r2 1482 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1483 * integer value, which we can do with 2 conditional mov/mvn instructions 1484 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1485 * us a constant 5-cycle path plus a branch at the end to the 1486 * instruction epilogue code. The multi-compare approach below needs 1487 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1488 * in the worst case (the 64-bit values are equal). 1489 */ 1490 /* cmp-long vAA, vBB, vCC */ 1491 FETCH(r0, 1) @ r0<- CCBB 1492 mov r9, rINST, lsr #8 @ r9<- AA 1493 and r2, r0, #255 @ r2<- BB 1494 mov r3, r0, lsr #8 @ r3<- CC 1495 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1496 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1497 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1498 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1499 cmp r1, r3 @ compare (vBB+1, vCC+1) 1500 blt .LOP_CMP_LONG_less @ signed compare on high part 1501 bgt .LOP_CMP_LONG_greater 1502 subs r1, r0, r2 @ r1<- r0 - r2 1503 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1504 bne .LOP_CMP_LONG_less 1505 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1506 1507/* ------------------------------ */ 1508 .balign 64 1509.L_OP_IF_EQ: /* 0x32 */ 1510/* File: armv6t2/OP_IF_EQ.S */ 1511/* File: armv6t2/bincmp.S */ 1512 /* 1513 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1514 * fragment that specifies the *reverse* comparison to perform, e.g. 1515 * for "if-le" you would use "gt". 1516 * 1517 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1518 */ 1519 /* if-cmp vA, vB, +CCCC */ 1520 mov r1, rINST, lsr #12 @ r1<- B 1521 ubfx r0, rINST, #8, #4 @ r0<- A 1522 GET_VREG(r3, r1) @ r3<- vB 1523 GET_VREG(r2, r0) @ r2<- vA 1524 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1525 cmp r2, r3 @ compare (vA, vB) 1526 bne 1f @ branch to 1 if comparison failed 1527 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1528 movs r9, r9, asl #1 @ convert to bytes, check sign 1529 bmi common_backwardBranch @ yes, do periodic checks 15301: 1531#if defined(WITH_JIT) 1532 GET_JIT_PROF_TABLE(r0) 1533 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1534 b common_testUpdateProfile 1535#else 1536 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1537 GET_INST_OPCODE(ip) @ extract opcode from rINST 1538 GOTO_OPCODE(ip) @ jump to next instruction 1539#endif 1540 1541 1542 1543/* ------------------------------ */ 1544 .balign 64 1545.L_OP_IF_NE: /* 0x33 */ 1546/* File: armv6t2/OP_IF_NE.S */ 1547/* File: armv6t2/bincmp.S */ 1548 /* 1549 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1550 * fragment that specifies the *reverse* comparison to perform, e.g. 1551 * for "if-le" you would use "gt". 1552 * 1553 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1554 */ 1555 /* if-cmp vA, vB, +CCCC */ 1556 mov r1, rINST, lsr #12 @ r1<- B 1557 ubfx r0, rINST, #8, #4 @ r0<- A 1558 GET_VREG(r3, r1) @ r3<- vB 1559 GET_VREG(r2, r0) @ r2<- vA 1560 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1561 cmp r2, r3 @ compare (vA, vB) 1562 beq 1f @ branch to 1 if comparison failed 1563 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1564 movs r9, r9, asl #1 @ convert to bytes, check sign 1565 bmi common_backwardBranch @ yes, do periodic checks 15661: 1567#if defined(WITH_JIT) 1568 GET_JIT_PROF_TABLE(r0) 1569 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1570 b common_testUpdateProfile 1571#else 1572 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1573 GET_INST_OPCODE(ip) @ extract opcode from rINST 1574 GOTO_OPCODE(ip) @ jump to next instruction 1575#endif 1576 1577 1578 1579/* ------------------------------ */ 1580 .balign 64 1581.L_OP_IF_LT: /* 0x34 */ 1582/* File: armv6t2/OP_IF_LT.S */ 1583/* File: armv6t2/bincmp.S */ 1584 /* 1585 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1586 * fragment that specifies the *reverse* comparison to perform, e.g. 1587 * for "if-le" you would use "gt". 1588 * 1589 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1590 */ 1591 /* if-cmp vA, vB, +CCCC */ 1592 mov r1, rINST, lsr #12 @ r1<- B 1593 ubfx r0, rINST, #8, #4 @ r0<- A 1594 GET_VREG(r3, r1) @ r3<- vB 1595 GET_VREG(r2, r0) @ r2<- vA 1596 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1597 cmp r2, r3 @ compare (vA, vB) 1598 bge 1f @ branch to 1 if comparison failed 1599 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1600 movs r9, r9, asl #1 @ convert to bytes, check sign 1601 bmi common_backwardBranch @ yes, do periodic checks 16021: 1603#if defined(WITH_JIT) 1604 GET_JIT_PROF_TABLE(r0) 1605 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1606 b common_testUpdateProfile 1607#else 1608 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1609 GET_INST_OPCODE(ip) @ extract opcode from rINST 1610 GOTO_OPCODE(ip) @ jump to next instruction 1611#endif 1612 1613 1614 1615/* ------------------------------ */ 1616 .balign 64 1617.L_OP_IF_GE: /* 0x35 */ 1618/* File: armv6t2/OP_IF_GE.S */ 1619/* File: armv6t2/bincmp.S */ 1620 /* 1621 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1622 * fragment that specifies the *reverse* comparison to perform, e.g. 1623 * for "if-le" you would use "gt". 1624 * 1625 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1626 */ 1627 /* if-cmp vA, vB, +CCCC */ 1628 mov r1, rINST, lsr #12 @ r1<- B 1629 ubfx r0, rINST, #8, #4 @ r0<- A 1630 GET_VREG(r3, r1) @ r3<- vB 1631 GET_VREG(r2, r0) @ r2<- vA 1632 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1633 cmp r2, r3 @ compare (vA, vB) 1634 blt 1f @ branch to 1 if comparison failed 1635 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1636 movs r9, r9, asl #1 @ convert to bytes, check sign 1637 bmi common_backwardBranch @ yes, do periodic checks 16381: 1639#if defined(WITH_JIT) 1640 GET_JIT_PROF_TABLE(r0) 1641 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1642 b common_testUpdateProfile 1643#else 1644 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1645 GET_INST_OPCODE(ip) @ extract opcode from rINST 1646 GOTO_OPCODE(ip) @ jump to next instruction 1647#endif 1648 1649 1650 1651/* ------------------------------ */ 1652 .balign 64 1653.L_OP_IF_GT: /* 0x36 */ 1654/* File: armv6t2/OP_IF_GT.S */ 1655/* File: armv6t2/bincmp.S */ 1656 /* 1657 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1658 * fragment that specifies the *reverse* comparison to perform, e.g. 1659 * for "if-le" you would use "gt". 1660 * 1661 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1662 */ 1663 /* if-cmp vA, vB, +CCCC */ 1664 mov r1, rINST, lsr #12 @ r1<- B 1665 ubfx r0, rINST, #8, #4 @ r0<- A 1666 GET_VREG(r3, r1) @ r3<- vB 1667 GET_VREG(r2, r0) @ r2<- vA 1668 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1669 cmp r2, r3 @ compare (vA, vB) 1670 ble 1f @ branch to 1 if comparison failed 1671 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1672 movs r9, r9, asl #1 @ convert to bytes, check sign 1673 bmi common_backwardBranch @ yes, do periodic checks 16741: 1675#if defined(WITH_JIT) 1676 GET_JIT_PROF_TABLE(r0) 1677 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1678 b common_testUpdateProfile 1679#else 1680 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1681 GET_INST_OPCODE(ip) @ extract opcode from rINST 1682 GOTO_OPCODE(ip) @ jump to next instruction 1683#endif 1684 1685 1686 1687/* ------------------------------ */ 1688 .balign 64 1689.L_OP_IF_LE: /* 0x37 */ 1690/* File: armv6t2/OP_IF_LE.S */ 1691/* File: armv6t2/bincmp.S */ 1692 /* 1693 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1694 * fragment that specifies the *reverse* comparison to perform, e.g. 1695 * for "if-le" you would use "gt". 1696 * 1697 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1698 */ 1699 /* if-cmp vA, vB, +CCCC */ 1700 mov r1, rINST, lsr #12 @ r1<- B 1701 ubfx r0, rINST, #8, #4 @ r0<- A 1702 GET_VREG(r3, r1) @ r3<- vB 1703 GET_VREG(r2, r0) @ r2<- vA 1704 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1705 cmp r2, r3 @ compare (vA, vB) 1706 bgt 1f @ branch to 1 if comparison failed 1707 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1708 movs r9, r9, asl #1 @ convert to bytes, check sign 1709 bmi common_backwardBranch @ yes, do periodic checks 17101: 1711#if defined(WITH_JIT) 1712 GET_JIT_PROF_TABLE(r0) 1713 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1714 b common_testUpdateProfile 1715#else 1716 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1717 GET_INST_OPCODE(ip) @ extract opcode from rINST 1718 GOTO_OPCODE(ip) @ jump to next instruction 1719#endif 1720 1721 1722 1723/* ------------------------------ */ 1724 .balign 64 1725.L_OP_IF_EQZ: /* 0x38 */ 1726/* File: armv5te/OP_IF_EQZ.S */ 1727/* File: armv5te/zcmp.S */ 1728 /* 1729 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1730 * fragment that specifies the *reverse* comparison to perform, e.g. 1731 * for "if-le" you would use "gt". 1732 * 1733 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1734 */ 1735 /* if-cmp vAA, +BBBB */ 1736 mov r0, rINST, lsr #8 @ r0<- AA 1737 GET_VREG(r2, r0) @ r2<- vAA 1738 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1739 cmp r2, #0 @ compare (vA, 0) 1740 bne 1f @ branch to 1 if comparison failed 1741 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1742 movs r9, r9, asl #1 @ convert to bytes, check sign 1743 bmi common_backwardBranch @ backward branch, do periodic checks 17441: 1745#if defined(WITH_JIT) 1746 GET_JIT_PROF_TABLE(r0) 1747 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1748 cmp r0,#0 1749 bne common_updateProfile 1750 GET_INST_OPCODE(ip) @ extract opcode from rINST 1751 GOTO_OPCODE(ip) @ jump to next instruction 1752#else 1753 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1754 GET_INST_OPCODE(ip) @ extract opcode from rINST 1755 GOTO_OPCODE(ip) @ jump to next instruction 1756#endif 1757 1758 1759 1760/* ------------------------------ */ 1761 .balign 64 1762.L_OP_IF_NEZ: /* 0x39 */ 1763/* File: armv5te/OP_IF_NEZ.S */ 1764/* File: armv5te/zcmp.S */ 1765 /* 1766 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1767 * fragment that specifies the *reverse* comparison to perform, e.g. 1768 * for "if-le" you would use "gt". 1769 * 1770 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1771 */ 1772 /* if-cmp vAA, +BBBB */ 1773 mov r0, rINST, lsr #8 @ r0<- AA 1774 GET_VREG(r2, r0) @ r2<- vAA 1775 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1776 cmp r2, #0 @ compare (vA, 0) 1777 beq 1f @ branch to 1 if comparison failed 1778 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1779 movs r9, r9, asl #1 @ convert to bytes, check sign 1780 bmi common_backwardBranch @ backward branch, do periodic checks 17811: 1782#if defined(WITH_JIT) 1783 GET_JIT_PROF_TABLE(r0) 1784 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1785 cmp r0,#0 1786 bne common_updateProfile 1787 GET_INST_OPCODE(ip) @ extract opcode from rINST 1788 GOTO_OPCODE(ip) @ jump to next instruction 1789#else 1790 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1791 GET_INST_OPCODE(ip) @ extract opcode from rINST 1792 GOTO_OPCODE(ip) @ jump to next instruction 1793#endif 1794 1795 1796 1797/* ------------------------------ */ 1798 .balign 64 1799.L_OP_IF_LTZ: /* 0x3a */ 1800/* File: armv5te/OP_IF_LTZ.S */ 1801/* File: armv5te/zcmp.S */ 1802 /* 1803 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1804 * fragment that specifies the *reverse* comparison to perform, e.g. 1805 * for "if-le" you would use "gt". 1806 * 1807 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1808 */ 1809 /* if-cmp vAA, +BBBB */ 1810 mov r0, rINST, lsr #8 @ r0<- AA 1811 GET_VREG(r2, r0) @ r2<- vAA 1812 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1813 cmp r2, #0 @ compare (vA, 0) 1814 bge 1f @ branch to 1 if comparison failed 1815 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1816 movs r9, r9, asl #1 @ convert to bytes, check sign 1817 bmi common_backwardBranch @ backward branch, do periodic checks 18181: 1819#if defined(WITH_JIT) 1820 GET_JIT_PROF_TABLE(r0) 1821 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1822 cmp r0,#0 1823 bne common_updateProfile 1824 GET_INST_OPCODE(ip) @ extract opcode from rINST 1825 GOTO_OPCODE(ip) @ jump to next instruction 1826#else 1827 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1828 GET_INST_OPCODE(ip) @ extract opcode from rINST 1829 GOTO_OPCODE(ip) @ jump to next instruction 1830#endif 1831 1832 1833 1834/* ------------------------------ */ 1835 .balign 64 1836.L_OP_IF_GEZ: /* 0x3b */ 1837/* File: armv5te/OP_IF_GEZ.S */ 1838/* File: armv5te/zcmp.S */ 1839 /* 1840 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1841 * fragment that specifies the *reverse* comparison to perform, e.g. 1842 * for "if-le" you would use "gt". 1843 * 1844 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1845 */ 1846 /* if-cmp vAA, +BBBB */ 1847 mov r0, rINST, lsr #8 @ r0<- AA 1848 GET_VREG(r2, r0) @ r2<- vAA 1849 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1850 cmp r2, #0 @ compare (vA, 0) 1851 blt 1f @ branch to 1 if comparison failed 1852 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1853 movs r9, r9, asl #1 @ convert to bytes, check sign 1854 bmi common_backwardBranch @ backward branch, do periodic checks 18551: 1856#if defined(WITH_JIT) 1857 GET_JIT_PROF_TABLE(r0) 1858 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1859 cmp r0,#0 1860 bne common_updateProfile 1861 GET_INST_OPCODE(ip) @ extract opcode from rINST 1862 GOTO_OPCODE(ip) @ jump to next instruction 1863#else 1864 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1865 GET_INST_OPCODE(ip) @ extract opcode from rINST 1866 GOTO_OPCODE(ip) @ jump to next instruction 1867#endif 1868 1869 1870 1871/* ------------------------------ */ 1872 .balign 64 1873.L_OP_IF_GTZ: /* 0x3c */ 1874/* File: armv5te/OP_IF_GTZ.S */ 1875/* File: armv5te/zcmp.S */ 1876 /* 1877 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1878 * fragment that specifies the *reverse* comparison to perform, e.g. 1879 * for "if-le" you would use "gt". 1880 * 1881 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1882 */ 1883 /* if-cmp vAA, +BBBB */ 1884 mov r0, rINST, lsr #8 @ r0<- AA 1885 GET_VREG(r2, r0) @ r2<- vAA 1886 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1887 cmp r2, #0 @ compare (vA, 0) 1888 ble 1f @ branch to 1 if comparison failed 1889 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1890 movs r9, r9, asl #1 @ convert to bytes, check sign 1891 bmi common_backwardBranch @ backward branch, do periodic checks 18921: 1893#if defined(WITH_JIT) 1894 GET_JIT_PROF_TABLE(r0) 1895 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1896 cmp r0,#0 1897 bne common_updateProfile 1898 GET_INST_OPCODE(ip) @ extract opcode from rINST 1899 GOTO_OPCODE(ip) @ jump to next instruction 1900#else 1901 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1902 GET_INST_OPCODE(ip) @ extract opcode from rINST 1903 GOTO_OPCODE(ip) @ jump to next instruction 1904#endif 1905 1906 1907 1908/* ------------------------------ */ 1909 .balign 64 1910.L_OP_IF_LEZ: /* 0x3d */ 1911/* File: armv5te/OP_IF_LEZ.S */ 1912/* File: armv5te/zcmp.S */ 1913 /* 1914 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1915 * fragment that specifies the *reverse* comparison to perform, e.g. 1916 * for "if-le" you would use "gt". 1917 * 1918 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1919 */ 1920 /* if-cmp vAA, +BBBB */ 1921 mov r0, rINST, lsr #8 @ r0<- AA 1922 GET_VREG(r2, r0) @ r2<- vAA 1923 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1924 cmp r2, #0 @ compare (vA, 0) 1925 bgt 1f @ branch to 1 if comparison failed 1926 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1927 movs r9, r9, asl #1 @ convert to bytes, check sign 1928 bmi common_backwardBranch @ backward branch, do periodic checks 19291: 1930#if defined(WITH_JIT) 1931 GET_JIT_PROF_TABLE(r0) 1932 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1933 cmp r0,#0 1934 bne common_updateProfile 1935 GET_INST_OPCODE(ip) @ extract opcode from rINST 1936 GOTO_OPCODE(ip) @ jump to next instruction 1937#else 1938 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1939 GET_INST_OPCODE(ip) @ extract opcode from rINST 1940 GOTO_OPCODE(ip) @ jump to next instruction 1941#endif 1942 1943 1944 1945/* ------------------------------ */ 1946 .balign 64 1947.L_OP_UNUSED_3E: /* 0x3e */ 1948/* File: armv5te/OP_UNUSED_3E.S */ 1949/* File: armv5te/unused.S */ 1950 bl common_abort 1951 1952 1953 1954/* ------------------------------ */ 1955 .balign 64 1956.L_OP_UNUSED_3F: /* 0x3f */ 1957/* File: armv5te/OP_UNUSED_3F.S */ 1958/* File: armv5te/unused.S */ 1959 bl common_abort 1960 1961 1962 1963/* ------------------------------ */ 1964 .balign 64 1965.L_OP_UNUSED_40: /* 0x40 */ 1966/* File: armv5te/OP_UNUSED_40.S */ 1967/* File: armv5te/unused.S */ 1968 bl common_abort 1969 1970 1971 1972/* ------------------------------ */ 1973 .balign 64 1974.L_OP_UNUSED_41: /* 0x41 */ 1975/* File: armv5te/OP_UNUSED_41.S */ 1976/* File: armv5te/unused.S */ 1977 bl common_abort 1978 1979 1980 1981/* ------------------------------ */ 1982 .balign 64 1983.L_OP_UNUSED_42: /* 0x42 */ 1984/* File: armv5te/OP_UNUSED_42.S */ 1985/* File: armv5te/unused.S */ 1986 bl common_abort 1987 1988 1989 1990/* ------------------------------ */ 1991 .balign 64 1992.L_OP_UNUSED_43: /* 0x43 */ 1993/* File: armv5te/OP_UNUSED_43.S */ 1994/* File: armv5te/unused.S */ 1995 bl common_abort 1996 1997 1998 1999/* ------------------------------ */ 2000 .balign 64 2001.L_OP_AGET: /* 0x44 */ 2002/* File: armv5te/OP_AGET.S */ 2003 /* 2004 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2005 * 2006 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2007 * instructions. We use a pair of FETCH_Bs instead. 2008 * 2009 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2010 */ 2011 /* op vAA, vBB, vCC */ 2012 FETCH_B(r2, 1, 0) @ r2<- BB 2013 mov r9, rINST, lsr #8 @ r9<- AA 2014 FETCH_B(r3, 1, 1) @ r3<- CC 2015 GET_VREG(r0, r2) @ r0<- vBB (array object) 2016 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2017 cmp r0, #0 @ null array object? 2018 beq common_errNullObject @ yes, bail 2019 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2020 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2021 cmp r1, r3 @ compare unsigned index, length 2022 bcs common_errArrayIndex @ index >= length, bail 2023 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2024 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2025 GET_INST_OPCODE(ip) @ extract opcode from rINST 2026 SET_VREG(r2, r9) @ vAA<- r2 2027 GOTO_OPCODE(ip) @ jump to next instruction 2028 2029 2030/* ------------------------------ */ 2031 .balign 64 2032.L_OP_AGET_WIDE: /* 0x45 */ 2033/* File: armv5te/OP_AGET_WIDE.S */ 2034 /* 2035 * Array get, 64 bits. vAA <- vBB[vCC]. 2036 * 2037 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 2038 */ 2039 /* aget-wide vAA, vBB, vCC */ 2040 FETCH(r0, 1) @ r0<- CCBB 2041 mov r9, rINST, lsr #8 @ r9<- AA 2042 and r2, r0, #255 @ r2<- BB 2043 mov r3, r0, lsr #8 @ r3<- CC 2044 GET_VREG(r0, r2) @ r0<- vBB (array object) 2045 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2046 cmp r0, #0 @ null array object? 2047 beq common_errNullObject @ yes, bail 2048 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2049 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2050 cmp r1, r3 @ compare unsigned index, length 2051 bcc .LOP_AGET_WIDE_finish @ okay, continue below 2052 b common_errArrayIndex @ index >= length, bail 2053 @ May want to swap the order of these two branches depending on how the 2054 @ branch prediction (if any) handles conditional forward branches vs. 2055 @ unconditional forward branches. 2056 2057/* ------------------------------ */ 2058 .balign 64 2059.L_OP_AGET_OBJECT: /* 0x46 */ 2060/* File: armv5te/OP_AGET_OBJECT.S */ 2061/* File: armv5te/OP_AGET.S */ 2062 /* 2063 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2064 * 2065 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2066 * instructions. We use a pair of FETCH_Bs instead. 2067 * 2068 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2069 */ 2070 /* op vAA, vBB, vCC */ 2071 FETCH_B(r2, 1, 0) @ r2<- BB 2072 mov r9, rINST, lsr #8 @ r9<- AA 2073 FETCH_B(r3, 1, 1) @ r3<- CC 2074 GET_VREG(r0, r2) @ r0<- vBB (array object) 2075 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2076 cmp r0, #0 @ null array object? 2077 beq common_errNullObject @ yes, bail 2078 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2079 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2080 cmp r1, r3 @ compare unsigned index, length 2081 bcs common_errArrayIndex @ index >= length, bail 2082 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2083 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2084 GET_INST_OPCODE(ip) @ extract opcode from rINST 2085 SET_VREG(r2, r9) @ vAA<- r2 2086 GOTO_OPCODE(ip) @ jump to next instruction 2087 2088 2089 2090/* ------------------------------ */ 2091 .balign 64 2092.L_OP_AGET_BOOLEAN: /* 0x47 */ 2093/* File: armv5te/OP_AGET_BOOLEAN.S */ 2094/* File: armv5te/OP_AGET.S */ 2095 /* 2096 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2097 * 2098 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2099 * instructions. We use a pair of FETCH_Bs instead. 2100 * 2101 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2102 */ 2103 /* op vAA, vBB, vCC */ 2104 FETCH_B(r2, 1, 0) @ r2<- BB 2105 mov r9, rINST, lsr #8 @ r9<- AA 2106 FETCH_B(r3, 1, 1) @ r3<- CC 2107 GET_VREG(r0, r2) @ r0<- vBB (array object) 2108 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2109 cmp r0, #0 @ null array object? 2110 beq common_errNullObject @ yes, bail 2111 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2112 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2113 cmp r1, r3 @ compare unsigned index, length 2114 bcs common_errArrayIndex @ index >= length, bail 2115 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2116 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2117 GET_INST_OPCODE(ip) @ extract opcode from rINST 2118 SET_VREG(r2, r9) @ vAA<- r2 2119 GOTO_OPCODE(ip) @ jump to next instruction 2120 2121 2122 2123/* ------------------------------ */ 2124 .balign 64 2125.L_OP_AGET_BYTE: /* 0x48 */ 2126/* File: armv5te/OP_AGET_BYTE.S */ 2127/* File: armv5te/OP_AGET.S */ 2128 /* 2129 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2130 * 2131 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2132 * instructions. We use a pair of FETCH_Bs instead. 2133 * 2134 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2135 */ 2136 /* op vAA, vBB, vCC */ 2137 FETCH_B(r2, 1, 0) @ r2<- BB 2138 mov r9, rINST, lsr #8 @ r9<- AA 2139 FETCH_B(r3, 1, 1) @ r3<- CC 2140 GET_VREG(r0, r2) @ r0<- vBB (array object) 2141 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2142 cmp r0, #0 @ null array object? 2143 beq common_errNullObject @ yes, bail 2144 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2145 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2146 cmp r1, r3 @ compare unsigned index, length 2147 bcs common_errArrayIndex @ index >= length, bail 2148 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2149 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2150 GET_INST_OPCODE(ip) @ extract opcode from rINST 2151 SET_VREG(r2, r9) @ vAA<- r2 2152 GOTO_OPCODE(ip) @ jump to next instruction 2153 2154 2155 2156/* ------------------------------ */ 2157 .balign 64 2158.L_OP_AGET_CHAR: /* 0x49 */ 2159/* File: armv5te/OP_AGET_CHAR.S */ 2160/* File: armv5te/OP_AGET.S */ 2161 /* 2162 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2163 * 2164 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2165 * instructions. We use a pair of FETCH_Bs instead. 2166 * 2167 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2168 */ 2169 /* op vAA, vBB, vCC */ 2170 FETCH_B(r2, 1, 0) @ r2<- BB 2171 mov r9, rINST, lsr #8 @ r9<- AA 2172 FETCH_B(r3, 1, 1) @ r3<- CC 2173 GET_VREG(r0, r2) @ r0<- vBB (array object) 2174 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2175 cmp r0, #0 @ null array object? 2176 beq common_errNullObject @ yes, bail 2177 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2178 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2179 cmp r1, r3 @ compare unsigned index, length 2180 bcs common_errArrayIndex @ index >= length, bail 2181 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2182 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2183 GET_INST_OPCODE(ip) @ extract opcode from rINST 2184 SET_VREG(r2, r9) @ vAA<- r2 2185 GOTO_OPCODE(ip) @ jump to next instruction 2186 2187 2188 2189/* ------------------------------ */ 2190 .balign 64 2191.L_OP_AGET_SHORT: /* 0x4a */ 2192/* File: armv5te/OP_AGET_SHORT.S */ 2193/* File: armv5te/OP_AGET.S */ 2194 /* 2195 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2196 * 2197 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2198 * instructions. We use a pair of FETCH_Bs instead. 2199 * 2200 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2201 */ 2202 /* op vAA, vBB, vCC */ 2203 FETCH_B(r2, 1, 0) @ r2<- BB 2204 mov r9, rINST, lsr #8 @ r9<- AA 2205 FETCH_B(r3, 1, 1) @ r3<- CC 2206 GET_VREG(r0, r2) @ r0<- vBB (array object) 2207 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2208 cmp r0, #0 @ null array object? 2209 beq common_errNullObject @ yes, bail 2210 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2211 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2212 cmp r1, r3 @ compare unsigned index, length 2213 bcs common_errArrayIndex @ index >= length, bail 2214 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2215 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2216 GET_INST_OPCODE(ip) @ extract opcode from rINST 2217 SET_VREG(r2, r9) @ vAA<- r2 2218 GOTO_OPCODE(ip) @ jump to next instruction 2219 2220 2221 2222/* ------------------------------ */ 2223 .balign 64 2224.L_OP_APUT: /* 0x4b */ 2225/* File: armv5te/OP_APUT.S */ 2226 /* 2227 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2228 * 2229 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2230 * instructions. We use a pair of FETCH_Bs instead. 2231 * 2232 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2233 */ 2234 /* op vAA, vBB, vCC */ 2235 FETCH_B(r2, 1, 0) @ r2<- BB 2236 mov r9, rINST, lsr #8 @ r9<- AA 2237 FETCH_B(r3, 1, 1) @ 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 #2 @ r0<- arrayObj + index*width 2244 cmp r1, r3 @ compare unsigned index, length 2245 bcs common_errArrayIndex @ index >= length, bail 2246 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2247 GET_VREG(r2, r9) @ r2<- vAA 2248 GET_INST_OPCODE(ip) @ extract opcode from rINST 2249 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2250 GOTO_OPCODE(ip) @ jump to next instruction 2251 2252 2253/* ------------------------------ */ 2254 .balign 64 2255.L_OP_APUT_WIDE: /* 0x4c */ 2256/* File: armv5te/OP_APUT_WIDE.S */ 2257 /* 2258 * Array put, 64 bits. vBB[vCC] <- vAA. 2259 * 2260 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 2261 */ 2262 /* aput-wide 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(r0, r2) @ r0<- vBB (array object) 2268 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2269 cmp r0, #0 @ null array object? 2270 beq common_errNullObject @ yes, bail 2271 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2272 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2273 cmp r1, r3 @ compare unsigned index, length 2274 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2275 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2276 b common_errArrayIndex @ index >= length, bail 2277 @ May want to swap the order of these two branches depending on how the 2278 @ branch prediction (if any) handles conditional forward branches vs. 2279 @ unconditional forward branches. 2280 2281/* ------------------------------ */ 2282 .balign 64 2283.L_OP_APUT_OBJECT: /* 0x4d */ 2284/* File: armv5te/OP_APUT_OBJECT.S */ 2285 /* 2286 * Store an object into an array. vBB[vCC] <- vAA. 2287 * 2288 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2289 * instructions. We use a pair of FETCH_Bs instead. 2290 */ 2291 /* op vAA, vBB, vCC */ 2292 FETCH(r0, 1) @ r0<- CCBB 2293 mov r9, rINST, lsr #8 @ r9<- AA 2294 and r2, r0, #255 @ r2<- BB 2295 mov r3, r0, lsr #8 @ r3<- CC 2296 GET_VREG(r1, r2) @ r1<- vBB (array object) 2297 GET_VREG(r0, r3) @ r0<- vCC (requested index) 2298 cmp r1, #0 @ null array object? 2299 GET_VREG(r9, r9) @ r9<- vAA 2300 beq common_errNullObject @ yes, bail 2301 ldr r3, [r1, #offArrayObject_length] @ r3<- arrayObj->length 2302 add r10, r1, r0, lsl #2 @ r10<- arrayObj + index*width 2303 cmp r0, r3 @ compare unsigned index, length 2304 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2305 b common_errArrayIndex @ index >= length, bail 2306 2307 2308/* ------------------------------ */ 2309 .balign 64 2310.L_OP_APUT_BOOLEAN: /* 0x4e */ 2311/* File: armv5te/OP_APUT_BOOLEAN.S */ 2312/* File: armv5te/OP_APUT.S */ 2313 /* 2314 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2315 * 2316 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2317 * instructions. We use a pair of FETCH_Bs instead. 2318 * 2319 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2320 */ 2321 /* op vAA, vBB, vCC */ 2322 FETCH_B(r2, 1, 0) @ r2<- BB 2323 mov r9, rINST, lsr #8 @ r9<- AA 2324 FETCH_B(r3, 1, 1) @ r3<- CC 2325 GET_VREG(r0, r2) @ r0<- vBB (array object) 2326 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2327 cmp r0, #0 @ null array object? 2328 beq common_errNullObject @ yes, bail 2329 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2330 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2331 cmp r1, r3 @ compare unsigned index, length 2332 bcs common_errArrayIndex @ index >= length, bail 2333 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2334 GET_VREG(r2, r9) @ r2<- vAA 2335 GET_INST_OPCODE(ip) @ extract opcode from rINST 2336 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2337 GOTO_OPCODE(ip) @ jump to next instruction 2338 2339 2340 2341/* ------------------------------ */ 2342 .balign 64 2343.L_OP_APUT_BYTE: /* 0x4f */ 2344/* File: armv5te/OP_APUT_BYTE.S */ 2345/* File: armv5te/OP_APUT.S */ 2346 /* 2347 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2348 * 2349 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2350 * instructions. We use a pair of FETCH_Bs instead. 2351 * 2352 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2353 */ 2354 /* op vAA, vBB, vCC */ 2355 FETCH_B(r2, 1, 0) @ r2<- BB 2356 mov r9, rINST, lsr #8 @ r9<- AA 2357 FETCH_B(r3, 1, 1) @ r3<- CC 2358 GET_VREG(r0, r2) @ r0<- vBB (array object) 2359 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2360 cmp r0, #0 @ null array object? 2361 beq common_errNullObject @ yes, bail 2362 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2363 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2364 cmp r1, r3 @ compare unsigned index, length 2365 bcs common_errArrayIndex @ index >= length, bail 2366 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2367 GET_VREG(r2, r9) @ r2<- vAA 2368 GET_INST_OPCODE(ip) @ extract opcode from rINST 2369 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2370 GOTO_OPCODE(ip) @ jump to next instruction 2371 2372 2373 2374/* ------------------------------ */ 2375 .balign 64 2376.L_OP_APUT_CHAR: /* 0x50 */ 2377/* File: armv5te/OP_APUT_CHAR.S */ 2378/* File: armv5te/OP_APUT.S */ 2379 /* 2380 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2381 * 2382 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2383 * instructions. We use a pair of FETCH_Bs instead. 2384 * 2385 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2386 */ 2387 /* op vAA, vBB, vCC */ 2388 FETCH_B(r2, 1, 0) @ r2<- BB 2389 mov r9, rINST, lsr #8 @ r9<- AA 2390 FETCH_B(r3, 1, 1) @ r3<- CC 2391 GET_VREG(r0, r2) @ r0<- vBB (array object) 2392 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2393 cmp r0, #0 @ null array object? 2394 beq common_errNullObject @ yes, bail 2395 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2396 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2397 cmp r1, r3 @ compare unsigned index, length 2398 bcs common_errArrayIndex @ index >= length, bail 2399 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2400 GET_VREG(r2, r9) @ r2<- vAA 2401 GET_INST_OPCODE(ip) @ extract opcode from rINST 2402 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2403 GOTO_OPCODE(ip) @ jump to next instruction 2404 2405 2406 2407/* ------------------------------ */ 2408 .balign 64 2409.L_OP_APUT_SHORT: /* 0x51 */ 2410/* File: armv5te/OP_APUT_SHORT.S */ 2411/* File: armv5te/OP_APUT.S */ 2412 /* 2413 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2414 * 2415 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2416 * instructions. We use a pair of FETCH_Bs instead. 2417 * 2418 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2419 */ 2420 /* op vAA, vBB, vCC */ 2421 FETCH_B(r2, 1, 0) @ r2<- BB 2422 mov r9, rINST, lsr #8 @ r9<- AA 2423 FETCH_B(r3, 1, 1) @ r3<- CC 2424 GET_VREG(r0, r2) @ r0<- vBB (array object) 2425 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2426 cmp r0, #0 @ null array object? 2427 beq common_errNullObject @ yes, bail 2428 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2429 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2430 cmp r1, r3 @ compare unsigned index, length 2431 bcs common_errArrayIndex @ index >= length, bail 2432 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2433 GET_VREG(r2, r9) @ r2<- vAA 2434 GET_INST_OPCODE(ip) @ extract opcode from rINST 2435 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2436 GOTO_OPCODE(ip) @ jump to next instruction 2437 2438 2439 2440/* ------------------------------ */ 2441 .balign 64 2442.L_OP_IGET: /* 0x52 */ 2443/* File: armv6t2/OP_IGET.S */ 2444 /* 2445 * General 32-bit instance field get. 2446 * 2447 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2448 */ 2449 /* op vA, vB, field@CCCC */ 2450 mov r0, rINST, lsr #12 @ r0<- B 2451 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2452 FETCH(r1, 1) @ r1<- field ref CCCC 2453 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2454 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2455 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2456 cmp r0, #0 @ is resolved entry null? 2457 bne .LOP_IGET_finish @ no, already resolved 24588: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2459 EXPORT_PC() @ resolve() could throw 2460 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2461 bl dvmResolveInstField @ r0<- resolved InstField ptr 2462 cmp r0, #0 2463 bne .LOP_IGET_finish 2464 b common_exceptionThrown 2465 2466/* ------------------------------ */ 2467 .balign 64 2468.L_OP_IGET_WIDE: /* 0x53 */ 2469/* File: armv6t2/OP_IGET_WIDE.S */ 2470 /* 2471 * Wide 32-bit instance field get. 2472 */ 2473 /* iget-wide vA, vB, field@CCCC */ 2474 mov r0, rINST, lsr #12 @ r0<- B 2475 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2476 FETCH(r1, 1) @ r1<- field ref CCCC 2477 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2478 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2479 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2480 cmp r0, #0 @ is resolved entry null? 2481 bne .LOP_IGET_WIDE_finish @ no, already resolved 24828: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2483 EXPORT_PC() @ resolve() could throw 2484 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2485 bl dvmResolveInstField @ r0<- resolved InstField ptr 2486 cmp r0, #0 2487 bne .LOP_IGET_WIDE_finish 2488 b common_exceptionThrown 2489 2490/* ------------------------------ */ 2491 .balign 64 2492.L_OP_IGET_OBJECT: /* 0x54 */ 2493/* File: armv5te/OP_IGET_OBJECT.S */ 2494/* File: armv5te/OP_IGET.S */ 2495 /* 2496 * General 32-bit instance field get. 2497 * 2498 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2499 */ 2500 /* op vA, vB, field@CCCC */ 2501 mov r0, rINST, lsr #12 @ r0<- B 2502 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2503 FETCH(r1, 1) @ r1<- field ref CCCC 2504 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2505 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2506 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2507 cmp r0, #0 @ is resolved entry null? 2508 bne .LOP_IGET_OBJECT_finish @ no, already resolved 25098: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2510 EXPORT_PC() @ resolve() could throw 2511 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2512 bl dvmResolveInstField @ r0<- resolved InstField ptr 2513 cmp r0, #0 2514 bne .LOP_IGET_OBJECT_finish 2515 b common_exceptionThrown 2516 2517 2518/* ------------------------------ */ 2519 .balign 64 2520.L_OP_IGET_BOOLEAN: /* 0x55 */ 2521/* File: armv5te/OP_IGET_BOOLEAN.S */ 2522@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2523/* File: armv5te/OP_IGET.S */ 2524 /* 2525 * General 32-bit instance field get. 2526 * 2527 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2528 */ 2529 /* op vA, vB, field@CCCC */ 2530 mov r0, rINST, lsr #12 @ r0<- B 2531 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2532 FETCH(r1, 1) @ r1<- field ref CCCC 2533 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2534 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2535 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2536 cmp r0, #0 @ is resolved entry null? 2537 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 25388: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2539 EXPORT_PC() @ resolve() could throw 2540 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2541 bl dvmResolveInstField @ r0<- resolved InstField ptr 2542 cmp r0, #0 2543 bne .LOP_IGET_BOOLEAN_finish 2544 b common_exceptionThrown 2545 2546 2547/* ------------------------------ */ 2548 .balign 64 2549.L_OP_IGET_BYTE: /* 0x56 */ 2550/* File: armv5te/OP_IGET_BYTE.S */ 2551@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2552/* File: armv5te/OP_IGET.S */ 2553 /* 2554 * General 32-bit instance field get. 2555 * 2556 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2557 */ 2558 /* op vA, vB, field@CCCC */ 2559 mov r0, rINST, lsr #12 @ r0<- B 2560 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2561 FETCH(r1, 1) @ r1<- field ref CCCC 2562 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2563 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2564 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2565 cmp r0, #0 @ is resolved entry null? 2566 bne .LOP_IGET_BYTE_finish @ no, already resolved 25678: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2568 EXPORT_PC() @ resolve() could throw 2569 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2570 bl dvmResolveInstField @ r0<- resolved InstField ptr 2571 cmp r0, #0 2572 bne .LOP_IGET_BYTE_finish 2573 b common_exceptionThrown 2574 2575 2576/* ------------------------------ */ 2577 .balign 64 2578.L_OP_IGET_CHAR: /* 0x57 */ 2579/* File: armv5te/OP_IGET_CHAR.S */ 2580@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2581/* File: armv5te/OP_IGET.S */ 2582 /* 2583 * General 32-bit instance field get. 2584 * 2585 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2586 */ 2587 /* op vA, vB, field@CCCC */ 2588 mov r0, rINST, lsr #12 @ r0<- B 2589 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2590 FETCH(r1, 1) @ r1<- field ref CCCC 2591 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2592 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2593 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2594 cmp r0, #0 @ is resolved entry null? 2595 bne .LOP_IGET_CHAR_finish @ no, already resolved 25968: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2597 EXPORT_PC() @ resolve() could throw 2598 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2599 bl dvmResolveInstField @ r0<- resolved InstField ptr 2600 cmp r0, #0 2601 bne .LOP_IGET_CHAR_finish 2602 b common_exceptionThrown 2603 2604 2605/* ------------------------------ */ 2606 .balign 64 2607.L_OP_IGET_SHORT: /* 0x58 */ 2608/* File: armv5te/OP_IGET_SHORT.S */ 2609@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2610/* File: armv5te/OP_IGET.S */ 2611 /* 2612 * General 32-bit instance field get. 2613 * 2614 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2615 */ 2616 /* op vA, vB, field@CCCC */ 2617 mov r0, rINST, lsr #12 @ r0<- B 2618 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2619 FETCH(r1, 1) @ r1<- field ref CCCC 2620 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2621 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2622 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2623 cmp r0, #0 @ is resolved entry null? 2624 bne .LOP_IGET_SHORT_finish @ no, already resolved 26258: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2626 EXPORT_PC() @ resolve() could throw 2627 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2628 bl dvmResolveInstField @ r0<- resolved InstField ptr 2629 cmp r0, #0 2630 bne .LOP_IGET_SHORT_finish 2631 b common_exceptionThrown 2632 2633 2634/* ------------------------------ */ 2635 .balign 64 2636.L_OP_IPUT: /* 0x59 */ 2637/* File: armv6t2/OP_IPUT.S */ 2638 /* 2639 * General 32-bit instance field put. 2640 * 2641 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2642 */ 2643 /* op vA, vB, field@CCCC */ 2644 mov r0, rINST, lsr #12 @ r0<- B 2645 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2646 FETCH(r1, 1) @ r1<- field ref CCCC 2647 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2648 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2649 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2650 cmp r0, #0 @ is resolved entry null? 2651 bne .LOP_IPUT_finish @ no, already resolved 26528: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2653 EXPORT_PC() @ resolve() could throw 2654 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2655 bl dvmResolveInstField @ r0<- resolved InstField ptr 2656 cmp r0, #0 @ success? 2657 bne .LOP_IPUT_finish @ yes, finish up 2658 b common_exceptionThrown 2659 2660/* ------------------------------ */ 2661 .balign 64 2662.L_OP_IPUT_WIDE: /* 0x5a */ 2663/* File: armv6t2/OP_IPUT_WIDE.S */ 2664 /* iput-wide vA, vB, field@CCCC */ 2665 mov r0, rINST, lsr #12 @ r0<- B 2666 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2667 FETCH(r1, 1) @ r1<- field ref CCCC 2668 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2669 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2670 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2671 cmp r0, #0 @ is resolved entry null? 2672 bne .LOP_IPUT_WIDE_finish @ no, already resolved 26738: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2674 EXPORT_PC() @ resolve() could throw 2675 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2676 bl dvmResolveInstField @ r0<- resolved InstField ptr 2677 cmp r0, #0 @ success? 2678 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2679 b common_exceptionThrown 2680 2681/* ------------------------------ */ 2682 .balign 64 2683.L_OP_IPUT_OBJECT: /* 0x5b */ 2684/* File: armv5te/OP_IPUT_OBJECT.S */ 2685/* File: armv5te/OP_IPUT.S */ 2686 /* 2687 * General 32-bit instance field put. 2688 * 2689 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2690 */ 2691 /* op vA, vB, field@CCCC */ 2692 mov r0, rINST, lsr #12 @ r0<- B 2693 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2694 FETCH(r1, 1) @ r1<- field ref CCCC 2695 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2696 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2697 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2698 cmp r0, #0 @ is resolved entry null? 2699 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 27008: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2701 EXPORT_PC() @ resolve() could throw 2702 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2703 bl dvmResolveInstField @ r0<- resolved InstField ptr 2704 cmp r0, #0 @ success? 2705 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2706 b common_exceptionThrown 2707 2708 2709/* ------------------------------ */ 2710 .balign 64 2711.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2712/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2713@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2714/* File: armv5te/OP_IPUT.S */ 2715 /* 2716 * General 32-bit instance field put. 2717 * 2718 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2719 */ 2720 /* op vA, vB, field@CCCC */ 2721 mov r0, rINST, lsr #12 @ r0<- B 2722 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2723 FETCH(r1, 1) @ r1<- field ref CCCC 2724 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2725 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2726 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2727 cmp r0, #0 @ is resolved entry null? 2728 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 27298: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2730 EXPORT_PC() @ resolve() could throw 2731 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2732 bl dvmResolveInstField @ r0<- resolved InstField ptr 2733 cmp r0, #0 @ success? 2734 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2735 b common_exceptionThrown 2736 2737 2738/* ------------------------------ */ 2739 .balign 64 2740.L_OP_IPUT_BYTE: /* 0x5d */ 2741/* File: armv5te/OP_IPUT_BYTE.S */ 2742@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2743/* File: armv5te/OP_IPUT.S */ 2744 /* 2745 * General 32-bit instance field put. 2746 * 2747 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2748 */ 2749 /* op vA, vB, field@CCCC */ 2750 mov r0, rINST, lsr #12 @ r0<- B 2751 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2752 FETCH(r1, 1) @ r1<- field ref CCCC 2753 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2754 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2755 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2756 cmp r0, #0 @ is resolved entry null? 2757 bne .LOP_IPUT_BYTE_finish @ no, already resolved 27588: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2759 EXPORT_PC() @ resolve() could throw 2760 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2761 bl dvmResolveInstField @ r0<- resolved InstField ptr 2762 cmp r0, #0 @ success? 2763 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2764 b common_exceptionThrown 2765 2766 2767/* ------------------------------ */ 2768 .balign 64 2769.L_OP_IPUT_CHAR: /* 0x5e */ 2770/* File: armv5te/OP_IPUT_CHAR.S */ 2771@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2772/* File: armv5te/OP_IPUT.S */ 2773 /* 2774 * General 32-bit instance field put. 2775 * 2776 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2777 */ 2778 /* op vA, vB, field@CCCC */ 2779 mov r0, rINST, lsr #12 @ r0<- B 2780 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2781 FETCH(r1, 1) @ r1<- field ref CCCC 2782 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2783 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2784 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2785 cmp r0, #0 @ is resolved entry null? 2786 bne .LOP_IPUT_CHAR_finish @ no, already resolved 27878: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2788 EXPORT_PC() @ resolve() could throw 2789 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2790 bl dvmResolveInstField @ r0<- resolved InstField ptr 2791 cmp r0, #0 @ success? 2792 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2793 b common_exceptionThrown 2794 2795 2796/* ------------------------------ */ 2797 .balign 64 2798.L_OP_IPUT_SHORT: /* 0x5f */ 2799/* File: armv5te/OP_IPUT_SHORT.S */ 2800@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2801/* File: armv5te/OP_IPUT.S */ 2802 /* 2803 * General 32-bit instance field put. 2804 * 2805 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2806 */ 2807 /* op vA, vB, field@CCCC */ 2808 mov r0, rINST, lsr #12 @ r0<- B 2809 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2810 FETCH(r1, 1) @ r1<- field ref CCCC 2811 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2812 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2813 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2814 cmp r0, #0 @ is resolved entry null? 2815 bne .LOP_IPUT_SHORT_finish @ no, already resolved 28168: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2817 EXPORT_PC() @ resolve() could throw 2818 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2819 bl dvmResolveInstField @ r0<- resolved InstField ptr 2820 cmp r0, #0 @ success? 2821 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2822 b common_exceptionThrown 2823 2824 2825/* ------------------------------ */ 2826 .balign 64 2827.L_OP_SGET: /* 0x60 */ 2828/* File: armv5te/OP_SGET.S */ 2829 /* 2830 * General 32-bit SGET handler. 2831 * 2832 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2833 */ 2834 /* op vAA, field@BBBB */ 2835 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2836 FETCH(r1, 1) @ r1<- field ref BBBB 2837 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2838 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2839 cmp r0, #0 @ is resolved entry null? 2840 beq .LOP_SGET_resolve @ yes, do resolve 2841.LOP_SGET_finish: @ field ptr in r0 2842 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2843 mov r2, rINST, lsr #8 @ r2<- AA 2844 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2845 SET_VREG(r1, r2) @ fp[AA]<- r1 2846 GET_INST_OPCODE(ip) @ extract opcode from rINST 2847 GOTO_OPCODE(ip) @ jump to next instruction 2848 2849/* ------------------------------ */ 2850 .balign 64 2851.L_OP_SGET_WIDE: /* 0x61 */ 2852/* File: armv5te/OP_SGET_WIDE.S */ 2853 /* 2854 * 64-bit SGET handler. 2855 */ 2856 /* sget-wide vAA, field@BBBB */ 2857 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2858 FETCH(r1, 1) @ r1<- field ref BBBB 2859 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2860 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2861 cmp r0, #0 @ is resolved entry null? 2862 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2863.LOP_SGET_WIDE_finish: 2864 mov r9, rINST, lsr #8 @ r9<- AA 2865 .if 0 2866 add r0, r0, #offStaticField_value @ r0<- pointer to data 2867 bl android_quasiatomic_read_64 @ r0/r1<- contents of field 2868 .else 2869 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 2870 .endif 2871 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2872 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2873 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 2874 GET_INST_OPCODE(ip) @ extract opcode from rINST 2875 GOTO_OPCODE(ip) @ jump to next instruction 2876 2877/* ------------------------------ */ 2878 .balign 64 2879.L_OP_SGET_OBJECT: /* 0x62 */ 2880/* File: armv5te/OP_SGET_OBJECT.S */ 2881/* File: armv5te/OP_SGET.S */ 2882 /* 2883 * General 32-bit SGET handler. 2884 * 2885 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2886 */ 2887 /* op vAA, field@BBBB */ 2888 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2889 FETCH(r1, 1) @ r1<- field ref BBBB 2890 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2891 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2892 cmp r0, #0 @ is resolved entry null? 2893 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2894.LOP_SGET_OBJECT_finish: @ field ptr in r0 2895 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2896 mov r2, rINST, lsr #8 @ r2<- AA 2897 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2898 SET_VREG(r1, r2) @ fp[AA]<- r1 2899 GET_INST_OPCODE(ip) @ extract opcode from rINST 2900 GOTO_OPCODE(ip) @ jump to next instruction 2901 2902 2903/* ------------------------------ */ 2904 .balign 64 2905.L_OP_SGET_BOOLEAN: /* 0x63 */ 2906/* File: armv5te/OP_SGET_BOOLEAN.S */ 2907/* File: armv5te/OP_SGET.S */ 2908 /* 2909 * General 32-bit SGET handler. 2910 * 2911 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2912 */ 2913 /* op vAA, field@BBBB */ 2914 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2915 FETCH(r1, 1) @ r1<- field ref BBBB 2916 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2917 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2918 cmp r0, #0 @ is resolved entry null? 2919 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2920.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2921 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2922 mov r2, rINST, lsr #8 @ r2<- AA 2923 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2924 SET_VREG(r1, r2) @ fp[AA]<- r1 2925 GET_INST_OPCODE(ip) @ extract opcode from rINST 2926 GOTO_OPCODE(ip) @ jump to next instruction 2927 2928 2929/* ------------------------------ */ 2930 .balign 64 2931.L_OP_SGET_BYTE: /* 0x64 */ 2932/* File: armv5te/OP_SGET_BYTE.S */ 2933/* File: armv5te/OP_SGET.S */ 2934 /* 2935 * General 32-bit SGET handler. 2936 * 2937 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2938 */ 2939 /* op vAA, field@BBBB */ 2940 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2941 FETCH(r1, 1) @ r1<- field ref BBBB 2942 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2943 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2944 cmp r0, #0 @ is resolved entry null? 2945 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2946.LOP_SGET_BYTE_finish: @ field ptr in r0 2947 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2948 mov r2, rINST, lsr #8 @ r2<- AA 2949 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2950 SET_VREG(r1, r2) @ fp[AA]<- r1 2951 GET_INST_OPCODE(ip) @ extract opcode from rINST 2952 GOTO_OPCODE(ip) @ jump to next instruction 2953 2954 2955/* ------------------------------ */ 2956 .balign 64 2957.L_OP_SGET_CHAR: /* 0x65 */ 2958/* File: armv5te/OP_SGET_CHAR.S */ 2959/* File: armv5te/OP_SGET.S */ 2960 /* 2961 * General 32-bit SGET handler. 2962 * 2963 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2964 */ 2965 /* op vAA, field@BBBB */ 2966 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2967 FETCH(r1, 1) @ r1<- field ref BBBB 2968 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2969 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2970 cmp r0, #0 @ is resolved entry null? 2971 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2972.LOP_SGET_CHAR_finish: @ field ptr in r0 2973 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2974 mov r2, rINST, lsr #8 @ r2<- AA 2975 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2976 SET_VREG(r1, r2) @ fp[AA]<- r1 2977 GET_INST_OPCODE(ip) @ extract opcode from rINST 2978 GOTO_OPCODE(ip) @ jump to next instruction 2979 2980 2981/* ------------------------------ */ 2982 .balign 64 2983.L_OP_SGET_SHORT: /* 0x66 */ 2984/* File: armv5te/OP_SGET_SHORT.S */ 2985/* File: armv5te/OP_SGET.S */ 2986 /* 2987 * General 32-bit SGET handler. 2988 * 2989 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2990 */ 2991 /* op vAA, field@BBBB */ 2992 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2993 FETCH(r1, 1) @ r1<- field ref BBBB 2994 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2995 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2996 cmp r0, #0 @ is resolved entry null? 2997 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 2998.LOP_SGET_SHORT_finish: @ field ptr in r0 2999 ldr r1, [r0, #offStaticField_value] @ r1<- field value 3000 mov r2, rINST, lsr #8 @ r2<- AA 3001 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3002 SET_VREG(r1, r2) @ fp[AA]<- r1 3003 GET_INST_OPCODE(ip) @ extract opcode from rINST 3004 GOTO_OPCODE(ip) @ jump to next instruction 3005 3006 3007/* ------------------------------ */ 3008 .balign 64 3009.L_OP_SPUT: /* 0x67 */ 3010/* File: armv5te/OP_SPUT.S */ 3011 /* 3012 * General 32-bit SPUT handler. 3013 * 3014 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3015 */ 3016 /* op vAA, field@BBBB */ 3017 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3018 FETCH(r1, 1) @ r1<- field ref BBBB 3019 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3020 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3021 cmp r0, #0 @ is resolved entry null? 3022 beq .LOP_SPUT_resolve @ yes, do resolve 3023.LOP_SPUT_finish: @ field ptr in r0 3024 mov r2, rINST, lsr #8 @ r2<- AA 3025 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3026 GET_VREG(r1, r2) @ r1<- fp[AA] 3027 GET_INST_OPCODE(ip) @ extract opcode from rINST 3028 str r1, [r0, #offStaticField_value] @ field<- vAA 3029 GOTO_OPCODE(ip) @ jump to next instruction 3030 3031/* ------------------------------ */ 3032 .balign 64 3033.L_OP_SPUT_WIDE: /* 0x68 */ 3034/* File: armv5te/OP_SPUT_WIDE.S */ 3035 /* 3036 * 64-bit SPUT handler. 3037 */ 3038 /* sput-wide vAA, field@BBBB */ 3039 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 3040 FETCH(r1, 1) @ r1<- field ref BBBB 3041 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 3042 mov r9, rINST, lsr #8 @ r9<- AA 3043 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 3044 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 3045 cmp r2, #0 @ is resolved entry null? 3046 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 3047.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9 3048 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3049 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 3050 GET_INST_OPCODE(r10) @ extract opcode from rINST 3051 .if 0 3052 add r2, r2, #offStaticField_value @ r2<- pointer to data 3053 bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2 3054 .else 3055 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 3056 .endif 3057 GOTO_OPCODE(r10) @ jump to next instruction 3058 3059/* ------------------------------ */ 3060 .balign 64 3061.L_OP_SPUT_OBJECT: /* 0x69 */ 3062/* File: armv5te/OP_SPUT_OBJECT.S */ 3063/* File: armv5te/OP_SPUT.S */ 3064 /* 3065 * General 32-bit SPUT handler. 3066 * 3067 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3068 */ 3069 /* op vAA, field@BBBB */ 3070 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3071 FETCH(r1, 1) @ r1<- field ref BBBB 3072 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3073 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3074 cmp r0, #0 @ is resolved entry null? 3075 beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve 3076.LOP_SPUT_OBJECT_finish: @ field ptr in r0 3077 mov r2, rINST, lsr #8 @ r2<- AA 3078 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3079 GET_VREG(r1, r2) @ r1<- fp[AA] 3080 GET_INST_OPCODE(ip) @ extract opcode from rINST 3081 str r1, [r0, #offStaticField_value] @ field<- vAA 3082 GOTO_OPCODE(ip) @ jump to next instruction 3083 3084 3085/* ------------------------------ */ 3086 .balign 64 3087.L_OP_SPUT_BOOLEAN: /* 0x6a */ 3088/* File: armv5te/OP_SPUT_BOOLEAN.S */ 3089/* File: armv5te/OP_SPUT.S */ 3090 /* 3091 * General 32-bit SPUT handler. 3092 * 3093 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3094 */ 3095 /* op vAA, field@BBBB */ 3096 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3097 FETCH(r1, 1) @ r1<- field ref BBBB 3098 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3099 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3100 cmp r0, #0 @ is resolved entry null? 3101 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 3102.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 3103 mov r2, rINST, lsr #8 @ r2<- AA 3104 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3105 GET_VREG(r1, r2) @ r1<- fp[AA] 3106 GET_INST_OPCODE(ip) @ extract opcode from rINST 3107 str r1, [r0, #offStaticField_value] @ field<- vAA 3108 GOTO_OPCODE(ip) @ jump to next instruction 3109 3110 3111/* ------------------------------ */ 3112 .balign 64 3113.L_OP_SPUT_BYTE: /* 0x6b */ 3114/* File: armv5te/OP_SPUT_BYTE.S */ 3115/* File: armv5te/OP_SPUT.S */ 3116 /* 3117 * General 32-bit SPUT handler. 3118 * 3119 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3120 */ 3121 /* op vAA, field@BBBB */ 3122 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3123 FETCH(r1, 1) @ r1<- field ref BBBB 3124 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3125 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3126 cmp r0, #0 @ is resolved entry null? 3127 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 3128.LOP_SPUT_BYTE_finish: @ field ptr in r0 3129 mov r2, rINST, lsr #8 @ r2<- AA 3130 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3131 GET_VREG(r1, r2) @ r1<- fp[AA] 3132 GET_INST_OPCODE(ip) @ extract opcode from rINST 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_CHAR: /* 0x6c */ 3140/* File: armv5te/OP_SPUT_CHAR.S */ 3141/* File: armv5te/OP_SPUT.S */ 3142 /* 3143 * General 32-bit SPUT handler. 3144 * 3145 * for: sput, sput-object, 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_CHAR_resolve @ yes, do resolve 3154.LOP_SPUT_CHAR_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 str r1, [r0, #offStaticField_value] @ field<- vAA 3160 GOTO_OPCODE(ip) @ jump to next instruction 3161 3162 3163/* ------------------------------ */ 3164 .balign 64 3165.L_OP_SPUT_SHORT: /* 0x6d */ 3166/* File: armv5te/OP_SPUT_SHORT.S */ 3167/* File: armv5te/OP_SPUT.S */ 3168 /* 3169 * General 32-bit SPUT handler. 3170 * 3171 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3172 */ 3173 /* op vAA, field@BBBB */ 3174 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3175 FETCH(r1, 1) @ r1<- field ref BBBB 3176 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3177 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3178 cmp r0, #0 @ is resolved entry null? 3179 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 3180.LOP_SPUT_SHORT_finish: @ field ptr in r0 3181 mov r2, rINST, lsr #8 @ r2<- AA 3182 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3183 GET_VREG(r1, r2) @ r1<- fp[AA] 3184 GET_INST_OPCODE(ip) @ extract opcode from rINST 3185 str r1, [r0, #offStaticField_value] @ field<- vAA 3186 GOTO_OPCODE(ip) @ jump to next instruction 3187 3188 3189/* ------------------------------ */ 3190 .balign 64 3191.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3192/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3193 /* 3194 * Handle a virtual method call. 3195 * 3196 * for: invoke-virtual, invoke-virtual/range 3197 */ 3198 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3199 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3200 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3201 FETCH(r1, 1) @ r1<- BBBB 3202 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3203 FETCH(r10, 2) @ r10<- GFED or CCCC 3204 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3205 .if (!0) 3206 and r10, r10, #15 @ r10<- D (or stays CCCC) 3207 .endif 3208 cmp r0, #0 @ already resolved? 3209 EXPORT_PC() @ must export for invoke 3210 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3211 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3212 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3213 mov r2, #METHOD_VIRTUAL @ resolver method type 3214 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3215 cmp r0, #0 @ got null? 3216 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3217 b common_exceptionThrown @ yes, handle exception 3218 3219/* ------------------------------ */ 3220 .balign 64 3221.L_OP_INVOKE_SUPER: /* 0x6f */ 3222/* File: armv5te/OP_INVOKE_SUPER.S */ 3223 /* 3224 * Handle a "super" method call. 3225 * 3226 * for: invoke-super, invoke-super/range 3227 */ 3228 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3229 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3230 FETCH(r10, 2) @ r10<- GFED or CCCC 3231 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3232 .if (!0) 3233 and r10, r10, #15 @ r10<- D (or stays CCCC) 3234 .endif 3235 FETCH(r1, 1) @ r1<- BBBB 3236 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3237 GET_VREG(r2, r10) @ r2<- "this" ptr 3238 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3239 cmp r2, #0 @ null "this"? 3240 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3241 beq common_errNullObject @ null "this", throw exception 3242 cmp r0, #0 @ already resolved? 3243 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3244 EXPORT_PC() @ must export for invoke 3245 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3246 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3247 3248/* ------------------------------ */ 3249 .balign 64 3250.L_OP_INVOKE_DIRECT: /* 0x70 */ 3251/* File: armv5te/OP_INVOKE_DIRECT.S */ 3252 /* 3253 * Handle a direct method call. 3254 * 3255 * (We could defer the "is 'this' pointer null" test to the common 3256 * method invocation code, and use a flag to indicate that static 3257 * calls don't count. If we do this as part of copying the arguments 3258 * out we could avoiding loading the first arg twice.) 3259 * 3260 * for: invoke-direct, invoke-direct/range 3261 */ 3262 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3263 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3264 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3265 FETCH(r1, 1) @ r1<- BBBB 3266 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3267 FETCH(r10, 2) @ r10<- GFED or CCCC 3268 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3269 .if (!0) 3270 and r10, r10, #15 @ r10<- D (or stays CCCC) 3271 .endif 3272 cmp r0, #0 @ already resolved? 3273 EXPORT_PC() @ must export for invoke 3274 GET_VREG(r2, r10) @ r2<- "this" ptr 3275 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3276.LOP_INVOKE_DIRECT_finish: 3277 cmp r2, #0 @ null "this" ref? 3278 bne common_invokeMethodNoRange @ no, continue on 3279 b common_errNullObject @ yes, throw exception 3280 3281/* ------------------------------ */ 3282 .balign 64 3283.L_OP_INVOKE_STATIC: /* 0x71 */ 3284/* File: armv5te/OP_INVOKE_STATIC.S */ 3285 /* 3286 * Handle a static method call. 3287 * 3288 * for: invoke-static, invoke-static/range 3289 */ 3290 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3291 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3292 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3293 FETCH(r1, 1) @ r1<- BBBB 3294 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3295 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3296 cmp r0, #0 @ already resolved? 3297 EXPORT_PC() @ must export for invoke 3298 bne common_invokeMethodNoRange @ yes, continue on 32990: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3300 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3301 mov r2, #METHOD_STATIC @ resolver method type 3302 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3303 cmp r0, #0 @ got null? 3304 bne common_invokeMethodNoRange @ no, continue 3305 b common_exceptionThrown @ yes, handle exception 3306 3307 3308/* ------------------------------ */ 3309 .balign 64 3310.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3311/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3312 /* 3313 * Handle an interface method call. 3314 * 3315 * for: invoke-interface, invoke-interface/range 3316 */ 3317 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3318 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3319 FETCH(r2, 2) @ r2<- FEDC or CCCC 3320 FETCH(r1, 1) @ r1<- BBBB 3321 .if (!0) 3322 and r2, r2, #15 @ r2<- C (or stays CCCC) 3323 .endif 3324 EXPORT_PC() @ must export for invoke 3325 GET_VREG(r0, r2) @ r0<- first arg ("this") 3326 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3327 cmp r0, #0 @ null obj? 3328 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3329 beq common_errNullObject @ yes, fail 3330 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3331 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3332 cmp r0, #0 @ failed? 3333 beq common_exceptionThrown @ yes, handle exception 3334 b common_invokeMethodNoRange @ jump to common handler 3335 3336 3337/* ------------------------------ */ 3338 .balign 64 3339.L_OP_UNUSED_73: /* 0x73 */ 3340/* File: armv5te/OP_UNUSED_73.S */ 3341/* File: armv5te/unused.S */ 3342 bl common_abort 3343 3344 3345 3346/* ------------------------------ */ 3347 .balign 64 3348.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3349/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3350/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3351 /* 3352 * Handle a virtual method call. 3353 * 3354 * for: invoke-virtual, invoke-virtual/range 3355 */ 3356 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3357 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3358 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3359 FETCH(r1, 1) @ r1<- BBBB 3360 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3361 FETCH(r10, 2) @ r10<- GFED or CCCC 3362 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3363 .if (!1) 3364 and r10, r10, #15 @ r10<- D (or stays CCCC) 3365 .endif 3366 cmp r0, #0 @ already resolved? 3367 EXPORT_PC() @ must export for invoke 3368 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3369 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3370 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3371 mov r2, #METHOD_VIRTUAL @ resolver method type 3372 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3373 cmp r0, #0 @ got null? 3374 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3375 b common_exceptionThrown @ yes, handle exception 3376 3377 3378/* ------------------------------ */ 3379 .balign 64 3380.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3381/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3382/* File: armv5te/OP_INVOKE_SUPER.S */ 3383 /* 3384 * Handle a "super" method call. 3385 * 3386 * for: invoke-super, invoke-super/range 3387 */ 3388 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3389 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3390 FETCH(r10, 2) @ r10<- GFED or CCCC 3391 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3392 .if (!1) 3393 and r10, r10, #15 @ r10<- D (or stays CCCC) 3394 .endif 3395 FETCH(r1, 1) @ r1<- BBBB 3396 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3397 GET_VREG(r2, r10) @ r2<- "this" ptr 3398 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3399 cmp r2, #0 @ null "this"? 3400 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3401 beq common_errNullObject @ null "this", throw exception 3402 cmp r0, #0 @ already resolved? 3403 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3404 EXPORT_PC() @ must export for invoke 3405 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3406 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3407 3408 3409/* ------------------------------ */ 3410 .balign 64 3411.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3412/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3413/* File: armv5te/OP_INVOKE_DIRECT.S */ 3414 /* 3415 * Handle a direct method call. 3416 * 3417 * (We could defer the "is 'this' pointer null" test to the common 3418 * method invocation code, and use a flag to indicate that static 3419 * calls don't count. If we do this as part of copying the arguments 3420 * out we could avoiding loading the first arg twice.) 3421 * 3422 * for: invoke-direct, invoke-direct/range 3423 */ 3424 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3425 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3426 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3427 FETCH(r1, 1) @ r1<- BBBB 3428 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3429 FETCH(r10, 2) @ r10<- GFED or CCCC 3430 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3431 .if (!1) 3432 and r10, r10, #15 @ r10<- D (or stays CCCC) 3433 .endif 3434 cmp r0, #0 @ already resolved? 3435 EXPORT_PC() @ must export for invoke 3436 GET_VREG(r2, r10) @ r2<- "this" ptr 3437 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3438.LOP_INVOKE_DIRECT_RANGE_finish: 3439 cmp r2, #0 @ null "this" ref? 3440 bne common_invokeMethodRange @ no, continue on 3441 b common_errNullObject @ yes, throw exception 3442 3443 3444/* ------------------------------ */ 3445 .balign 64 3446.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3447/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3448/* File: armv5te/OP_INVOKE_STATIC.S */ 3449 /* 3450 * Handle a static method call. 3451 * 3452 * for: invoke-static, invoke-static/range 3453 */ 3454 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3455 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3456 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3457 FETCH(r1, 1) @ r1<- BBBB 3458 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3459 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3460 cmp r0, #0 @ already resolved? 3461 EXPORT_PC() @ must export for invoke 3462 bne common_invokeMethodRange @ yes, continue on 34630: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3464 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3465 mov r2, #METHOD_STATIC @ resolver method type 3466 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3467 cmp r0, #0 @ got null? 3468 bne common_invokeMethodRange @ no, continue 3469 b common_exceptionThrown @ yes, handle exception 3470 3471 3472 3473/* ------------------------------ */ 3474 .balign 64 3475.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3476/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3477/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3478 /* 3479 * Handle an interface method call. 3480 * 3481 * for: invoke-interface, invoke-interface/range 3482 */ 3483 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3484 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3485 FETCH(r2, 2) @ r2<- FEDC or CCCC 3486 FETCH(r1, 1) @ r1<- BBBB 3487 .if (!1) 3488 and r2, r2, #15 @ r2<- C (or stays CCCC) 3489 .endif 3490 EXPORT_PC() @ must export for invoke 3491 GET_VREG(r0, r2) @ r0<- first arg ("this") 3492 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3493 cmp r0, #0 @ null obj? 3494 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3495 beq common_errNullObject @ yes, fail 3496 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3497 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3498 cmp r0, #0 @ failed? 3499 beq common_exceptionThrown @ yes, handle exception 3500 b common_invokeMethodRange @ jump to common handler 3501 3502 3503 3504/* ------------------------------ */ 3505 .balign 64 3506.L_OP_UNUSED_79: /* 0x79 */ 3507/* File: armv5te/OP_UNUSED_79.S */ 3508/* File: armv5te/unused.S */ 3509 bl common_abort 3510 3511 3512 3513/* ------------------------------ */ 3514 .balign 64 3515.L_OP_UNUSED_7A: /* 0x7a */ 3516/* File: armv5te/OP_UNUSED_7A.S */ 3517/* File: armv5te/unused.S */ 3518 bl common_abort 3519 3520 3521 3522/* ------------------------------ */ 3523 .balign 64 3524.L_OP_NEG_INT: /* 0x7b */ 3525/* File: armv6t2/OP_NEG_INT.S */ 3526/* File: armv6t2/unop.S */ 3527 /* 3528 * Generic 32-bit unary operation. Provide an "instr" line that 3529 * specifies an instruction that performs "result = op r0". 3530 * This could be an ARM instruction or a function call. 3531 * 3532 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3533 * int-to-byte, int-to-char, int-to-short 3534 */ 3535 /* unop vA, vB */ 3536 mov r3, rINST, lsr #12 @ r3<- B 3537 ubfx r9, rINST, #8, #4 @ r9<- A 3538 GET_VREG(r0, r3) @ r0<- vB 3539 @ optional op; may set condition codes 3540 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3541 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3542 GET_INST_OPCODE(ip) @ extract opcode from rINST 3543 SET_VREG(r0, r9) @ vAA<- r0 3544 GOTO_OPCODE(ip) @ jump to next instruction 3545 /* 8-9 instructions */ 3546 3547 3548/* ------------------------------ */ 3549 .balign 64 3550.L_OP_NOT_INT: /* 0x7c */ 3551/* File: armv6t2/OP_NOT_INT.S */ 3552/* File: armv6t2/unop.S */ 3553 /* 3554 * Generic 32-bit unary operation. Provide an "instr" line that 3555 * specifies an instruction that performs "result = op r0". 3556 * This could be an ARM instruction or a function call. 3557 * 3558 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3559 * int-to-byte, int-to-char, int-to-short 3560 */ 3561 /* unop vA, vB */ 3562 mov r3, rINST, lsr #12 @ r3<- B 3563 ubfx r9, rINST, #8, #4 @ r9<- A 3564 GET_VREG(r0, r3) @ r0<- vB 3565 @ optional op; may set condition codes 3566 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3567 mvn r0, r0 @ r0<- op, r0-r3 changed 3568 GET_INST_OPCODE(ip) @ extract opcode from rINST 3569 SET_VREG(r0, r9) @ vAA<- r0 3570 GOTO_OPCODE(ip) @ jump to next instruction 3571 /* 8-9 instructions */ 3572 3573 3574/* ------------------------------ */ 3575 .balign 64 3576.L_OP_NEG_LONG: /* 0x7d */ 3577/* File: armv6t2/OP_NEG_LONG.S */ 3578/* File: armv6t2/unopWide.S */ 3579 /* 3580 * Generic 64-bit unary operation. Provide an "instr" line that 3581 * specifies an instruction that performs "result = op r0/r1". 3582 * This could be an ARM instruction or a function call. 3583 * 3584 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3585 */ 3586 /* unop vA, vB */ 3587 mov r3, rINST, lsr #12 @ r3<- B 3588 ubfx r9, rINST, #8, #4 @ r9<- A 3589 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3590 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3591 ldmia r3, {r0-r1} @ r0/r1<- vAA 3592 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3593 rsbs r0, r0, #0 @ optional op; may set condition codes 3594 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3595 GET_INST_OPCODE(ip) @ extract opcode from rINST 3596 stmia r9, {r0-r1} @ vAA<- r0/r1 3597 GOTO_OPCODE(ip) @ jump to next instruction 3598 /* 10-11 instructions */ 3599 3600 3601 3602/* ------------------------------ */ 3603 .balign 64 3604.L_OP_NOT_LONG: /* 0x7e */ 3605/* File: armv6t2/OP_NOT_LONG.S */ 3606/* File: armv6t2/unopWide.S */ 3607 /* 3608 * Generic 64-bit unary operation. Provide an "instr" line that 3609 * specifies an instruction that performs "result = op r0/r1". 3610 * This could be an ARM instruction or a function call. 3611 * 3612 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3613 */ 3614 /* unop vA, vB */ 3615 mov r3, rINST, lsr #12 @ r3<- B 3616 ubfx r9, rINST, #8, #4 @ r9<- A 3617 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3618 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3619 ldmia r3, {r0-r1} @ r0/r1<- vAA 3620 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3621 mvn r0, r0 @ optional op; may set condition codes 3622 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3623 GET_INST_OPCODE(ip) @ extract opcode from rINST 3624 stmia r9, {r0-r1} @ vAA<- r0/r1 3625 GOTO_OPCODE(ip) @ jump to next instruction 3626 /* 10-11 instructions */ 3627 3628 3629 3630/* ------------------------------ */ 3631 .balign 64 3632.L_OP_NEG_FLOAT: /* 0x7f */ 3633/* File: armv6t2/OP_NEG_FLOAT.S */ 3634/* File: armv6t2/unop.S */ 3635 /* 3636 * Generic 32-bit unary operation. Provide an "instr" line that 3637 * specifies an instruction that performs "result = op r0". 3638 * This could be an ARM instruction or a function call. 3639 * 3640 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3641 * int-to-byte, int-to-char, int-to-short 3642 */ 3643 /* unop vA, vB */ 3644 mov r3, rINST, lsr #12 @ r3<- B 3645 ubfx r9, rINST, #8, #4 @ r9<- A 3646 GET_VREG(r0, r3) @ r0<- vB 3647 @ optional op; may set condition codes 3648 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3649 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3650 GET_INST_OPCODE(ip) @ extract opcode from rINST 3651 SET_VREG(r0, r9) @ vAA<- r0 3652 GOTO_OPCODE(ip) @ jump to next instruction 3653 /* 8-9 instructions */ 3654 3655 3656/* ------------------------------ */ 3657 .balign 64 3658.L_OP_NEG_DOUBLE: /* 0x80 */ 3659/* File: armv6t2/OP_NEG_DOUBLE.S */ 3660/* File: armv6t2/unopWide.S */ 3661 /* 3662 * Generic 64-bit unary operation. Provide an "instr" line that 3663 * specifies an instruction that performs "result = op r0/r1". 3664 * This could be an ARM instruction or a function call. 3665 * 3666 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3667 */ 3668 /* unop vA, vB */ 3669 mov r3, rINST, lsr #12 @ r3<- B 3670 ubfx r9, rINST, #8, #4 @ r9<- A 3671 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3672 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3673 ldmia r3, {r0-r1} @ r0/r1<- vAA 3674 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3675 @ optional op; may set condition codes 3676 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3677 GET_INST_OPCODE(ip) @ extract opcode from rINST 3678 stmia r9, {r0-r1} @ vAA<- r0/r1 3679 GOTO_OPCODE(ip) @ jump to next instruction 3680 /* 10-11 instructions */ 3681 3682 3683 3684/* ------------------------------ */ 3685 .balign 64 3686.L_OP_INT_TO_LONG: /* 0x81 */ 3687/* File: armv6t2/OP_INT_TO_LONG.S */ 3688/* File: armv6t2/unopWider.S */ 3689 /* 3690 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3691 * that specifies an instruction that performs "result = op r0", where 3692 * "result" is a 64-bit quantity in r0/r1. 3693 * 3694 * For: int-to-long, int-to-double, float-to-long, float-to-double 3695 */ 3696 /* unop vA, vB */ 3697 mov r3, rINST, lsr #12 @ r3<- B 3698 ubfx r9, rINST, #8, #4 @ r9<- A 3699 GET_VREG(r0, r3) @ r0<- vB 3700 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3701 @ optional op; may set condition codes 3702 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3703 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3704 GET_INST_OPCODE(ip) @ extract opcode from rINST 3705 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3706 GOTO_OPCODE(ip) @ jump to next instruction 3707 /* 9-10 instructions */ 3708 3709 3710/* ------------------------------ */ 3711 .balign 64 3712.L_OP_INT_TO_FLOAT: /* 0x82 */ 3713/* File: arm-vfp/OP_INT_TO_FLOAT.S */ 3714/* File: arm-vfp/funop.S */ 3715 /* 3716 * Generic 32-bit unary floating-point operation. Provide an "instr" 3717 * line that specifies an instruction that performs "s1 = op s0". 3718 * 3719 * for: int-to-float, float-to-int 3720 */ 3721 /* unop vA, vB */ 3722 mov r3, rINST, lsr #12 @ r3<- B 3723 mov r9, rINST, lsr #8 @ r9<- A+ 3724 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3725 flds s0, [r3] @ s0<- vB 3726 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3727 and r9, r9, #15 @ r9<- A 3728 fsitos s1, s0 @ s1<- op 3729 GET_INST_OPCODE(ip) @ extract opcode from rINST 3730 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3731 fsts s1, [r9] @ vA<- s1 3732 GOTO_OPCODE(ip) @ jump to next instruction 3733 3734 3735/* ------------------------------ */ 3736 .balign 64 3737.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3738/* File: arm-vfp/OP_INT_TO_DOUBLE.S */ 3739/* File: arm-vfp/funopWider.S */ 3740 /* 3741 * Generic 32bit-to-64bit floating point unary operation. Provide an 3742 * "instr" line that specifies an instruction that performs "d0 = op s0". 3743 * 3744 * For: int-to-double, float-to-double 3745 */ 3746 /* unop vA, vB */ 3747 mov r3, rINST, lsr #12 @ r3<- B 3748 mov r9, rINST, lsr #8 @ r9<- A+ 3749 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3750 flds s0, [r3] @ s0<- vB 3751 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3752 and r9, r9, #15 @ r9<- A 3753 fsitod d0, s0 @ d0<- op 3754 GET_INST_OPCODE(ip) @ extract opcode from rINST 3755 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3756 fstd d0, [r9] @ vA<- d0 3757 GOTO_OPCODE(ip) @ jump to next instruction 3758 3759 3760/* ------------------------------ */ 3761 .balign 64 3762.L_OP_LONG_TO_INT: /* 0x84 */ 3763/* File: armv5te/OP_LONG_TO_INT.S */ 3764/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3765/* File: armv5te/OP_MOVE.S */ 3766 /* for move, move-object, long-to-int */ 3767 /* op vA, vB */ 3768 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3769 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3770 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3771 GET_VREG(r2, r1) @ r2<- fp[B] 3772 and r0, r0, #15 3773 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3774 SET_VREG(r2, r0) @ fp[A]<- r2 3775 GOTO_OPCODE(ip) @ execute next instruction 3776 3777 3778 3779/* ------------------------------ */ 3780 .balign 64 3781.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3782/* File: armv6t2/OP_LONG_TO_FLOAT.S */ 3783/* File: armv6t2/unopNarrower.S */ 3784 /* 3785 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3786 * that specifies an instruction that performs "result = op r0/r1", where 3787 * "result" is a 32-bit quantity in r0. 3788 * 3789 * For: long-to-float, double-to-int, double-to-float 3790 * 3791 * (This would work for long-to-int, but that instruction is actually 3792 * an exact match for OP_MOVE.) 3793 */ 3794 /* unop vA, vB */ 3795 mov r3, rINST, lsr #12 @ r3<- B 3796 ubfx r9, rINST, #8, #4 @ r9<- A 3797 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3798 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3799 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3800 @ optional op; may set condition codes 3801 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3802 GET_INST_OPCODE(ip) @ extract opcode from rINST 3803 SET_VREG(r0, r9) @ vA<- r0 3804 GOTO_OPCODE(ip) @ jump to next instruction 3805 /* 9-10 instructions */ 3806 3807 3808/* ------------------------------ */ 3809 .balign 64 3810.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3811/* File: armv6t2/OP_LONG_TO_DOUBLE.S */ 3812/* File: armv6t2/unopWide.S */ 3813 /* 3814 * Generic 64-bit unary operation. Provide an "instr" line that 3815 * specifies an instruction that performs "result = op r0/r1". 3816 * This could be an ARM instruction or a function call. 3817 * 3818 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3819 */ 3820 /* unop vA, vB */ 3821 mov r3, rINST, lsr #12 @ r3<- B 3822 ubfx r9, rINST, #8, #4 @ r9<- A 3823 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3824 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3825 ldmia r3, {r0-r1} @ r0/r1<- vAA 3826 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3827 @ optional op; may set condition codes 3828 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3829 GET_INST_OPCODE(ip) @ extract opcode from rINST 3830 stmia r9, {r0-r1} @ vAA<- r0/r1 3831 GOTO_OPCODE(ip) @ jump to next instruction 3832 /* 10-11 instructions */ 3833 3834 3835 3836/* ------------------------------ */ 3837 .balign 64 3838.L_OP_FLOAT_TO_INT: /* 0x87 */ 3839/* File: arm-vfp/OP_FLOAT_TO_INT.S */ 3840/* File: arm-vfp/funop.S */ 3841 /* 3842 * Generic 32-bit unary floating-point operation. Provide an "instr" 3843 * line that specifies an instruction that performs "s1 = op s0". 3844 * 3845 * for: int-to-float, float-to-int 3846 */ 3847 /* unop vA, vB */ 3848 mov r3, rINST, lsr #12 @ r3<- B 3849 mov r9, rINST, lsr #8 @ r9<- A+ 3850 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3851 flds s0, [r3] @ s0<- vB 3852 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3853 and r9, r9, #15 @ r9<- A 3854 ftosizs s1, s0 @ s1<- op 3855 GET_INST_OPCODE(ip) @ extract opcode from rINST 3856 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3857 fsts s1, [r9] @ vA<- s1 3858 GOTO_OPCODE(ip) @ jump to next instruction 3859 3860 3861/* ------------------------------ */ 3862 .balign 64 3863.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3864/* File: armv6t2/OP_FLOAT_TO_LONG.S */ 3865@include "armv6t2/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3866/* File: armv6t2/unopWider.S */ 3867 /* 3868 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3869 * that specifies an instruction that performs "result = op r0", where 3870 * "result" is a 64-bit quantity in r0/r1. 3871 * 3872 * For: int-to-long, int-to-double, float-to-long, float-to-double 3873 */ 3874 /* unop vA, vB */ 3875 mov r3, rINST, lsr #12 @ r3<- B 3876 ubfx r9, rINST, #8, #4 @ r9<- A 3877 GET_VREG(r0, r3) @ r0<- vB 3878 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3879 @ optional op; may set condition codes 3880 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3881 bl f2l_doconv @ r0<- op, r0-r3 changed 3882 GET_INST_OPCODE(ip) @ extract opcode from rINST 3883 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3884 GOTO_OPCODE(ip) @ jump to next instruction 3885 /* 9-10 instructions */ 3886 3887 3888 3889/* ------------------------------ */ 3890 .balign 64 3891.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3892/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */ 3893/* File: arm-vfp/funopWider.S */ 3894 /* 3895 * Generic 32bit-to-64bit floating point unary operation. Provide an 3896 * "instr" line that specifies an instruction that performs "d0 = op s0". 3897 * 3898 * For: int-to-double, float-to-double 3899 */ 3900 /* unop vA, vB */ 3901 mov r3, rINST, lsr #12 @ r3<- B 3902 mov r9, rINST, lsr #8 @ r9<- A+ 3903 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3904 flds s0, [r3] @ s0<- vB 3905 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3906 and r9, r9, #15 @ r9<- A 3907 fcvtds d0, s0 @ d0<- op 3908 GET_INST_OPCODE(ip) @ extract opcode from rINST 3909 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3910 fstd d0, [r9] @ vA<- d0 3911 GOTO_OPCODE(ip) @ jump to next instruction 3912 3913 3914/* ------------------------------ */ 3915 .balign 64 3916.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3917/* File: arm-vfp/OP_DOUBLE_TO_INT.S */ 3918/* File: arm-vfp/funopNarrower.S */ 3919 /* 3920 * Generic 64bit-to-32bit unary floating point operation. Provide an 3921 * "instr" line that specifies an instruction that performs "s0 = op d0". 3922 * 3923 * For: double-to-int, double-to-float 3924 */ 3925 /* unop vA, vB */ 3926 mov r3, rINST, lsr #12 @ r3<- B 3927 mov r9, rINST, lsr #8 @ r9<- A+ 3928 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3929 fldd d0, [r3] @ d0<- vB 3930 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3931 and r9, r9, #15 @ r9<- A 3932 ftosizd s0, d0 @ s0<- op 3933 GET_INST_OPCODE(ip) @ extract opcode from rINST 3934 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3935 fsts s0, [r9] @ vA<- s0 3936 GOTO_OPCODE(ip) @ jump to next instruction 3937 3938 3939/* ------------------------------ */ 3940 .balign 64 3941.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3942/* File: armv6t2/OP_DOUBLE_TO_LONG.S */ 3943@include "armv6t2/unopWide.S" {"instr":"bl __aeabi_d2lz"} 3944/* File: armv6t2/unopWide.S */ 3945 /* 3946 * Generic 64-bit unary operation. Provide an "instr" line that 3947 * specifies an instruction that performs "result = op r0/r1". 3948 * This could be an ARM instruction or a function call. 3949 * 3950 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3951 */ 3952 /* unop vA, vB */ 3953 mov r3, rINST, lsr #12 @ r3<- B 3954 ubfx r9, rINST, #8, #4 @ r9<- A 3955 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3956 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3957 ldmia r3, {r0-r1} @ r0/r1<- vAA 3958 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3959 @ optional op; may set condition codes 3960 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 3961 GET_INST_OPCODE(ip) @ extract opcode from rINST 3962 stmia r9, {r0-r1} @ vAA<- r0/r1 3963 GOTO_OPCODE(ip) @ jump to next instruction 3964 /* 10-11 instructions */ 3965 3966 3967 3968 3969/* ------------------------------ */ 3970 .balign 64 3971.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3972/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */ 3973/* File: arm-vfp/funopNarrower.S */ 3974 /* 3975 * Generic 64bit-to-32bit unary floating point operation. Provide an 3976 * "instr" line that specifies an instruction that performs "s0 = op d0". 3977 * 3978 * For: double-to-int, double-to-float 3979 */ 3980 /* unop vA, vB */ 3981 mov r3, rINST, lsr #12 @ r3<- B 3982 mov r9, rINST, lsr #8 @ r9<- A+ 3983 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3984 fldd d0, [r3] @ d0<- vB 3985 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3986 and r9, r9, #15 @ r9<- A 3987 fcvtsd s0, d0 @ s0<- op 3988 GET_INST_OPCODE(ip) @ extract opcode from rINST 3989 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3990 fsts s0, [r9] @ vA<- s0 3991 GOTO_OPCODE(ip) @ jump to next instruction 3992 3993 3994/* ------------------------------ */ 3995 .balign 64 3996.L_OP_INT_TO_BYTE: /* 0x8d */ 3997/* File: armv6t2/OP_INT_TO_BYTE.S */ 3998/* File: armv6t2/unop.S */ 3999 /* 4000 * Generic 32-bit unary operation. Provide an "instr" line that 4001 * specifies an instruction that performs "result = op r0". 4002 * This could be an ARM instruction or a function call. 4003 * 4004 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4005 * int-to-byte, int-to-char, int-to-short 4006 */ 4007 /* unop vA, vB */ 4008 mov r3, rINST, lsr #12 @ r3<- B 4009 ubfx r9, rINST, #8, #4 @ r9<- A 4010 GET_VREG(r0, r3) @ r0<- vB 4011 @ optional op; may set condition codes 4012 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4013 sxtb r0, r0 @ r0<- op, r0-r3 changed 4014 GET_INST_OPCODE(ip) @ extract opcode from rINST 4015 SET_VREG(r0, r9) @ vAA<- r0 4016 GOTO_OPCODE(ip) @ jump to next instruction 4017 /* 8-9 instructions */ 4018 4019 4020/* ------------------------------ */ 4021 .balign 64 4022.L_OP_INT_TO_CHAR: /* 0x8e */ 4023/* File: armv6t2/OP_INT_TO_CHAR.S */ 4024/* File: armv6t2/unop.S */ 4025 /* 4026 * Generic 32-bit unary operation. Provide an "instr" line that 4027 * specifies an instruction that performs "result = op r0". 4028 * This could be an ARM instruction or a function call. 4029 * 4030 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4031 * int-to-byte, int-to-char, int-to-short 4032 */ 4033 /* unop vA, vB */ 4034 mov r3, rINST, lsr #12 @ r3<- B 4035 ubfx r9, rINST, #8, #4 @ r9<- A 4036 GET_VREG(r0, r3) @ r0<- vB 4037 @ optional op; may set condition codes 4038 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4039 uxth r0, r0 @ r0<- op, r0-r3 changed 4040 GET_INST_OPCODE(ip) @ extract opcode from rINST 4041 SET_VREG(r0, r9) @ vAA<- r0 4042 GOTO_OPCODE(ip) @ jump to next instruction 4043 /* 8-9 instructions */ 4044 4045 4046/* ------------------------------ */ 4047 .balign 64 4048.L_OP_INT_TO_SHORT: /* 0x8f */ 4049/* File: armv6t2/OP_INT_TO_SHORT.S */ 4050/* File: armv6t2/unop.S */ 4051 /* 4052 * Generic 32-bit unary operation. Provide an "instr" line that 4053 * specifies an instruction that performs "result = op r0". 4054 * This could be an ARM instruction or a function call. 4055 * 4056 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4057 * int-to-byte, int-to-char, int-to-short 4058 */ 4059 /* unop vA, vB */ 4060 mov r3, rINST, lsr #12 @ r3<- B 4061 ubfx r9, rINST, #8, #4 @ r9<- A 4062 GET_VREG(r0, r3) @ r0<- vB 4063 @ optional op; may set condition codes 4064 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4065 sxth r0, r0 @ r0<- op, r0-r3 changed 4066 GET_INST_OPCODE(ip) @ extract opcode from rINST 4067 SET_VREG(r0, r9) @ vAA<- r0 4068 GOTO_OPCODE(ip) @ jump to next instruction 4069 /* 8-9 instructions */ 4070 4071 4072/* ------------------------------ */ 4073 .balign 64 4074.L_OP_ADD_INT: /* 0x90 */ 4075/* File: armv5te/OP_ADD_INT.S */ 4076/* File: armv5te/binop.S */ 4077 /* 4078 * Generic 32-bit binary operation. Provide an "instr" line that 4079 * specifies an instruction that performs "result = r0 op r1". 4080 * This could be an ARM instruction or a function call. (If the result 4081 * comes back in a register other than r0, you can override "result".) 4082 * 4083 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4084 * vCC (r1). Useful for integer division and modulus. Note that we 4085 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4086 * handles it correctly. 4087 * 4088 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4089 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4090 * mul-float, div-float, rem-float 4091 */ 4092 /* binop vAA, vBB, vCC */ 4093 FETCH(r0, 1) @ r0<- CCBB 4094 mov r9, rINST, lsr #8 @ r9<- AA 4095 mov r3, r0, lsr #8 @ r3<- CC 4096 and r2, r0, #255 @ r2<- BB 4097 GET_VREG(r1, r3) @ r1<- vCC 4098 GET_VREG(r0, r2) @ r0<- vBB 4099 .if 0 4100 cmp r1, #0 @ is second operand zero? 4101 beq common_errDivideByZero 4102 .endif 4103 4104 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4105 @ optional op; may set condition codes 4106 add r0, r0, r1 @ r0<- op, r0-r3 changed 4107 GET_INST_OPCODE(ip) @ extract opcode from rINST 4108 SET_VREG(r0, r9) @ vAA<- r0 4109 GOTO_OPCODE(ip) @ jump to next instruction 4110 /* 11-14 instructions */ 4111 4112 4113 4114/* ------------------------------ */ 4115 .balign 64 4116.L_OP_SUB_INT: /* 0x91 */ 4117/* File: armv5te/OP_SUB_INT.S */ 4118/* File: armv5te/binop.S */ 4119 /* 4120 * Generic 32-bit binary operation. Provide an "instr" line that 4121 * specifies an instruction that performs "result = r0 op r1". 4122 * This could be an ARM instruction or a function call. (If the result 4123 * comes back in a register other than r0, you can override "result".) 4124 * 4125 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4126 * vCC (r1). Useful for integer division and modulus. Note that we 4127 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4128 * handles it correctly. 4129 * 4130 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4131 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4132 * mul-float, div-float, rem-float 4133 */ 4134 /* binop vAA, vBB, vCC */ 4135 FETCH(r0, 1) @ r0<- CCBB 4136 mov r9, rINST, lsr #8 @ r9<- AA 4137 mov r3, r0, lsr #8 @ r3<- CC 4138 and r2, r0, #255 @ r2<- BB 4139 GET_VREG(r1, r3) @ r1<- vCC 4140 GET_VREG(r0, r2) @ r0<- vBB 4141 .if 0 4142 cmp r1, #0 @ is second operand zero? 4143 beq common_errDivideByZero 4144 .endif 4145 4146 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4147 @ optional op; may set condition codes 4148 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4149 GET_INST_OPCODE(ip) @ extract opcode from rINST 4150 SET_VREG(r0, r9) @ vAA<- r0 4151 GOTO_OPCODE(ip) @ jump to next instruction 4152 /* 11-14 instructions */ 4153 4154 4155 4156/* ------------------------------ */ 4157 .balign 64 4158.L_OP_MUL_INT: /* 0x92 */ 4159/* File: armv5te/OP_MUL_INT.S */ 4160/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4161/* File: armv5te/binop.S */ 4162 /* 4163 * Generic 32-bit binary operation. Provide an "instr" line that 4164 * specifies an instruction that performs "result = r0 op r1". 4165 * This could be an ARM instruction or a function call. (If the result 4166 * comes back in a register other than r0, you can override "result".) 4167 * 4168 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4169 * vCC (r1). Useful for integer division and modulus. Note that we 4170 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4171 * handles it correctly. 4172 * 4173 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4174 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4175 * mul-float, div-float, rem-float 4176 */ 4177 /* binop vAA, vBB, vCC */ 4178 FETCH(r0, 1) @ r0<- CCBB 4179 mov r9, rINST, lsr #8 @ r9<- AA 4180 mov r3, r0, lsr #8 @ r3<- CC 4181 and r2, r0, #255 @ r2<- BB 4182 GET_VREG(r1, r3) @ r1<- vCC 4183 GET_VREG(r0, r2) @ r0<- vBB 4184 .if 0 4185 cmp r1, #0 @ is second operand zero? 4186 beq common_errDivideByZero 4187 .endif 4188 4189 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4190 @ optional op; may set condition codes 4191 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4192 GET_INST_OPCODE(ip) @ extract opcode from rINST 4193 SET_VREG(r0, r9) @ vAA<- r0 4194 GOTO_OPCODE(ip) @ jump to next instruction 4195 /* 11-14 instructions */ 4196 4197 4198 4199/* ------------------------------ */ 4200 .balign 64 4201.L_OP_DIV_INT: /* 0x93 */ 4202/* File: armv5te/OP_DIV_INT.S */ 4203/* File: armv5te/binop.S */ 4204 /* 4205 * Generic 32-bit binary operation. Provide an "instr" line that 4206 * specifies an instruction that performs "result = r0 op r1". 4207 * This could be an ARM instruction or a function call. (If the result 4208 * comes back in a register other than r0, you can override "result".) 4209 * 4210 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4211 * vCC (r1). Useful for integer division and modulus. Note that we 4212 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4213 * handles it correctly. 4214 * 4215 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4216 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4217 * mul-float, div-float, rem-float 4218 */ 4219 /* binop vAA, vBB, vCC */ 4220 FETCH(r0, 1) @ r0<- CCBB 4221 mov r9, rINST, lsr #8 @ r9<- AA 4222 mov r3, r0, lsr #8 @ r3<- CC 4223 and r2, r0, #255 @ r2<- BB 4224 GET_VREG(r1, r3) @ r1<- vCC 4225 GET_VREG(r0, r2) @ r0<- vBB 4226 .if 1 4227 cmp r1, #0 @ is second operand zero? 4228 beq common_errDivideByZero 4229 .endif 4230 4231 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4232 @ optional op; may set condition codes 4233 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4234 GET_INST_OPCODE(ip) @ extract opcode from rINST 4235 SET_VREG(r0, r9) @ vAA<- r0 4236 GOTO_OPCODE(ip) @ jump to next instruction 4237 /* 11-14 instructions */ 4238 4239 4240 4241/* ------------------------------ */ 4242 .balign 64 4243.L_OP_REM_INT: /* 0x94 */ 4244/* File: armv5te/OP_REM_INT.S */ 4245/* idivmod returns quotient in r0 and remainder in r1 */ 4246/* File: armv5te/binop.S */ 4247 /* 4248 * Generic 32-bit binary operation. Provide an "instr" line that 4249 * specifies an instruction that performs "result = r0 op r1". 4250 * This could be an ARM instruction or a function call. (If the result 4251 * comes back in a register other than r0, you can override "result".) 4252 * 4253 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4254 * vCC (r1). Useful for integer division and modulus. Note that we 4255 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4256 * handles it correctly. 4257 * 4258 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4259 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4260 * mul-float, div-float, rem-float 4261 */ 4262 /* binop vAA, vBB, vCC */ 4263 FETCH(r0, 1) @ r0<- CCBB 4264 mov r9, rINST, lsr #8 @ r9<- AA 4265 mov r3, r0, lsr #8 @ r3<- CC 4266 and r2, r0, #255 @ r2<- BB 4267 GET_VREG(r1, r3) @ r1<- vCC 4268 GET_VREG(r0, r2) @ r0<- vBB 4269 .if 1 4270 cmp r1, #0 @ is second operand zero? 4271 beq common_errDivideByZero 4272 .endif 4273 4274 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4275 @ optional op; may set condition codes 4276 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4277 GET_INST_OPCODE(ip) @ extract opcode from rINST 4278 SET_VREG(r1, r9) @ vAA<- r1 4279 GOTO_OPCODE(ip) @ jump to next instruction 4280 /* 11-14 instructions */ 4281 4282 4283 4284/* ------------------------------ */ 4285 .balign 64 4286.L_OP_AND_INT: /* 0x95 */ 4287/* File: armv5te/OP_AND_INT.S */ 4288/* File: armv5te/binop.S */ 4289 /* 4290 * Generic 32-bit binary operation. Provide an "instr" line that 4291 * specifies an instruction that performs "result = r0 op r1". 4292 * This could be an ARM instruction or a function call. (If the result 4293 * comes back in a register other than r0, you can override "result".) 4294 * 4295 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4296 * vCC (r1). Useful for integer division and modulus. Note that we 4297 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4298 * handles it correctly. 4299 * 4300 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4301 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4302 * mul-float, div-float, rem-float 4303 */ 4304 /* binop vAA, vBB, vCC */ 4305 FETCH(r0, 1) @ r0<- CCBB 4306 mov r9, rINST, lsr #8 @ r9<- AA 4307 mov r3, r0, lsr #8 @ r3<- CC 4308 and r2, r0, #255 @ r2<- BB 4309 GET_VREG(r1, r3) @ r1<- vCC 4310 GET_VREG(r0, r2) @ r0<- vBB 4311 .if 0 4312 cmp r1, #0 @ is second operand zero? 4313 beq common_errDivideByZero 4314 .endif 4315 4316 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4317 @ optional op; may set condition codes 4318 and r0, r0, r1 @ r0<- op, r0-r3 changed 4319 GET_INST_OPCODE(ip) @ extract opcode from rINST 4320 SET_VREG(r0, r9) @ vAA<- r0 4321 GOTO_OPCODE(ip) @ jump to next instruction 4322 /* 11-14 instructions */ 4323 4324 4325 4326/* ------------------------------ */ 4327 .balign 64 4328.L_OP_OR_INT: /* 0x96 */ 4329/* File: armv5te/OP_OR_INT.S */ 4330/* File: armv5te/binop.S */ 4331 /* 4332 * Generic 32-bit binary operation. Provide an "instr" line that 4333 * specifies an instruction that performs "result = r0 op r1". 4334 * This could be an ARM instruction or a function call. (If the result 4335 * comes back in a register other than r0, you can override "result".) 4336 * 4337 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4338 * vCC (r1). Useful for integer division and modulus. Note that we 4339 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4340 * handles it correctly. 4341 * 4342 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4343 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4344 * mul-float, div-float, rem-float 4345 */ 4346 /* binop vAA, vBB, vCC */ 4347 FETCH(r0, 1) @ r0<- CCBB 4348 mov r9, rINST, lsr #8 @ r9<- AA 4349 mov r3, r0, lsr #8 @ r3<- CC 4350 and r2, r0, #255 @ r2<- BB 4351 GET_VREG(r1, r3) @ r1<- vCC 4352 GET_VREG(r0, r2) @ r0<- vBB 4353 .if 0 4354 cmp r1, #0 @ is second operand zero? 4355 beq common_errDivideByZero 4356 .endif 4357 4358 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4359 @ optional op; may set condition codes 4360 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4361 GET_INST_OPCODE(ip) @ extract opcode from rINST 4362 SET_VREG(r0, r9) @ vAA<- r0 4363 GOTO_OPCODE(ip) @ jump to next instruction 4364 /* 11-14 instructions */ 4365 4366 4367 4368/* ------------------------------ */ 4369 .balign 64 4370.L_OP_XOR_INT: /* 0x97 */ 4371/* File: armv5te/OP_XOR_INT.S */ 4372/* File: armv5te/binop.S */ 4373 /* 4374 * Generic 32-bit binary operation. Provide an "instr" line that 4375 * specifies an instruction that performs "result = r0 op r1". 4376 * This could be an ARM instruction or a function call. (If the result 4377 * comes back in a register other than r0, you can override "result".) 4378 * 4379 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4380 * vCC (r1). Useful for integer division and modulus. Note that we 4381 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4382 * handles it correctly. 4383 * 4384 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4385 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4386 * mul-float, div-float, rem-float 4387 */ 4388 /* binop vAA, vBB, vCC */ 4389 FETCH(r0, 1) @ r0<- CCBB 4390 mov r9, rINST, lsr #8 @ r9<- AA 4391 mov r3, r0, lsr #8 @ r3<- CC 4392 and r2, r0, #255 @ r2<- BB 4393 GET_VREG(r1, r3) @ r1<- vCC 4394 GET_VREG(r0, r2) @ r0<- vBB 4395 .if 0 4396 cmp r1, #0 @ is second operand zero? 4397 beq common_errDivideByZero 4398 .endif 4399 4400 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4401 @ optional op; may set condition codes 4402 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4403 GET_INST_OPCODE(ip) @ extract opcode from rINST 4404 SET_VREG(r0, r9) @ vAA<- r0 4405 GOTO_OPCODE(ip) @ jump to next instruction 4406 /* 11-14 instructions */ 4407 4408 4409 4410/* ------------------------------ */ 4411 .balign 64 4412.L_OP_SHL_INT: /* 0x98 */ 4413/* File: armv5te/OP_SHL_INT.S */ 4414/* File: armv5te/binop.S */ 4415 /* 4416 * Generic 32-bit binary operation. Provide an "instr" line that 4417 * specifies an instruction that performs "result = r0 op r1". 4418 * This could be an ARM instruction or a function call. (If the result 4419 * comes back in a register other than r0, you can override "result".) 4420 * 4421 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4422 * vCC (r1). Useful for integer division and modulus. Note that we 4423 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4424 * handles it correctly. 4425 * 4426 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4427 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4428 * mul-float, div-float, rem-float 4429 */ 4430 /* binop vAA, vBB, vCC */ 4431 FETCH(r0, 1) @ r0<- CCBB 4432 mov r9, rINST, lsr #8 @ r9<- AA 4433 mov r3, r0, lsr #8 @ r3<- CC 4434 and r2, r0, #255 @ r2<- BB 4435 GET_VREG(r1, r3) @ r1<- vCC 4436 GET_VREG(r0, r2) @ r0<- vBB 4437 .if 0 4438 cmp r1, #0 @ is second operand zero? 4439 beq common_errDivideByZero 4440 .endif 4441 4442 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4443 and r1, r1, #31 @ optional op; may set condition codes 4444 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4445 GET_INST_OPCODE(ip) @ extract opcode from rINST 4446 SET_VREG(r0, r9) @ vAA<- r0 4447 GOTO_OPCODE(ip) @ jump to next instruction 4448 /* 11-14 instructions */ 4449 4450 4451 4452/* ------------------------------ */ 4453 .balign 64 4454.L_OP_SHR_INT: /* 0x99 */ 4455/* File: armv5te/OP_SHR_INT.S */ 4456/* File: armv5te/binop.S */ 4457 /* 4458 * Generic 32-bit binary operation. Provide an "instr" line that 4459 * specifies an instruction that performs "result = r0 op r1". 4460 * This could be an ARM instruction or a function call. (If the result 4461 * comes back in a register other than r0, you can override "result".) 4462 * 4463 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4464 * vCC (r1). Useful for integer division and modulus. Note that we 4465 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4466 * handles it correctly. 4467 * 4468 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4469 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4470 * mul-float, div-float, rem-float 4471 */ 4472 /* binop vAA, vBB, vCC */ 4473 FETCH(r0, 1) @ r0<- CCBB 4474 mov r9, rINST, lsr #8 @ r9<- AA 4475 mov r3, r0, lsr #8 @ r3<- CC 4476 and r2, r0, #255 @ r2<- BB 4477 GET_VREG(r1, r3) @ r1<- vCC 4478 GET_VREG(r0, r2) @ r0<- vBB 4479 .if 0 4480 cmp r1, #0 @ is second operand zero? 4481 beq common_errDivideByZero 4482 .endif 4483 4484 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4485 and r1, r1, #31 @ optional op; may set condition codes 4486 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4487 GET_INST_OPCODE(ip) @ extract opcode from rINST 4488 SET_VREG(r0, r9) @ vAA<- r0 4489 GOTO_OPCODE(ip) @ jump to next instruction 4490 /* 11-14 instructions */ 4491 4492 4493 4494/* ------------------------------ */ 4495 .balign 64 4496.L_OP_USHR_INT: /* 0x9a */ 4497/* File: armv5te/OP_USHR_INT.S */ 4498/* File: armv5te/binop.S */ 4499 /* 4500 * Generic 32-bit binary operation. Provide an "instr" line that 4501 * specifies an instruction that performs "result = r0 op r1". 4502 * This could be an ARM instruction or a function call. (If the result 4503 * comes back in a register other than r0, you can override "result".) 4504 * 4505 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4506 * vCC (r1). Useful for integer division and modulus. Note that we 4507 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4508 * handles it correctly. 4509 * 4510 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4511 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4512 * mul-float, div-float, rem-float 4513 */ 4514 /* binop vAA, vBB, vCC */ 4515 FETCH(r0, 1) @ r0<- CCBB 4516 mov r9, rINST, lsr #8 @ r9<- AA 4517 mov r3, r0, lsr #8 @ r3<- CC 4518 and r2, r0, #255 @ r2<- BB 4519 GET_VREG(r1, r3) @ r1<- vCC 4520 GET_VREG(r0, r2) @ r0<- vBB 4521 .if 0 4522 cmp r1, #0 @ is second operand zero? 4523 beq common_errDivideByZero 4524 .endif 4525 4526 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4527 and r1, r1, #31 @ optional op; may set condition codes 4528 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4529 GET_INST_OPCODE(ip) @ extract opcode from rINST 4530 SET_VREG(r0, r9) @ vAA<- r0 4531 GOTO_OPCODE(ip) @ jump to next instruction 4532 /* 11-14 instructions */ 4533 4534 4535 4536/* ------------------------------ */ 4537 .balign 64 4538.L_OP_ADD_LONG: /* 0x9b */ 4539/* File: armv5te/OP_ADD_LONG.S */ 4540/* File: armv5te/binopWide.S */ 4541 /* 4542 * Generic 64-bit binary operation. Provide an "instr" line that 4543 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4544 * This could be an ARM instruction or a function call. (If the result 4545 * comes back in a register other than r0, you can override "result".) 4546 * 4547 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4548 * vCC (r1). Useful for integer division and modulus. 4549 * 4550 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4551 * xor-long, add-double, sub-double, mul-double, div-double, 4552 * rem-double 4553 * 4554 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4555 */ 4556 /* binop vAA, vBB, vCC */ 4557 FETCH(r0, 1) @ r0<- CCBB 4558 mov r9, rINST, lsr #8 @ r9<- AA 4559 and r2, r0, #255 @ r2<- BB 4560 mov r3, r0, lsr #8 @ r3<- CC 4561 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4562 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4563 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4564 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4565 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4566 .if 0 4567 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4568 beq common_errDivideByZero 4569 .endif 4570 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4571 4572 adds r0, r0, r2 @ optional op; may set condition codes 4573 adc r1, r1, r3 @ result<- op, r0-r3 changed 4574 GET_INST_OPCODE(ip) @ extract opcode from rINST 4575 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4576 GOTO_OPCODE(ip) @ jump to next instruction 4577 /* 14-17 instructions */ 4578 4579 4580 4581/* ------------------------------ */ 4582 .balign 64 4583.L_OP_SUB_LONG: /* 0x9c */ 4584/* File: armv5te/OP_SUB_LONG.S */ 4585/* File: armv5te/binopWide.S */ 4586 /* 4587 * Generic 64-bit binary operation. Provide an "instr" line that 4588 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4589 * This could be an ARM instruction or a function call. (If the result 4590 * comes back in a register other than r0, you can override "result".) 4591 * 4592 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4593 * vCC (r1). Useful for integer division and modulus. 4594 * 4595 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4596 * xor-long, add-double, sub-double, mul-double, div-double, 4597 * rem-double 4598 * 4599 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4600 */ 4601 /* binop vAA, vBB, vCC */ 4602 FETCH(r0, 1) @ r0<- CCBB 4603 mov r9, rINST, lsr #8 @ r9<- AA 4604 and r2, r0, #255 @ r2<- BB 4605 mov r3, r0, lsr #8 @ r3<- CC 4606 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4607 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4608 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4609 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4610 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4611 .if 0 4612 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4613 beq common_errDivideByZero 4614 .endif 4615 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4616 4617 subs r0, r0, r2 @ optional op; may set condition codes 4618 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4619 GET_INST_OPCODE(ip) @ extract opcode from rINST 4620 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4621 GOTO_OPCODE(ip) @ jump to next instruction 4622 /* 14-17 instructions */ 4623 4624 4625 4626/* ------------------------------ */ 4627 .balign 64 4628.L_OP_MUL_LONG: /* 0x9d */ 4629/* File: armv5te/OP_MUL_LONG.S */ 4630 /* 4631 * Signed 64-bit integer multiply. 4632 * 4633 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4634 * WX 4635 * x YZ 4636 * -------- 4637 * ZW ZX 4638 * YW YX 4639 * 4640 * The low word of the result holds ZX, the high word holds 4641 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4642 * it doesn't fit in the low 64 bits. 4643 * 4644 * Unlike most ARM math operations, multiply instructions have 4645 * restrictions on using the same register more than once (Rd and Rm 4646 * cannot be the same). 4647 */ 4648 /* mul-long vAA, vBB, vCC */ 4649 FETCH(r0, 1) @ r0<- CCBB 4650 and r2, r0, #255 @ r2<- BB 4651 mov r3, r0, lsr #8 @ r3<- CC 4652 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4653 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4654 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4655 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4656 mul ip, r2, r1 @ ip<- ZxW 4657 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4658 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4659 mov r0, rINST, lsr #8 @ r0<- AA 4660 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4661 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4662 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4663 b .LOP_MUL_LONG_finish 4664 4665/* ------------------------------ */ 4666 .balign 64 4667.L_OP_DIV_LONG: /* 0x9e */ 4668/* File: armv5te/OP_DIV_LONG.S */ 4669/* File: armv5te/binopWide.S */ 4670 /* 4671 * Generic 64-bit binary operation. Provide an "instr" line that 4672 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4673 * This could be an ARM instruction or a function call. (If the result 4674 * comes back in a register other than r0, you can override "result".) 4675 * 4676 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4677 * vCC (r1). Useful for integer division and modulus. 4678 * 4679 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4680 * xor-long, add-double, sub-double, mul-double, div-double, 4681 * rem-double 4682 * 4683 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4684 */ 4685 /* binop vAA, vBB, vCC */ 4686 FETCH(r0, 1) @ r0<- CCBB 4687 mov r9, rINST, lsr #8 @ r9<- AA 4688 and r2, r0, #255 @ r2<- BB 4689 mov r3, r0, lsr #8 @ r3<- CC 4690 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4691 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4692 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4693 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4694 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4695 .if 1 4696 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4697 beq common_errDivideByZero 4698 .endif 4699 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4700 4701 @ optional op; may set condition codes 4702 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4703 GET_INST_OPCODE(ip) @ extract opcode from rINST 4704 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4705 GOTO_OPCODE(ip) @ jump to next instruction 4706 /* 14-17 instructions */ 4707 4708 4709 4710/* ------------------------------ */ 4711 .balign 64 4712.L_OP_REM_LONG: /* 0x9f */ 4713/* File: armv5te/OP_REM_LONG.S */ 4714/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4715/* File: armv5te/binopWide.S */ 4716 /* 4717 * Generic 64-bit binary operation. Provide an "instr" line that 4718 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4719 * This could be an ARM instruction or a function call. (If the result 4720 * comes back in a register other than r0, you can override "result".) 4721 * 4722 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4723 * vCC (r1). Useful for integer division and modulus. 4724 * 4725 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4726 * xor-long, add-double, sub-double, mul-double, div-double, 4727 * rem-double 4728 * 4729 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4730 */ 4731 /* binop vAA, vBB, vCC */ 4732 FETCH(r0, 1) @ r0<- CCBB 4733 mov r9, rINST, lsr #8 @ r9<- AA 4734 and r2, r0, #255 @ r2<- BB 4735 mov r3, r0, lsr #8 @ r3<- CC 4736 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4737 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4738 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4739 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4740 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4741 .if 1 4742 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4743 beq common_errDivideByZero 4744 .endif 4745 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4746 4747 @ optional op; may set condition codes 4748 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4749 GET_INST_OPCODE(ip) @ extract opcode from rINST 4750 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4751 GOTO_OPCODE(ip) @ jump to next instruction 4752 /* 14-17 instructions */ 4753 4754 4755 4756/* ------------------------------ */ 4757 .balign 64 4758.L_OP_AND_LONG: /* 0xa0 */ 4759/* File: armv5te/OP_AND_LONG.S */ 4760/* File: armv5te/binopWide.S */ 4761 /* 4762 * Generic 64-bit binary operation. Provide an "instr" line that 4763 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4764 * This could be an ARM instruction or a function call. (If the result 4765 * comes back in a register other than r0, you can override "result".) 4766 * 4767 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4768 * vCC (r1). Useful for integer division and modulus. 4769 * 4770 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4771 * xor-long, add-double, sub-double, mul-double, div-double, 4772 * rem-double 4773 * 4774 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4775 */ 4776 /* binop vAA, vBB, vCC */ 4777 FETCH(r0, 1) @ r0<- CCBB 4778 mov r9, rINST, lsr #8 @ r9<- AA 4779 and r2, r0, #255 @ r2<- BB 4780 mov r3, r0, lsr #8 @ r3<- CC 4781 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4782 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4783 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4784 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4785 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4786 .if 0 4787 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4788 beq common_errDivideByZero 4789 .endif 4790 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4791 4792 and r0, r0, r2 @ optional op; may set condition codes 4793 and r1, r1, r3 @ result<- op, r0-r3 changed 4794 GET_INST_OPCODE(ip) @ extract opcode from rINST 4795 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4796 GOTO_OPCODE(ip) @ jump to next instruction 4797 /* 14-17 instructions */ 4798 4799 4800 4801/* ------------------------------ */ 4802 .balign 64 4803.L_OP_OR_LONG: /* 0xa1 */ 4804/* File: armv5te/OP_OR_LONG.S */ 4805/* File: armv5te/binopWide.S */ 4806 /* 4807 * Generic 64-bit binary operation. Provide an "instr" line that 4808 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4809 * This could be an ARM instruction or a function call. (If the result 4810 * comes back in a register other than r0, you can override "result".) 4811 * 4812 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4813 * vCC (r1). Useful for integer division and modulus. 4814 * 4815 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4816 * xor-long, add-double, sub-double, mul-double, div-double, 4817 * rem-double 4818 * 4819 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4820 */ 4821 /* binop vAA, vBB, vCC */ 4822 FETCH(r0, 1) @ r0<- CCBB 4823 mov r9, rINST, lsr #8 @ r9<- AA 4824 and r2, r0, #255 @ r2<- BB 4825 mov r3, r0, lsr #8 @ r3<- CC 4826 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4827 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4828 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4829 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4830 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4831 .if 0 4832 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4833 beq common_errDivideByZero 4834 .endif 4835 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4836 4837 orr r0, r0, r2 @ optional op; may set condition codes 4838 orr r1, r1, r3 @ result<- op, r0-r3 changed 4839 GET_INST_OPCODE(ip) @ extract opcode from rINST 4840 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4841 GOTO_OPCODE(ip) @ jump to next instruction 4842 /* 14-17 instructions */ 4843 4844 4845 4846/* ------------------------------ */ 4847 .balign 64 4848.L_OP_XOR_LONG: /* 0xa2 */ 4849/* File: armv5te/OP_XOR_LONG.S */ 4850/* File: armv5te/binopWide.S */ 4851 /* 4852 * Generic 64-bit binary operation. Provide an "instr" line that 4853 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4854 * This could be an ARM instruction or a function call. (If the result 4855 * comes back in a register other than r0, you can override "result".) 4856 * 4857 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4858 * vCC (r1). Useful for integer division and modulus. 4859 * 4860 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4861 * xor-long, add-double, sub-double, mul-double, div-double, 4862 * rem-double 4863 * 4864 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4865 */ 4866 /* binop vAA, vBB, vCC */ 4867 FETCH(r0, 1) @ r0<- CCBB 4868 mov r9, rINST, lsr #8 @ r9<- AA 4869 and r2, r0, #255 @ r2<- BB 4870 mov r3, r0, lsr #8 @ r3<- CC 4871 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4872 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4873 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4874 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4875 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4876 .if 0 4877 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4878 beq common_errDivideByZero 4879 .endif 4880 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4881 4882 eor r0, r0, r2 @ optional op; may set condition codes 4883 eor r1, r1, r3 @ result<- op, r0-r3 changed 4884 GET_INST_OPCODE(ip) @ extract opcode from rINST 4885 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4886 GOTO_OPCODE(ip) @ jump to next instruction 4887 /* 14-17 instructions */ 4888 4889 4890 4891/* ------------------------------ */ 4892 .balign 64 4893.L_OP_SHL_LONG: /* 0xa3 */ 4894/* File: armv5te/OP_SHL_LONG.S */ 4895 /* 4896 * Long integer shift. This is different from the generic 32/64-bit 4897 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4898 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4899 * 6 bits of the shift distance. 4900 */ 4901 /* shl-long vAA, vBB, vCC */ 4902 FETCH(r0, 1) @ r0<- CCBB 4903 mov r9, rINST, lsr #8 @ r9<- AA 4904 and r3, r0, #255 @ r3<- BB 4905 mov r0, r0, lsr #8 @ r0<- CC 4906 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4907 GET_VREG(r2, r0) @ r2<- vCC 4908 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4909 and r2, r2, #63 @ r2<- r2 & 0x3f 4910 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4911 4912 mov r1, r1, asl r2 @ r1<- r1 << r2 4913 rsb r3, r2, #32 @ r3<- 32 - r2 4914 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 4915 subs ip, r2, #32 @ ip<- r2 - 32 4916 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 4917 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4918 b .LOP_SHL_LONG_finish 4919 4920/* ------------------------------ */ 4921 .balign 64 4922.L_OP_SHR_LONG: /* 0xa4 */ 4923/* File: armv5te/OP_SHR_LONG.S */ 4924 /* 4925 * Long integer shift. This is different from the generic 32/64-bit 4926 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4927 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4928 * 6 bits of the shift distance. 4929 */ 4930 /* shr-long vAA, vBB, vCC */ 4931 FETCH(r0, 1) @ r0<- CCBB 4932 mov r9, rINST, lsr #8 @ r9<- AA 4933 and r3, r0, #255 @ r3<- BB 4934 mov r0, r0, lsr #8 @ r0<- CC 4935 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4936 GET_VREG(r2, r0) @ r2<- vCC 4937 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4938 and r2, r2, #63 @ r0<- r0 & 0x3f 4939 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4940 4941 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4942 rsb r3, r2, #32 @ r3<- 32 - r2 4943 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4944 subs ip, r2, #32 @ ip<- r2 - 32 4945 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 4946 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4947 b .LOP_SHR_LONG_finish 4948 4949/* ------------------------------ */ 4950 .balign 64 4951.L_OP_USHR_LONG: /* 0xa5 */ 4952/* File: armv5te/OP_USHR_LONG.S */ 4953 /* 4954 * Long integer shift. This is different from the generic 32/64-bit 4955 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4956 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4957 * 6 bits of the shift distance. 4958 */ 4959 /* ushr-long vAA, vBB, vCC */ 4960 FETCH(r0, 1) @ r0<- CCBB 4961 mov r9, rINST, lsr #8 @ r9<- AA 4962 and r3, r0, #255 @ r3<- BB 4963 mov r0, r0, lsr #8 @ r0<- CC 4964 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4965 GET_VREG(r2, r0) @ r2<- vCC 4966 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4967 and r2, r2, #63 @ r0<- r0 & 0x3f 4968 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4969 4970 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4971 rsb r3, r2, #32 @ r3<- 32 - r2 4972 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4973 subs ip, r2, #32 @ ip<- r2 - 32 4974 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 4975 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4976 b .LOP_USHR_LONG_finish 4977 4978/* ------------------------------ */ 4979 .balign 64 4980.L_OP_ADD_FLOAT: /* 0xa6 */ 4981/* File: arm-vfp/OP_ADD_FLOAT.S */ 4982/* File: arm-vfp/fbinop.S */ 4983 /* 4984 * Generic 32-bit floating-point operation. Provide an "instr" line that 4985 * specifies an instruction that performs "s2 = s0 op s1". Because we 4986 * use the "softfp" ABI, this must be an instruction, not a function call. 4987 * 4988 * For: add-float, sub-float, mul-float, div-float 4989 */ 4990 /* floatop vAA, vBB, vCC */ 4991 FETCH(r0, 1) @ r0<- CCBB 4992 mov r9, rINST, lsr #8 @ r9<- AA 4993 mov r3, r0, lsr #8 @ r3<- CC 4994 and r2, r0, #255 @ r2<- BB 4995 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4996 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4997 flds s1, [r3] @ s1<- vCC 4998 flds s0, [r2] @ s0<- vBB 4999 5000 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5001 fadds s2, s0, s1 @ s2<- op 5002 GET_INST_OPCODE(ip) @ extract opcode from rINST 5003 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5004 fsts s2, [r9] @ vAA<- s2 5005 GOTO_OPCODE(ip) @ jump to next instruction 5006 5007 5008/* ------------------------------ */ 5009 .balign 64 5010.L_OP_SUB_FLOAT: /* 0xa7 */ 5011/* File: arm-vfp/OP_SUB_FLOAT.S */ 5012/* File: arm-vfp/fbinop.S */ 5013 /* 5014 * Generic 32-bit floating-point operation. Provide an "instr" line that 5015 * specifies an instruction that performs "s2 = s0 op s1". Because we 5016 * use the "softfp" ABI, this must be an instruction, not a function call. 5017 * 5018 * For: add-float, sub-float, mul-float, div-float 5019 */ 5020 /* floatop vAA, vBB, vCC */ 5021 FETCH(r0, 1) @ r0<- CCBB 5022 mov r9, rINST, lsr #8 @ r9<- AA 5023 mov r3, r0, lsr #8 @ r3<- CC 5024 and r2, r0, #255 @ r2<- BB 5025 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5026 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5027 flds s1, [r3] @ s1<- vCC 5028 flds s0, [r2] @ s0<- vBB 5029 5030 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5031 fsubs s2, s0, s1 @ s2<- op 5032 GET_INST_OPCODE(ip) @ extract opcode from rINST 5033 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5034 fsts s2, [r9] @ vAA<- s2 5035 GOTO_OPCODE(ip) @ jump to next instruction 5036 5037 5038/* ------------------------------ */ 5039 .balign 64 5040.L_OP_MUL_FLOAT: /* 0xa8 */ 5041/* File: arm-vfp/OP_MUL_FLOAT.S */ 5042/* File: arm-vfp/fbinop.S */ 5043 /* 5044 * Generic 32-bit floating-point operation. Provide an "instr" line that 5045 * specifies an instruction that performs "s2 = s0 op s1". Because we 5046 * use the "softfp" ABI, this must be an instruction, not a function call. 5047 * 5048 * For: add-float, sub-float, mul-float, div-float 5049 */ 5050 /* floatop vAA, vBB, vCC */ 5051 FETCH(r0, 1) @ r0<- CCBB 5052 mov r9, rINST, lsr #8 @ r9<- AA 5053 mov r3, r0, lsr #8 @ r3<- CC 5054 and r2, r0, #255 @ r2<- BB 5055 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5056 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5057 flds s1, [r3] @ s1<- vCC 5058 flds s0, [r2] @ s0<- vBB 5059 5060 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5061 fmuls s2, s0, s1 @ s2<- op 5062 GET_INST_OPCODE(ip) @ extract opcode from rINST 5063 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5064 fsts s2, [r9] @ vAA<- s2 5065 GOTO_OPCODE(ip) @ jump to next instruction 5066 5067 5068/* ------------------------------ */ 5069 .balign 64 5070.L_OP_DIV_FLOAT: /* 0xa9 */ 5071/* File: arm-vfp/OP_DIV_FLOAT.S */ 5072/* File: arm-vfp/fbinop.S */ 5073 /* 5074 * Generic 32-bit floating-point operation. Provide an "instr" line that 5075 * specifies an instruction that performs "s2 = s0 op s1". Because we 5076 * use the "softfp" ABI, this must be an instruction, not a function call. 5077 * 5078 * For: add-float, sub-float, mul-float, div-float 5079 */ 5080 /* floatop vAA, vBB, vCC */ 5081 FETCH(r0, 1) @ r0<- CCBB 5082 mov r9, rINST, lsr #8 @ r9<- AA 5083 mov r3, r0, lsr #8 @ r3<- CC 5084 and r2, r0, #255 @ r2<- BB 5085 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5086 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5087 flds s1, [r3] @ s1<- vCC 5088 flds s0, [r2] @ s0<- vBB 5089 5090 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5091 fdivs s2, s0, s1 @ s2<- op 5092 GET_INST_OPCODE(ip) @ extract opcode from rINST 5093 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5094 fsts s2, [r9] @ vAA<- s2 5095 GOTO_OPCODE(ip) @ jump to next instruction 5096 5097 5098/* ------------------------------ */ 5099 .balign 64 5100.L_OP_REM_FLOAT: /* 0xaa */ 5101/* File: armv5te/OP_REM_FLOAT.S */ 5102/* EABI doesn't define a float remainder function, but libm does */ 5103/* File: armv5te/binop.S */ 5104 /* 5105 * Generic 32-bit binary operation. Provide an "instr" line that 5106 * specifies an instruction that performs "result = r0 op r1". 5107 * This could be an ARM instruction or a function call. (If the result 5108 * comes back in a register other than r0, you can override "result".) 5109 * 5110 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5111 * vCC (r1). Useful for integer division and modulus. Note that we 5112 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5113 * handles it correctly. 5114 * 5115 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5116 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5117 * mul-float, div-float, rem-float 5118 */ 5119 /* binop vAA, vBB, vCC */ 5120 FETCH(r0, 1) @ r0<- CCBB 5121 mov r9, rINST, lsr #8 @ r9<- AA 5122 mov r3, r0, lsr #8 @ r3<- CC 5123 and r2, r0, #255 @ r2<- BB 5124 GET_VREG(r1, r3) @ r1<- vCC 5125 GET_VREG(r0, r2) @ r0<- vBB 5126 .if 0 5127 cmp r1, #0 @ is second operand zero? 5128 beq common_errDivideByZero 5129 .endif 5130 5131 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5132 @ optional op; may set condition codes 5133 bl fmodf @ r0<- op, r0-r3 changed 5134 GET_INST_OPCODE(ip) @ extract opcode from rINST 5135 SET_VREG(r0, r9) @ vAA<- r0 5136 GOTO_OPCODE(ip) @ jump to next instruction 5137 /* 11-14 instructions */ 5138 5139 5140 5141/* ------------------------------ */ 5142 .balign 64 5143.L_OP_ADD_DOUBLE: /* 0xab */ 5144/* File: arm-vfp/OP_ADD_DOUBLE.S */ 5145/* File: arm-vfp/fbinopWide.S */ 5146 /* 5147 * Generic 64-bit double-precision floating point binary operation. 5148 * Provide an "instr" line that specifies an instruction that performs 5149 * "d2 = d0 op d1". 5150 * 5151 * for: add-double, sub-double, mul-double, div-double 5152 */ 5153 /* doubleop vAA, vBB, vCC */ 5154 FETCH(r0, 1) @ r0<- CCBB 5155 mov r9, rINST, lsr #8 @ r9<- AA 5156 mov r3, r0, lsr #8 @ r3<- CC 5157 and r2, r0, #255 @ r2<- BB 5158 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5159 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5160 fldd d1, [r3] @ d1<- vCC 5161 fldd d0, [r2] @ d0<- vBB 5162 5163 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5164 faddd d2, d0, d1 @ s2<- op 5165 GET_INST_OPCODE(ip) @ extract opcode from rINST 5166 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5167 fstd d2, [r9] @ vAA<- d2 5168 GOTO_OPCODE(ip) @ jump to next instruction 5169 5170 5171/* ------------------------------ */ 5172 .balign 64 5173.L_OP_SUB_DOUBLE: /* 0xac */ 5174/* File: arm-vfp/OP_SUB_DOUBLE.S */ 5175/* File: arm-vfp/fbinopWide.S */ 5176 /* 5177 * Generic 64-bit double-precision floating point binary operation. 5178 * Provide an "instr" line that specifies an instruction that performs 5179 * "d2 = d0 op d1". 5180 * 5181 * for: add-double, sub-double, mul-double, div-double 5182 */ 5183 /* doubleop vAA, vBB, vCC */ 5184 FETCH(r0, 1) @ r0<- CCBB 5185 mov r9, rINST, lsr #8 @ r9<- AA 5186 mov r3, r0, lsr #8 @ r3<- CC 5187 and r2, r0, #255 @ r2<- BB 5188 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5189 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5190 fldd d1, [r3] @ d1<- vCC 5191 fldd d0, [r2] @ d0<- vBB 5192 5193 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5194 fsubd d2, d0, d1 @ s2<- op 5195 GET_INST_OPCODE(ip) @ extract opcode from rINST 5196 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5197 fstd d2, [r9] @ vAA<- d2 5198 GOTO_OPCODE(ip) @ jump to next instruction 5199 5200 5201/* ------------------------------ */ 5202 .balign 64 5203.L_OP_MUL_DOUBLE: /* 0xad */ 5204/* File: arm-vfp/OP_MUL_DOUBLE.S */ 5205/* File: arm-vfp/fbinopWide.S */ 5206 /* 5207 * Generic 64-bit double-precision floating point binary operation. 5208 * Provide an "instr" line that specifies an instruction that performs 5209 * "d2 = d0 op d1". 5210 * 5211 * for: add-double, sub-double, mul-double, div-double 5212 */ 5213 /* doubleop vAA, vBB, vCC */ 5214 FETCH(r0, 1) @ r0<- CCBB 5215 mov r9, rINST, lsr #8 @ r9<- AA 5216 mov r3, r0, lsr #8 @ r3<- CC 5217 and r2, r0, #255 @ r2<- BB 5218 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5219 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5220 fldd d1, [r3] @ d1<- vCC 5221 fldd d0, [r2] @ d0<- vBB 5222 5223 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5224 fmuld d2, d0, d1 @ s2<- op 5225 GET_INST_OPCODE(ip) @ extract opcode from rINST 5226 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5227 fstd d2, [r9] @ vAA<- d2 5228 GOTO_OPCODE(ip) @ jump to next instruction 5229 5230 5231/* ------------------------------ */ 5232 .balign 64 5233.L_OP_DIV_DOUBLE: /* 0xae */ 5234/* File: arm-vfp/OP_DIV_DOUBLE.S */ 5235/* File: arm-vfp/fbinopWide.S */ 5236 /* 5237 * Generic 64-bit double-precision floating point binary operation. 5238 * Provide an "instr" line that specifies an instruction that performs 5239 * "d2 = d0 op d1". 5240 * 5241 * for: add-double, sub-double, mul-double, div-double 5242 */ 5243 /* doubleop vAA, vBB, vCC */ 5244 FETCH(r0, 1) @ r0<- CCBB 5245 mov r9, rINST, lsr #8 @ r9<- AA 5246 mov r3, r0, lsr #8 @ r3<- CC 5247 and r2, r0, #255 @ r2<- BB 5248 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5249 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5250 fldd d1, [r3] @ d1<- vCC 5251 fldd d0, [r2] @ d0<- vBB 5252 5253 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5254 fdivd d2, d0, d1 @ s2<- op 5255 GET_INST_OPCODE(ip) @ extract opcode from rINST 5256 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5257 fstd d2, [r9] @ vAA<- d2 5258 GOTO_OPCODE(ip) @ jump to next instruction 5259 5260 5261/* ------------------------------ */ 5262 .balign 64 5263.L_OP_REM_DOUBLE: /* 0xaf */ 5264/* File: armv5te/OP_REM_DOUBLE.S */ 5265/* EABI doesn't define a double remainder function, but libm does */ 5266/* File: armv5te/binopWide.S */ 5267 /* 5268 * Generic 64-bit binary operation. Provide an "instr" line that 5269 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5270 * This could be an ARM instruction or a function call. (If the result 5271 * comes back in a register other than r0, you can override "result".) 5272 * 5273 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5274 * vCC (r1). Useful for integer division and modulus. 5275 * 5276 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5277 * xor-long, add-double, sub-double, mul-double, div-double, 5278 * rem-double 5279 * 5280 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5281 */ 5282 /* binop vAA, vBB, vCC */ 5283 FETCH(r0, 1) @ r0<- CCBB 5284 mov r9, rINST, lsr #8 @ r9<- AA 5285 and r2, r0, #255 @ r2<- BB 5286 mov r3, r0, lsr #8 @ r3<- CC 5287 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5288 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5289 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5290 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5291 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5292 .if 0 5293 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5294 beq common_errDivideByZero 5295 .endif 5296 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5297 5298 @ optional op; may set condition codes 5299 bl fmod @ result<- op, r0-r3 changed 5300 GET_INST_OPCODE(ip) @ extract opcode from rINST 5301 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5302 GOTO_OPCODE(ip) @ jump to next instruction 5303 /* 14-17 instructions */ 5304 5305 5306 5307/* ------------------------------ */ 5308 .balign 64 5309.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5310/* File: armv6t2/OP_ADD_INT_2ADDR.S */ 5311/* File: armv6t2/binop2addr.S */ 5312 /* 5313 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5314 * that specifies an instruction that performs "result = r0 op r1". 5315 * This could be an ARM instruction or a function call. (If the result 5316 * comes back in a register other than r0, you can override "result".) 5317 * 5318 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5319 * vCC (r1). Useful for integer division and modulus. 5320 * 5321 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5322 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5323 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5324 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5325 */ 5326 /* binop/2addr vA, vB */ 5327 mov r3, rINST, lsr #12 @ r3<- B 5328 ubfx r9, rINST, #8, #4 @ r9<- A 5329 GET_VREG(r1, r3) @ r1<- vB 5330 GET_VREG(r0, r9) @ r0<- vA 5331 .if 0 5332 cmp r1, #0 @ is second operand zero? 5333 beq common_errDivideByZero 5334 .endif 5335 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5336 5337 @ optional op; may set condition codes 5338 add r0, r0, r1 @ r0<- op, r0-r3 changed 5339 GET_INST_OPCODE(ip) @ extract opcode from rINST 5340 SET_VREG(r0, r9) @ vAA<- r0 5341 GOTO_OPCODE(ip) @ jump to next instruction 5342 /* 10-13 instructions */ 5343 5344 5345 5346/* ------------------------------ */ 5347 .balign 64 5348.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5349/* File: armv6t2/OP_SUB_INT_2ADDR.S */ 5350/* File: armv6t2/binop2addr.S */ 5351 /* 5352 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5353 * that specifies an instruction that performs "result = r0 op r1". 5354 * This could be an ARM instruction or a function call. (If the result 5355 * comes back in a register other than r0, you can override "result".) 5356 * 5357 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5358 * vCC (r1). Useful for integer division and modulus. 5359 * 5360 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5361 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5362 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5363 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5364 */ 5365 /* binop/2addr vA, vB */ 5366 mov r3, rINST, lsr #12 @ r3<- B 5367 ubfx r9, rINST, #8, #4 @ r9<- A 5368 GET_VREG(r1, r3) @ r1<- vB 5369 GET_VREG(r0, r9) @ r0<- vA 5370 .if 0 5371 cmp r1, #0 @ is second operand zero? 5372 beq common_errDivideByZero 5373 .endif 5374 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5375 5376 @ optional op; may set condition codes 5377 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5378 GET_INST_OPCODE(ip) @ extract opcode from rINST 5379 SET_VREG(r0, r9) @ vAA<- r0 5380 GOTO_OPCODE(ip) @ jump to next instruction 5381 /* 10-13 instructions */ 5382 5383 5384 5385/* ------------------------------ */ 5386 .balign 64 5387.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5388/* File: armv6t2/OP_MUL_INT_2ADDR.S */ 5389/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5390/* File: armv6t2/binop2addr.S */ 5391 /* 5392 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5393 * that specifies an instruction that performs "result = r0 op r1". 5394 * This could be an ARM instruction or a function call. (If the result 5395 * comes back in a register other than r0, you can override "result".) 5396 * 5397 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5398 * vCC (r1). Useful for integer division and modulus. 5399 * 5400 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5401 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5402 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5403 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5404 */ 5405 /* binop/2addr vA, vB */ 5406 mov r3, rINST, lsr #12 @ r3<- B 5407 ubfx r9, rINST, #8, #4 @ r9<- A 5408 GET_VREG(r1, r3) @ r1<- vB 5409 GET_VREG(r0, r9) @ r0<- vA 5410 .if 0 5411 cmp r1, #0 @ is second operand zero? 5412 beq common_errDivideByZero 5413 .endif 5414 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5415 5416 @ optional op; may set condition codes 5417 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5418 GET_INST_OPCODE(ip) @ extract opcode from rINST 5419 SET_VREG(r0, r9) @ vAA<- r0 5420 GOTO_OPCODE(ip) @ jump to next instruction 5421 /* 10-13 instructions */ 5422 5423 5424 5425/* ------------------------------ */ 5426 .balign 64 5427.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5428/* File: armv6t2/OP_DIV_INT_2ADDR.S */ 5429/* File: armv6t2/binop2addr.S */ 5430 /* 5431 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5432 * that specifies an instruction that performs "result = r0 op r1". 5433 * This could be an ARM instruction or a function call. (If the result 5434 * comes back in a register other than r0, you can override "result".) 5435 * 5436 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5437 * vCC (r1). Useful for integer division and modulus. 5438 * 5439 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5440 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5441 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5442 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5443 */ 5444 /* binop/2addr vA, vB */ 5445 mov r3, rINST, lsr #12 @ r3<- B 5446 ubfx r9, rINST, #8, #4 @ r9<- A 5447 GET_VREG(r1, r3) @ r1<- vB 5448 GET_VREG(r0, r9) @ r0<- vA 5449 .if 1 5450 cmp r1, #0 @ is second operand zero? 5451 beq common_errDivideByZero 5452 .endif 5453 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5454 5455 @ optional op; may set condition codes 5456 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5457 GET_INST_OPCODE(ip) @ extract opcode from rINST 5458 SET_VREG(r0, r9) @ vAA<- r0 5459 GOTO_OPCODE(ip) @ jump to next instruction 5460 /* 10-13 instructions */ 5461 5462 5463 5464/* ------------------------------ */ 5465 .balign 64 5466.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5467/* File: armv6t2/OP_REM_INT_2ADDR.S */ 5468/* idivmod returns quotient in r0 and remainder in r1 */ 5469/* File: armv6t2/binop2addr.S */ 5470 /* 5471 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5472 * that specifies an instruction that performs "result = r0 op r1". 5473 * This could be an ARM instruction or a function call. (If the result 5474 * comes back in a register other than r0, you can override "result".) 5475 * 5476 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5477 * vCC (r1). Useful for integer division and modulus. 5478 * 5479 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5480 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5481 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5482 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5483 */ 5484 /* binop/2addr vA, vB */ 5485 mov r3, rINST, lsr #12 @ r3<- B 5486 ubfx r9, rINST, #8, #4 @ r9<- A 5487 GET_VREG(r1, r3) @ r1<- vB 5488 GET_VREG(r0, r9) @ r0<- vA 5489 .if 1 5490 cmp r1, #0 @ is second operand zero? 5491 beq common_errDivideByZero 5492 .endif 5493 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5494 5495 @ optional op; may set condition codes 5496 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5497 GET_INST_OPCODE(ip) @ extract opcode from rINST 5498 SET_VREG(r1, r9) @ vAA<- r1 5499 GOTO_OPCODE(ip) @ jump to next instruction 5500 /* 10-13 instructions */ 5501 5502 5503 5504/* ------------------------------ */ 5505 .balign 64 5506.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5507/* File: armv6t2/OP_AND_INT_2ADDR.S */ 5508/* File: armv6t2/binop2addr.S */ 5509 /* 5510 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5511 * that specifies an instruction that performs "result = r0 op r1". 5512 * This could be an ARM instruction or a function call. (If the result 5513 * comes back in a register other than r0, you can override "result".) 5514 * 5515 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5516 * vCC (r1). Useful for integer division and modulus. 5517 * 5518 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5519 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5520 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5521 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5522 */ 5523 /* binop/2addr vA, vB */ 5524 mov r3, rINST, lsr #12 @ r3<- B 5525 ubfx r9, rINST, #8, #4 @ r9<- A 5526 GET_VREG(r1, r3) @ r1<- vB 5527 GET_VREG(r0, r9) @ r0<- vA 5528 .if 0 5529 cmp r1, #0 @ is second operand zero? 5530 beq common_errDivideByZero 5531 .endif 5532 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5533 5534 @ optional op; may set condition codes 5535 and r0, r0, r1 @ r0<- op, r0-r3 changed 5536 GET_INST_OPCODE(ip) @ extract opcode from rINST 5537 SET_VREG(r0, r9) @ vAA<- r0 5538 GOTO_OPCODE(ip) @ jump to next instruction 5539 /* 10-13 instructions */ 5540 5541 5542 5543/* ------------------------------ */ 5544 .balign 64 5545.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5546/* File: armv6t2/OP_OR_INT_2ADDR.S */ 5547/* File: armv6t2/binop2addr.S */ 5548 /* 5549 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5550 * that specifies an instruction that performs "result = r0 op r1". 5551 * This could be an ARM instruction or a function call. (If the result 5552 * comes back in a register other than r0, you can override "result".) 5553 * 5554 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5555 * vCC (r1). Useful for integer division and modulus. 5556 * 5557 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5558 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5559 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5560 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5561 */ 5562 /* binop/2addr vA, vB */ 5563 mov r3, rINST, lsr #12 @ r3<- B 5564 ubfx r9, rINST, #8, #4 @ r9<- A 5565 GET_VREG(r1, r3) @ r1<- vB 5566 GET_VREG(r0, r9) @ r0<- vA 5567 .if 0 5568 cmp r1, #0 @ is second operand zero? 5569 beq common_errDivideByZero 5570 .endif 5571 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5572 5573 @ optional op; may set condition codes 5574 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5575 GET_INST_OPCODE(ip) @ extract opcode from rINST 5576 SET_VREG(r0, r9) @ vAA<- r0 5577 GOTO_OPCODE(ip) @ jump to next instruction 5578 /* 10-13 instructions */ 5579 5580 5581 5582/* ------------------------------ */ 5583 .balign 64 5584.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5585/* File: armv6t2/OP_XOR_INT_2ADDR.S */ 5586/* File: armv6t2/binop2addr.S */ 5587 /* 5588 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5589 * that specifies an instruction that performs "result = r0 op r1". 5590 * This could be an ARM instruction or a function call. (If the result 5591 * comes back in a register other than r0, you can override "result".) 5592 * 5593 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5594 * vCC (r1). Useful for integer division and modulus. 5595 * 5596 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5597 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5598 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5599 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5600 */ 5601 /* binop/2addr vA, vB */ 5602 mov r3, rINST, lsr #12 @ r3<- B 5603 ubfx r9, rINST, #8, #4 @ r9<- A 5604 GET_VREG(r1, r3) @ r1<- vB 5605 GET_VREG(r0, r9) @ r0<- vA 5606 .if 0 5607 cmp r1, #0 @ is second operand zero? 5608 beq common_errDivideByZero 5609 .endif 5610 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5611 5612 @ optional op; may set condition codes 5613 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5614 GET_INST_OPCODE(ip) @ extract opcode from rINST 5615 SET_VREG(r0, r9) @ vAA<- r0 5616 GOTO_OPCODE(ip) @ jump to next instruction 5617 /* 10-13 instructions */ 5618 5619 5620 5621/* ------------------------------ */ 5622 .balign 64 5623.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5624/* File: armv6t2/OP_SHL_INT_2ADDR.S */ 5625/* File: armv6t2/binop2addr.S */ 5626 /* 5627 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5628 * that specifies an instruction that performs "result = r0 op r1". 5629 * This could be an ARM instruction or a function call. (If the result 5630 * comes back in a register other than r0, you can override "result".) 5631 * 5632 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5633 * vCC (r1). Useful for integer division and modulus. 5634 * 5635 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5636 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5637 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5638 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5639 */ 5640 /* binop/2addr vA, vB */ 5641 mov r3, rINST, lsr #12 @ r3<- B 5642 ubfx r9, rINST, #8, #4 @ r9<- A 5643 GET_VREG(r1, r3) @ r1<- vB 5644 GET_VREG(r0, r9) @ r0<- vA 5645 .if 0 5646 cmp r1, #0 @ is second operand zero? 5647 beq common_errDivideByZero 5648 .endif 5649 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5650 5651 and r1, r1, #31 @ optional op; may set condition codes 5652 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5653 GET_INST_OPCODE(ip) @ extract opcode from rINST 5654 SET_VREG(r0, r9) @ vAA<- r0 5655 GOTO_OPCODE(ip) @ jump to next instruction 5656 /* 10-13 instructions */ 5657 5658 5659 5660/* ------------------------------ */ 5661 .balign 64 5662.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5663/* File: armv6t2/OP_SHR_INT_2ADDR.S */ 5664/* File: armv6t2/binop2addr.S */ 5665 /* 5666 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5667 * that specifies an instruction that performs "result = r0 op r1". 5668 * This could be an ARM instruction or a function call. (If the result 5669 * comes back in a register other than r0, you can override "result".) 5670 * 5671 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5672 * vCC (r1). Useful for integer division and modulus. 5673 * 5674 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5675 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5676 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5677 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5678 */ 5679 /* binop/2addr vA, vB */ 5680 mov r3, rINST, lsr #12 @ r3<- B 5681 ubfx r9, rINST, #8, #4 @ r9<- A 5682 GET_VREG(r1, r3) @ r1<- vB 5683 GET_VREG(r0, r9) @ r0<- vA 5684 .if 0 5685 cmp r1, #0 @ is second operand zero? 5686 beq common_errDivideByZero 5687 .endif 5688 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5689 5690 and r1, r1, #31 @ optional op; may set condition codes 5691 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5692 GET_INST_OPCODE(ip) @ extract opcode from rINST 5693 SET_VREG(r0, r9) @ vAA<- r0 5694 GOTO_OPCODE(ip) @ jump to next instruction 5695 /* 10-13 instructions */ 5696 5697 5698 5699/* ------------------------------ */ 5700 .balign 64 5701.L_OP_USHR_INT_2ADDR: /* 0xba */ 5702/* File: armv6t2/OP_USHR_INT_2ADDR.S */ 5703/* File: armv6t2/binop2addr.S */ 5704 /* 5705 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5706 * that specifies an instruction that performs "result = r0 op r1". 5707 * This could be an ARM instruction or a function call. (If the result 5708 * comes back in a register other than r0, you can override "result".) 5709 * 5710 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5711 * vCC (r1). Useful for integer division and modulus. 5712 * 5713 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5714 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5715 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5716 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5717 */ 5718 /* binop/2addr vA, vB */ 5719 mov r3, rINST, lsr #12 @ r3<- B 5720 ubfx r9, rINST, #8, #4 @ r9<- A 5721 GET_VREG(r1, r3) @ r1<- vB 5722 GET_VREG(r0, r9) @ r0<- vA 5723 .if 0 5724 cmp r1, #0 @ is second operand zero? 5725 beq common_errDivideByZero 5726 .endif 5727 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5728 5729 and r1, r1, #31 @ optional op; may set condition codes 5730 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5731 GET_INST_OPCODE(ip) @ extract opcode from rINST 5732 SET_VREG(r0, r9) @ vAA<- r0 5733 GOTO_OPCODE(ip) @ jump to next instruction 5734 /* 10-13 instructions */ 5735 5736 5737 5738/* ------------------------------ */ 5739 .balign 64 5740.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5741/* File: armv6t2/OP_ADD_LONG_2ADDR.S */ 5742/* File: armv6t2/binopWide2addr.S */ 5743 /* 5744 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5745 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5746 * This could be an ARM instruction or a function call. (If the result 5747 * comes back in a register other than r0, you can override "result".) 5748 * 5749 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5750 * vCC (r1). Useful for integer division and modulus. 5751 * 5752 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5753 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5754 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5755 * rem-double/2addr 5756 */ 5757 /* binop/2addr vA, vB */ 5758 mov r1, rINST, lsr #12 @ r1<- B 5759 ubfx r9, rINST, #8, #4 @ r9<- A 5760 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5761 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5762 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5763 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5764 .if 0 5765 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5766 beq common_errDivideByZero 5767 .endif 5768 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5769 5770 adds r0, r0, r2 @ optional op; may set condition codes 5771 adc r1, r1, r3 @ result<- op, r0-r3 changed 5772 GET_INST_OPCODE(ip) @ extract opcode from rINST 5773 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5774 GOTO_OPCODE(ip) @ jump to next instruction 5775 /* 12-15 instructions */ 5776 5777 5778 5779/* ------------------------------ */ 5780 .balign 64 5781.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5782/* File: armv6t2/OP_SUB_LONG_2ADDR.S */ 5783/* File: armv6t2/binopWide2addr.S */ 5784 /* 5785 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5786 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5787 * This could be an ARM instruction or a function call. (If the result 5788 * comes back in a register other than r0, you can override "result".) 5789 * 5790 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5791 * vCC (r1). Useful for integer division and modulus. 5792 * 5793 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5794 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5795 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5796 * rem-double/2addr 5797 */ 5798 /* binop/2addr vA, vB */ 5799 mov r1, rINST, lsr #12 @ r1<- B 5800 ubfx r9, rINST, #8, #4 @ r9<- A 5801 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5802 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5803 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5804 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5805 .if 0 5806 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5807 beq common_errDivideByZero 5808 .endif 5809 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5810 5811 subs r0, r0, r2 @ optional op; may set condition codes 5812 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5813 GET_INST_OPCODE(ip) @ extract opcode from rINST 5814 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5815 GOTO_OPCODE(ip) @ jump to next instruction 5816 /* 12-15 instructions */ 5817 5818 5819 5820/* ------------------------------ */ 5821 .balign 64 5822.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 5823/* File: armv6t2/OP_MUL_LONG_2ADDR.S */ 5824 /* 5825 * Signed 64-bit integer multiply, "/2addr" version. 5826 * 5827 * See OP_MUL_LONG for an explanation. 5828 * 5829 * We get a little tight on registers, so to avoid looking up &fp[A] 5830 * again we stuff it into rINST. 5831 */ 5832 /* mul-long/2addr vA, vB */ 5833 mov r1, rINST, lsr #12 @ r1<- B 5834 ubfx r9, rINST, #8, #4 @ r9<- A 5835 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5836 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 5837 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5838 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 5839 mul ip, r2, r1 @ ip<- ZxW 5840 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 5841 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 5842 mov r0, rINST @ r0<- &fp[A] (free up rINST) 5843 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5844 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 5845 GET_INST_OPCODE(ip) @ extract opcode from rINST 5846 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 5847 GOTO_OPCODE(ip) @ jump to next instruction 5848 5849 5850/* ------------------------------ */ 5851 .balign 64 5852.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 5853/* File: armv6t2/OP_DIV_LONG_2ADDR.S */ 5854/* File: armv6t2/binopWide2addr.S */ 5855 /* 5856 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5857 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5858 * This could be an ARM instruction or a function call. (If the result 5859 * comes back in a register other than r0, you can override "result".) 5860 * 5861 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5862 * vCC (r1). Useful for integer division and modulus. 5863 * 5864 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5865 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5866 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5867 * rem-double/2addr 5868 */ 5869 /* binop/2addr vA, vB */ 5870 mov r1, rINST, lsr #12 @ r1<- B 5871 ubfx r9, rINST, #8, #4 @ r9<- A 5872 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5873 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5874 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5875 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5876 .if 1 5877 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5878 beq common_errDivideByZero 5879 .endif 5880 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5881 5882 @ optional op; may set condition codes 5883 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5884 GET_INST_OPCODE(ip) @ extract opcode from rINST 5885 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5886 GOTO_OPCODE(ip) @ jump to next instruction 5887 /* 12-15 instructions */ 5888 5889 5890 5891/* ------------------------------ */ 5892 .balign 64 5893.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5894/* File: armv6t2/OP_REM_LONG_2ADDR.S */ 5895/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 5896/* File: armv6t2/binopWide2addr.S */ 5897 /* 5898 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5899 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5900 * This could be an ARM instruction or a function call. (If the result 5901 * comes back in a register other than r0, you can override "result".) 5902 * 5903 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5904 * vCC (r1). Useful for integer division and modulus. 5905 * 5906 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5907 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5908 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5909 * rem-double/2addr 5910 */ 5911 /* binop/2addr vA, vB */ 5912 mov r1, rINST, lsr #12 @ r1<- B 5913 ubfx r9, rINST, #8, #4 @ r9<- A 5914 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5915 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5916 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5917 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5918 .if 1 5919 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5920 beq common_errDivideByZero 5921 .endif 5922 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5923 5924 @ optional op; may set condition codes 5925 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5926 GET_INST_OPCODE(ip) @ extract opcode from rINST 5927 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 5928 GOTO_OPCODE(ip) @ jump to next instruction 5929 /* 12-15 instructions */ 5930 5931 5932 5933/* ------------------------------ */ 5934 .balign 64 5935.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 5936/* File: armv6t2/OP_AND_LONG_2ADDR.S */ 5937/* File: armv6t2/binopWide2addr.S */ 5938 /* 5939 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5940 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5941 * This could be an ARM instruction or a function call. (If the result 5942 * comes back in a register other than r0, you can override "result".) 5943 * 5944 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5945 * vCC (r1). Useful for integer division and modulus. 5946 * 5947 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5948 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5949 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5950 * rem-double/2addr 5951 */ 5952 /* binop/2addr vA, vB */ 5953 mov r1, rINST, lsr #12 @ r1<- B 5954 ubfx r9, rINST, #8, #4 @ r9<- A 5955 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5956 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5957 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5958 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5959 .if 0 5960 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5961 beq common_errDivideByZero 5962 .endif 5963 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5964 5965 and r0, r0, r2 @ optional op; may set condition codes 5966 and r1, r1, r3 @ result<- op, r0-r3 changed 5967 GET_INST_OPCODE(ip) @ extract opcode from rINST 5968 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5969 GOTO_OPCODE(ip) @ jump to next instruction 5970 /* 12-15 instructions */ 5971 5972 5973 5974/* ------------------------------ */ 5975 .balign 64 5976.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 5977/* File: armv6t2/OP_OR_LONG_2ADDR.S */ 5978/* File: armv6t2/binopWide2addr.S */ 5979 /* 5980 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5981 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5982 * This could be an ARM instruction or a function call. (If the result 5983 * comes back in a register other than r0, you can override "result".) 5984 * 5985 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5986 * vCC (r1). Useful for integer division and modulus. 5987 * 5988 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5989 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5990 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5991 * rem-double/2addr 5992 */ 5993 /* binop/2addr vA, vB */ 5994 mov r1, rINST, lsr #12 @ r1<- B 5995 ubfx r9, rINST, #8, #4 @ r9<- A 5996 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5997 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5998 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5999 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6000 .if 0 6001 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6002 beq common_errDivideByZero 6003 .endif 6004 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6005 6006 orr r0, r0, r2 @ optional op; may set condition codes 6007 orr r1, r1, r3 @ result<- op, r0-r3 changed 6008 GET_INST_OPCODE(ip) @ extract opcode from rINST 6009 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6010 GOTO_OPCODE(ip) @ jump to next instruction 6011 /* 12-15 instructions */ 6012 6013 6014 6015/* ------------------------------ */ 6016 .balign 64 6017.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 6018/* File: armv6t2/OP_XOR_LONG_2ADDR.S */ 6019/* File: armv6t2/binopWide2addr.S */ 6020 /* 6021 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6022 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6023 * This could be an ARM instruction or a function call. (If the result 6024 * comes back in a register other than r0, you can override "result".) 6025 * 6026 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6027 * vCC (r1). Useful for integer division and modulus. 6028 * 6029 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6030 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6031 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6032 * rem-double/2addr 6033 */ 6034 /* binop/2addr vA, vB */ 6035 mov r1, rINST, lsr #12 @ r1<- B 6036 ubfx r9, rINST, #8, #4 @ r9<- A 6037 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6038 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6039 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6040 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6041 .if 0 6042 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6043 beq common_errDivideByZero 6044 .endif 6045 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6046 6047 eor r0, r0, r2 @ optional op; may set condition codes 6048 eor r1, r1, r3 @ result<- op, r0-r3 changed 6049 GET_INST_OPCODE(ip) @ extract opcode from rINST 6050 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6051 GOTO_OPCODE(ip) @ jump to next instruction 6052 /* 12-15 instructions */ 6053 6054 6055 6056/* ------------------------------ */ 6057 .balign 64 6058.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 6059/* File: armv6t2/OP_SHL_LONG_2ADDR.S */ 6060 /* 6061 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6062 * 32-bit shift distance. 6063 */ 6064 /* shl-long/2addr vA, vB */ 6065 mov r3, rINST, lsr #12 @ r3<- B 6066 ubfx r9, rINST, #8, #4 @ r9<- A 6067 GET_VREG(r2, r3) @ r2<- vB 6068 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6069 and r2, r2, #63 @ r2<- r2 & 0x3f 6070 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6071 6072 mov r1, r1, asl r2 @ r1<- r1 << r2 6073 rsb r3, r2, #32 @ r3<- 32 - r2 6074 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 6075 subs ip, r2, #32 @ ip<- r2 - 32 6076 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6077 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 6078 mov r0, r0, asl r2 @ r0<- r0 << r2 6079 b .LOP_SHL_LONG_2ADDR_finish 6080 6081/* ------------------------------ */ 6082 .balign 64 6083.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 6084/* File: armv6t2/OP_SHR_LONG_2ADDR.S */ 6085 /* 6086 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6087 * 32-bit shift distance. 6088 */ 6089 /* shr-long/2addr vA, vB */ 6090 mov r3, rINST, lsr #12 @ r3<- B 6091 ubfx r9, rINST, #8, #4 @ r9<- A 6092 GET_VREG(r2, r3) @ r2<- vB 6093 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6094 and r2, r2, #63 @ r2<- r2 & 0x3f 6095 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6096 6097 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6098 rsb r3, r2, #32 @ r3<- 32 - r2 6099 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6100 subs ip, r2, #32 @ ip<- r2 - 32 6101 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6102 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6103 mov r1, r1, asr r2 @ r1<- r1 >> r2 6104 b .LOP_SHR_LONG_2ADDR_finish 6105 6106/* ------------------------------ */ 6107 .balign 64 6108.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6109/* File: armv6t2/OP_USHR_LONG_2ADDR.S */ 6110 /* 6111 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6112 * 32-bit shift distance. 6113 */ 6114 /* ushr-long/2addr vA, vB */ 6115 mov r3, rINST, lsr #12 @ r3<- B 6116 ubfx r9, rINST, #8, #4 @ r9<- A 6117 GET_VREG(r2, r3) @ r2<- vB 6118 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6119 and r2, r2, #63 @ r2<- r2 & 0x3f 6120 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6121 6122 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6123 rsb r3, r2, #32 @ r3<- 32 - r2 6124 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6125 subs ip, r2, #32 @ ip<- r2 - 32 6126 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6127 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6128 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6129 b .LOP_USHR_LONG_2ADDR_finish 6130 6131/* ------------------------------ */ 6132 .balign 64 6133.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6134/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */ 6135/* File: arm-vfp/fbinop2addr.S */ 6136 /* 6137 * Generic 32-bit floating point "/2addr" binary operation. Provide 6138 * an "instr" line that specifies an instruction that performs 6139 * "s2 = s0 op s1". 6140 * 6141 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6142 */ 6143 /* binop/2addr vA, vB */ 6144 mov r3, rINST, lsr #12 @ r3<- B 6145 mov r9, rINST, lsr #8 @ r9<- A+ 6146 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6147 and r9, r9, #15 @ r9<- A 6148 flds s1, [r3] @ s1<- vB 6149 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6150 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6151 flds s0, [r9] @ s0<- vA 6152 6153 fadds s2, s0, s1 @ s2<- op 6154 GET_INST_OPCODE(ip) @ extract opcode from rINST 6155 fsts s2, [r9] @ vAA<- s2 6156 GOTO_OPCODE(ip) @ jump to next instruction 6157 6158 6159/* ------------------------------ */ 6160 .balign 64 6161.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6162/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */ 6163/* File: arm-vfp/fbinop2addr.S */ 6164 /* 6165 * Generic 32-bit floating point "/2addr" binary operation. Provide 6166 * an "instr" line that specifies an instruction that performs 6167 * "s2 = s0 op s1". 6168 * 6169 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6170 */ 6171 /* binop/2addr vA, vB */ 6172 mov r3, rINST, lsr #12 @ r3<- B 6173 mov r9, rINST, lsr #8 @ r9<- A+ 6174 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6175 and r9, r9, #15 @ r9<- A 6176 flds s1, [r3] @ s1<- vB 6177 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6178 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6179 flds s0, [r9] @ s0<- vA 6180 6181 fsubs s2, s0, s1 @ s2<- op 6182 GET_INST_OPCODE(ip) @ extract opcode from rINST 6183 fsts s2, [r9] @ vAA<- s2 6184 GOTO_OPCODE(ip) @ jump to next instruction 6185 6186 6187/* ------------------------------ */ 6188 .balign 64 6189.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6190/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */ 6191/* File: arm-vfp/fbinop2addr.S */ 6192 /* 6193 * Generic 32-bit floating point "/2addr" binary operation. Provide 6194 * an "instr" line that specifies an instruction that performs 6195 * "s2 = s0 op s1". 6196 * 6197 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6198 */ 6199 /* binop/2addr vA, vB */ 6200 mov r3, rINST, lsr #12 @ r3<- B 6201 mov r9, rINST, lsr #8 @ r9<- A+ 6202 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6203 and r9, r9, #15 @ r9<- A 6204 flds s1, [r3] @ s1<- vB 6205 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6206 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6207 flds s0, [r9] @ s0<- vA 6208 6209 fmuls s2, s0, s1 @ s2<- op 6210 GET_INST_OPCODE(ip) @ extract opcode from rINST 6211 fsts s2, [r9] @ vAA<- s2 6212 GOTO_OPCODE(ip) @ jump to next instruction 6213 6214 6215/* ------------------------------ */ 6216 .balign 64 6217.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6218/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */ 6219/* File: arm-vfp/fbinop2addr.S */ 6220 /* 6221 * Generic 32-bit floating point "/2addr" binary operation. Provide 6222 * an "instr" line that specifies an instruction that performs 6223 * "s2 = s0 op s1". 6224 * 6225 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6226 */ 6227 /* binop/2addr vA, vB */ 6228 mov r3, rINST, lsr #12 @ r3<- B 6229 mov r9, rINST, lsr #8 @ r9<- A+ 6230 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6231 and r9, r9, #15 @ r9<- A 6232 flds s1, [r3] @ s1<- vB 6233 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6234 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6235 flds s0, [r9] @ s0<- vA 6236 6237 fdivs s2, s0, s1 @ s2<- op 6238 GET_INST_OPCODE(ip) @ extract opcode from rINST 6239 fsts s2, [r9] @ vAA<- s2 6240 GOTO_OPCODE(ip) @ jump to next instruction 6241 6242 6243/* ------------------------------ */ 6244 .balign 64 6245.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6246/* File: armv6t2/OP_REM_FLOAT_2ADDR.S */ 6247/* EABI doesn't define a float remainder function, but libm does */ 6248/* File: armv6t2/binop2addr.S */ 6249 /* 6250 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6251 * that specifies an instruction that performs "result = r0 op r1". 6252 * This could be an ARM instruction or a function call. (If the result 6253 * comes back in a register other than r0, you can override "result".) 6254 * 6255 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6256 * vCC (r1). Useful for integer division and modulus. 6257 * 6258 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6259 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6260 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6261 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6262 */ 6263 /* binop/2addr vA, vB */ 6264 mov r3, rINST, lsr #12 @ r3<- B 6265 ubfx r9, rINST, #8, #4 @ r9<- A 6266 GET_VREG(r1, r3) @ r1<- vB 6267 GET_VREG(r0, r9) @ r0<- vA 6268 .if 0 6269 cmp r1, #0 @ is second operand zero? 6270 beq common_errDivideByZero 6271 .endif 6272 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6273 6274 @ optional op; may set condition codes 6275 bl fmodf @ r0<- op, r0-r3 changed 6276 GET_INST_OPCODE(ip) @ extract opcode from rINST 6277 SET_VREG(r0, r9) @ vAA<- r0 6278 GOTO_OPCODE(ip) @ jump to next instruction 6279 /* 10-13 instructions */ 6280 6281 6282 6283/* ------------------------------ */ 6284 .balign 64 6285.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6286/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */ 6287/* File: arm-vfp/fbinopWide2addr.S */ 6288 /* 6289 * Generic 64-bit floating point "/2addr" binary operation. Provide 6290 * an "instr" line that specifies an instruction that performs 6291 * "d2 = d0 op d1". 6292 * 6293 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6294 * div-double/2addr 6295 */ 6296 /* binop/2addr vA, vB */ 6297 mov r3, rINST, lsr #12 @ r3<- B 6298 mov r9, rINST, lsr #8 @ r9<- A+ 6299 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6300 and r9, r9, #15 @ r9<- A 6301 fldd d1, [r3] @ d1<- vB 6302 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6303 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6304 fldd d0, [r9] @ d0<- vA 6305 6306 faddd d2, d0, d1 @ d2<- op 6307 GET_INST_OPCODE(ip) @ extract opcode from rINST 6308 fstd d2, [r9] @ vAA<- d2 6309 GOTO_OPCODE(ip) @ jump to next instruction 6310 6311 6312/* ------------------------------ */ 6313 .balign 64 6314.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6315/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */ 6316/* File: arm-vfp/fbinopWide2addr.S */ 6317 /* 6318 * Generic 64-bit floating point "/2addr" binary operation. Provide 6319 * an "instr" line that specifies an instruction that performs 6320 * "d2 = d0 op d1". 6321 * 6322 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6323 * div-double/2addr 6324 */ 6325 /* binop/2addr vA, vB */ 6326 mov r3, rINST, lsr #12 @ r3<- B 6327 mov r9, rINST, lsr #8 @ r9<- A+ 6328 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6329 and r9, r9, #15 @ r9<- A 6330 fldd d1, [r3] @ d1<- vB 6331 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6332 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6333 fldd d0, [r9] @ d0<- vA 6334 6335 fsubd d2, d0, d1 @ d2<- op 6336 GET_INST_OPCODE(ip) @ extract opcode from rINST 6337 fstd d2, [r9] @ vAA<- d2 6338 GOTO_OPCODE(ip) @ jump to next instruction 6339 6340 6341/* ------------------------------ */ 6342 .balign 64 6343.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6344/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */ 6345/* File: arm-vfp/fbinopWide2addr.S */ 6346 /* 6347 * Generic 64-bit floating point "/2addr" binary operation. Provide 6348 * an "instr" line that specifies an instruction that performs 6349 * "d2 = d0 op d1". 6350 * 6351 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6352 * div-double/2addr 6353 */ 6354 /* binop/2addr vA, vB */ 6355 mov r3, rINST, lsr #12 @ r3<- B 6356 mov r9, rINST, lsr #8 @ r9<- A+ 6357 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6358 and r9, r9, #15 @ r9<- A 6359 fldd d1, [r3] @ d1<- vB 6360 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6361 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6362 fldd d0, [r9] @ d0<- vA 6363 6364 fmuld d2, d0, d1 @ d2<- op 6365 GET_INST_OPCODE(ip) @ extract opcode from rINST 6366 fstd d2, [r9] @ vAA<- d2 6367 GOTO_OPCODE(ip) @ jump to next instruction 6368 6369 6370/* ------------------------------ */ 6371 .balign 64 6372.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6373/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */ 6374/* File: arm-vfp/fbinopWide2addr.S */ 6375 /* 6376 * Generic 64-bit floating point "/2addr" binary operation. Provide 6377 * an "instr" line that specifies an instruction that performs 6378 * "d2 = d0 op d1". 6379 * 6380 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6381 * div-double/2addr 6382 */ 6383 /* binop/2addr vA, vB */ 6384 mov r3, rINST, lsr #12 @ r3<- B 6385 mov r9, rINST, lsr #8 @ r9<- A+ 6386 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6387 and r9, r9, #15 @ r9<- A 6388 fldd d1, [r3] @ d1<- vB 6389 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6390 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6391 fldd d0, [r9] @ d0<- vA 6392 6393 fdivd d2, d0, d1 @ d2<- op 6394 GET_INST_OPCODE(ip) @ extract opcode from rINST 6395 fstd d2, [r9] @ vAA<- d2 6396 GOTO_OPCODE(ip) @ jump to next instruction 6397 6398 6399/* ------------------------------ */ 6400 .balign 64 6401.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6402/* File: armv6t2/OP_REM_DOUBLE_2ADDR.S */ 6403/* EABI doesn't define a double remainder function, but libm does */ 6404/* File: armv6t2/binopWide2addr.S */ 6405 /* 6406 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6407 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6408 * This could be an ARM instruction or a function call. (If the result 6409 * comes back in a register other than r0, you can override "result".) 6410 * 6411 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6412 * vCC (r1). Useful for integer division and modulus. 6413 * 6414 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6415 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6416 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6417 * rem-double/2addr 6418 */ 6419 /* binop/2addr vA, vB */ 6420 mov r1, rINST, lsr #12 @ r1<- B 6421 ubfx r9, rINST, #8, #4 @ r9<- A 6422 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6423 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6424 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6425 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6426 .if 0 6427 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6428 beq common_errDivideByZero 6429 .endif 6430 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6431 6432 @ optional op; may set condition codes 6433 bl fmod @ result<- op, r0-r3 changed 6434 GET_INST_OPCODE(ip) @ extract opcode from rINST 6435 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6436 GOTO_OPCODE(ip) @ jump to next instruction 6437 /* 12-15 instructions */ 6438 6439 6440 6441/* ------------------------------ */ 6442 .balign 64 6443.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6444/* File: armv6t2/OP_ADD_INT_LIT16.S */ 6445/* File: armv6t2/binopLit16.S */ 6446 /* 6447 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6448 * that specifies an instruction that performs "result = r0 op r1". 6449 * This could be an ARM instruction or a function call. (If the result 6450 * comes back in a register other than r0, you can override "result".) 6451 * 6452 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6453 * vCC (r1). Useful for integer division and modulus. 6454 * 6455 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6456 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6457 */ 6458 /* binop/lit16 vA, vB, #+CCCC */ 6459 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6460 mov r2, rINST, lsr #12 @ r2<- B 6461 ubfx r9, rINST, #8, #4 @ r9<- A 6462 GET_VREG(r0, r2) @ r0<- vB 6463 .if 0 6464 cmp r1, #0 @ is second operand zero? 6465 beq common_errDivideByZero 6466 .endif 6467 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6468 6469 add r0, r0, r1 @ r0<- op, r0-r3 changed 6470 GET_INST_OPCODE(ip) @ extract opcode from rINST 6471 SET_VREG(r0, r9) @ vAA<- r0 6472 GOTO_OPCODE(ip) @ jump to next instruction 6473 /* 10-13 instructions */ 6474 6475 6476 6477/* ------------------------------ */ 6478 .balign 64 6479.L_OP_RSUB_INT: /* 0xd1 */ 6480/* File: armv6t2/OP_RSUB_INT.S */ 6481/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6482/* File: armv6t2/binopLit16.S */ 6483 /* 6484 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6485 * that specifies an instruction that performs "result = r0 op r1". 6486 * This could be an ARM instruction or a function call. (If the result 6487 * comes back in a register other than r0, you can override "result".) 6488 * 6489 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6490 * vCC (r1). Useful for integer division and modulus. 6491 * 6492 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6493 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6494 */ 6495 /* binop/lit16 vA, vB, #+CCCC */ 6496 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6497 mov r2, rINST, lsr #12 @ r2<- B 6498 ubfx r9, rINST, #8, #4 @ r9<- A 6499 GET_VREG(r0, r2) @ r0<- vB 6500 .if 0 6501 cmp r1, #0 @ is second operand zero? 6502 beq common_errDivideByZero 6503 .endif 6504 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6505 6506 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6507 GET_INST_OPCODE(ip) @ extract opcode from rINST 6508 SET_VREG(r0, r9) @ vAA<- r0 6509 GOTO_OPCODE(ip) @ jump to next instruction 6510 /* 10-13 instructions */ 6511 6512 6513 6514/* ------------------------------ */ 6515 .balign 64 6516.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6517/* File: armv6t2/OP_MUL_INT_LIT16.S */ 6518/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6519/* File: armv6t2/binopLit16.S */ 6520 /* 6521 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6522 * that specifies an instruction that performs "result = r0 op r1". 6523 * This could be an ARM instruction or a function call. (If the result 6524 * comes back in a register other than r0, you can override "result".) 6525 * 6526 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6527 * vCC (r1). Useful for integer division and modulus. 6528 * 6529 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6530 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6531 */ 6532 /* binop/lit16 vA, vB, #+CCCC */ 6533 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6534 mov r2, rINST, lsr #12 @ r2<- B 6535 ubfx r9, rINST, #8, #4 @ r9<- A 6536 GET_VREG(r0, r2) @ r0<- vB 6537 .if 0 6538 cmp r1, #0 @ is second operand zero? 6539 beq common_errDivideByZero 6540 .endif 6541 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6542 6543 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6544 GET_INST_OPCODE(ip) @ extract opcode from rINST 6545 SET_VREG(r0, r9) @ vAA<- r0 6546 GOTO_OPCODE(ip) @ jump to next instruction 6547 /* 10-13 instructions */ 6548 6549 6550 6551/* ------------------------------ */ 6552 .balign 64 6553.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6554/* File: armv6t2/OP_DIV_INT_LIT16.S */ 6555/* File: armv6t2/binopLit16.S */ 6556 /* 6557 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6558 * that specifies an instruction that performs "result = r0 op r1". 6559 * This could be an ARM instruction or a function call. (If the result 6560 * comes back in a register other than r0, you can override "result".) 6561 * 6562 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6563 * vCC (r1). Useful for integer division and modulus. 6564 * 6565 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6566 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6567 */ 6568 /* binop/lit16 vA, vB, #+CCCC */ 6569 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6570 mov r2, rINST, lsr #12 @ r2<- B 6571 ubfx r9, rINST, #8, #4 @ r9<- A 6572 GET_VREG(r0, r2) @ r0<- vB 6573 .if 1 6574 cmp r1, #0 @ is second operand zero? 6575 beq common_errDivideByZero 6576 .endif 6577 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6578 6579 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6580 GET_INST_OPCODE(ip) @ extract opcode from rINST 6581 SET_VREG(r0, r9) @ vAA<- r0 6582 GOTO_OPCODE(ip) @ jump to next instruction 6583 /* 10-13 instructions */ 6584 6585 6586 6587/* ------------------------------ */ 6588 .balign 64 6589.L_OP_REM_INT_LIT16: /* 0xd4 */ 6590/* File: armv6t2/OP_REM_INT_LIT16.S */ 6591/* idivmod returns quotient in r0 and remainder in r1 */ 6592/* File: armv6t2/binopLit16.S */ 6593 /* 6594 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6595 * that specifies an instruction that performs "result = r0 op r1". 6596 * This could be an ARM instruction or a function call. (If the result 6597 * comes back in a register other than r0, you can override "result".) 6598 * 6599 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6600 * vCC (r1). Useful for integer division and modulus. 6601 * 6602 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6603 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6604 */ 6605 /* binop/lit16 vA, vB, #+CCCC */ 6606 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6607 mov r2, rINST, lsr #12 @ r2<- B 6608 ubfx r9, rINST, #8, #4 @ r9<- A 6609 GET_VREG(r0, r2) @ r0<- vB 6610 .if 1 6611 cmp r1, #0 @ is second operand zero? 6612 beq common_errDivideByZero 6613 .endif 6614 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6615 6616 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6617 GET_INST_OPCODE(ip) @ extract opcode from rINST 6618 SET_VREG(r1, r9) @ vAA<- r1 6619 GOTO_OPCODE(ip) @ jump to next instruction 6620 /* 10-13 instructions */ 6621 6622 6623 6624/* ------------------------------ */ 6625 .balign 64 6626.L_OP_AND_INT_LIT16: /* 0xd5 */ 6627/* File: armv6t2/OP_AND_INT_LIT16.S */ 6628/* File: armv6t2/binopLit16.S */ 6629 /* 6630 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6631 * that specifies an instruction that performs "result = r0 op r1". 6632 * This could be an ARM instruction or a function call. (If the result 6633 * comes back in a register other than r0, you can override "result".) 6634 * 6635 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6636 * vCC (r1). Useful for integer division and modulus. 6637 * 6638 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6639 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6640 */ 6641 /* binop/lit16 vA, vB, #+CCCC */ 6642 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6643 mov r2, rINST, lsr #12 @ r2<- B 6644 ubfx r9, rINST, #8, #4 @ r9<- A 6645 GET_VREG(r0, r2) @ r0<- vB 6646 .if 0 6647 cmp r1, #0 @ is second operand zero? 6648 beq common_errDivideByZero 6649 .endif 6650 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6651 6652 and r0, r0, r1 @ r0<- op, r0-r3 changed 6653 GET_INST_OPCODE(ip) @ extract opcode from rINST 6654 SET_VREG(r0, r9) @ vAA<- r0 6655 GOTO_OPCODE(ip) @ jump to next instruction 6656 /* 10-13 instructions */ 6657 6658 6659 6660/* ------------------------------ */ 6661 .balign 64 6662.L_OP_OR_INT_LIT16: /* 0xd6 */ 6663/* File: armv6t2/OP_OR_INT_LIT16.S */ 6664/* File: armv6t2/binopLit16.S */ 6665 /* 6666 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6667 * that specifies an instruction that performs "result = r0 op r1". 6668 * This could be an ARM instruction or a function call. (If the result 6669 * comes back in a register other than r0, you can override "result".) 6670 * 6671 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6672 * vCC (r1). Useful for integer division and modulus. 6673 * 6674 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6675 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6676 */ 6677 /* binop/lit16 vA, vB, #+CCCC */ 6678 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6679 mov r2, rINST, lsr #12 @ r2<- B 6680 ubfx r9, rINST, #8, #4 @ r9<- A 6681 GET_VREG(r0, r2) @ r0<- vB 6682 .if 0 6683 cmp r1, #0 @ is second operand zero? 6684 beq common_errDivideByZero 6685 .endif 6686 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6687 6688 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6689 GET_INST_OPCODE(ip) @ extract opcode from rINST 6690 SET_VREG(r0, r9) @ vAA<- r0 6691 GOTO_OPCODE(ip) @ jump to next instruction 6692 /* 10-13 instructions */ 6693 6694 6695 6696/* ------------------------------ */ 6697 .balign 64 6698.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6699/* File: armv6t2/OP_XOR_INT_LIT16.S */ 6700/* File: armv6t2/binopLit16.S */ 6701 /* 6702 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6703 * that specifies an instruction that performs "result = r0 op r1". 6704 * This could be an ARM instruction or a function call. (If the result 6705 * comes back in a register other than r0, you can override "result".) 6706 * 6707 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6708 * vCC (r1). Useful for integer division and modulus. 6709 * 6710 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6711 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6712 */ 6713 /* binop/lit16 vA, vB, #+CCCC */ 6714 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6715 mov r2, rINST, lsr #12 @ r2<- B 6716 ubfx r9, rINST, #8, #4 @ r9<- A 6717 GET_VREG(r0, r2) @ r0<- vB 6718 .if 0 6719 cmp r1, #0 @ is second operand zero? 6720 beq common_errDivideByZero 6721 .endif 6722 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6723 6724 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6725 GET_INST_OPCODE(ip) @ extract opcode from rINST 6726 SET_VREG(r0, r9) @ vAA<- r0 6727 GOTO_OPCODE(ip) @ jump to next instruction 6728 /* 10-13 instructions */ 6729 6730 6731 6732/* ------------------------------ */ 6733 .balign 64 6734.L_OP_ADD_INT_LIT8: /* 0xd8 */ 6735/* File: armv5te/OP_ADD_INT_LIT8.S */ 6736/* File: armv5te/binopLit8.S */ 6737 /* 6738 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6739 * that specifies an instruction that performs "result = r0 op r1". 6740 * This could be an ARM instruction or a function call. (If the result 6741 * comes back in a register other than r0, you can override "result".) 6742 * 6743 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6744 * vCC (r1). Useful for integer division and modulus. 6745 * 6746 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6747 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6748 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6749 */ 6750 /* binop/lit8 vAA, vBB, #+CC */ 6751 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6752 mov r9, rINST, lsr #8 @ r9<- AA 6753 and r2, r3, #255 @ r2<- BB 6754 GET_VREG(r0, r2) @ r0<- vBB 6755 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6756 .if 0 6757 @cmp r1, #0 @ is second operand zero? 6758 beq common_errDivideByZero 6759 .endif 6760 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6761 6762 @ optional op; may set condition codes 6763 add r0, r0, r1 @ r0<- op, r0-r3 changed 6764 GET_INST_OPCODE(ip) @ extract opcode from rINST 6765 SET_VREG(r0, r9) @ vAA<- r0 6766 GOTO_OPCODE(ip) @ jump to next instruction 6767 /* 10-12 instructions */ 6768 6769 6770 6771/* ------------------------------ */ 6772 .balign 64 6773.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 6774/* File: armv5te/OP_RSUB_INT_LIT8.S */ 6775/* File: armv5te/binopLit8.S */ 6776 /* 6777 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6778 * that specifies an instruction that performs "result = r0 op r1". 6779 * This could be an ARM instruction or a function call. (If the result 6780 * comes back in a register other than r0, you can override "result".) 6781 * 6782 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6783 * vCC (r1). Useful for integer division and modulus. 6784 * 6785 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6786 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6787 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6788 */ 6789 /* binop/lit8 vAA, vBB, #+CC */ 6790 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6791 mov r9, rINST, lsr #8 @ r9<- AA 6792 and r2, r3, #255 @ r2<- BB 6793 GET_VREG(r0, r2) @ r0<- vBB 6794 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6795 .if 0 6796 @cmp r1, #0 @ is second operand zero? 6797 beq common_errDivideByZero 6798 .endif 6799 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6800 6801 @ optional op; may set condition codes 6802 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6803 GET_INST_OPCODE(ip) @ extract opcode from rINST 6804 SET_VREG(r0, r9) @ vAA<- r0 6805 GOTO_OPCODE(ip) @ jump to next instruction 6806 /* 10-12 instructions */ 6807 6808 6809 6810/* ------------------------------ */ 6811 .balign 64 6812.L_OP_MUL_INT_LIT8: /* 0xda */ 6813/* File: armv5te/OP_MUL_INT_LIT8.S */ 6814/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6815/* File: armv5te/binopLit8.S */ 6816 /* 6817 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6818 * that specifies an instruction that performs "result = r0 op r1". 6819 * This could be an ARM instruction or a function call. (If the result 6820 * comes back in a register other than r0, you can override "result".) 6821 * 6822 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6823 * vCC (r1). Useful for integer division and modulus. 6824 * 6825 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6826 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6827 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6828 */ 6829 /* binop/lit8 vAA, vBB, #+CC */ 6830 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6831 mov r9, rINST, lsr #8 @ r9<- AA 6832 and r2, r3, #255 @ r2<- BB 6833 GET_VREG(r0, r2) @ r0<- vBB 6834 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6835 .if 0 6836 @cmp r1, #0 @ is second operand zero? 6837 beq common_errDivideByZero 6838 .endif 6839 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6840 6841 @ optional op; may set condition codes 6842 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6843 GET_INST_OPCODE(ip) @ extract opcode from rINST 6844 SET_VREG(r0, r9) @ vAA<- r0 6845 GOTO_OPCODE(ip) @ jump to next instruction 6846 /* 10-12 instructions */ 6847 6848 6849 6850/* ------------------------------ */ 6851 .balign 64 6852.L_OP_DIV_INT_LIT8: /* 0xdb */ 6853/* File: armv5te/OP_DIV_INT_LIT8.S */ 6854/* File: armv5te/binopLit8.S */ 6855 /* 6856 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6857 * that specifies an instruction that performs "result = r0 op r1". 6858 * This could be an ARM instruction or a function call. (If the result 6859 * comes back in a register other than r0, you can override "result".) 6860 * 6861 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6862 * vCC (r1). Useful for integer division and modulus. 6863 * 6864 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6865 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6866 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6867 */ 6868 /* binop/lit8 vAA, vBB, #+CC */ 6869 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6870 mov r9, rINST, lsr #8 @ r9<- AA 6871 and r2, r3, #255 @ r2<- BB 6872 GET_VREG(r0, r2) @ r0<- vBB 6873 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6874 .if 1 6875 @cmp r1, #0 @ is second operand zero? 6876 beq common_errDivideByZero 6877 .endif 6878 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6879 6880 @ optional op; may set condition codes 6881 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6882 GET_INST_OPCODE(ip) @ extract opcode from rINST 6883 SET_VREG(r0, r9) @ vAA<- r0 6884 GOTO_OPCODE(ip) @ jump to next instruction 6885 /* 10-12 instructions */ 6886 6887 6888 6889/* ------------------------------ */ 6890 .balign 64 6891.L_OP_REM_INT_LIT8: /* 0xdc */ 6892/* File: armv5te/OP_REM_INT_LIT8.S */ 6893/* idivmod returns quotient in r0 and remainder in r1 */ 6894/* File: armv5te/binopLit8.S */ 6895 /* 6896 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6897 * that specifies an instruction that performs "result = r0 op r1". 6898 * This could be an ARM instruction or a function call. (If the result 6899 * comes back in a register other than r0, you can override "result".) 6900 * 6901 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6902 * vCC (r1). Useful for integer division and modulus. 6903 * 6904 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6905 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6906 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6907 */ 6908 /* binop/lit8 vAA, vBB, #+CC */ 6909 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6910 mov r9, rINST, lsr #8 @ r9<- AA 6911 and r2, r3, #255 @ r2<- BB 6912 GET_VREG(r0, r2) @ r0<- vBB 6913 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6914 .if 1 6915 @cmp r1, #0 @ is second operand zero? 6916 beq common_errDivideByZero 6917 .endif 6918 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6919 6920 @ optional op; may set condition codes 6921 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6922 GET_INST_OPCODE(ip) @ extract opcode from rINST 6923 SET_VREG(r1, r9) @ vAA<- r1 6924 GOTO_OPCODE(ip) @ jump to next instruction 6925 /* 10-12 instructions */ 6926 6927 6928 6929/* ------------------------------ */ 6930 .balign 64 6931.L_OP_AND_INT_LIT8: /* 0xdd */ 6932/* File: armv5te/OP_AND_INT_LIT8.S */ 6933/* File: armv5te/binopLit8.S */ 6934 /* 6935 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6936 * that specifies an instruction that performs "result = r0 op r1". 6937 * This could be an ARM instruction or a function call. (If the result 6938 * comes back in a register other than r0, you can override "result".) 6939 * 6940 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6941 * vCC (r1). Useful for integer division and modulus. 6942 * 6943 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6944 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6945 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6946 */ 6947 /* binop/lit8 vAA, vBB, #+CC */ 6948 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6949 mov r9, rINST, lsr #8 @ r9<- AA 6950 and r2, r3, #255 @ r2<- BB 6951 GET_VREG(r0, r2) @ r0<- vBB 6952 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6953 .if 0 6954 @cmp r1, #0 @ is second operand zero? 6955 beq common_errDivideByZero 6956 .endif 6957 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6958 6959 @ optional op; may set condition codes 6960 and r0, r0, r1 @ r0<- op, r0-r3 changed 6961 GET_INST_OPCODE(ip) @ extract opcode from rINST 6962 SET_VREG(r0, r9) @ vAA<- r0 6963 GOTO_OPCODE(ip) @ jump to next instruction 6964 /* 10-12 instructions */ 6965 6966 6967 6968/* ------------------------------ */ 6969 .balign 64 6970.L_OP_OR_INT_LIT8: /* 0xde */ 6971/* File: armv5te/OP_OR_INT_LIT8.S */ 6972/* File: armv5te/binopLit8.S */ 6973 /* 6974 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6975 * that specifies an instruction that performs "result = r0 op r1". 6976 * This could be an ARM instruction or a function call. (If the result 6977 * comes back in a register other than r0, you can override "result".) 6978 * 6979 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6980 * vCC (r1). Useful for integer division and modulus. 6981 * 6982 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6983 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6984 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6985 */ 6986 /* binop/lit8 vAA, vBB, #+CC */ 6987 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6988 mov r9, rINST, lsr #8 @ r9<- AA 6989 and r2, r3, #255 @ r2<- BB 6990 GET_VREG(r0, r2) @ r0<- vBB 6991 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6992 .if 0 6993 @cmp r1, #0 @ is second operand zero? 6994 beq common_errDivideByZero 6995 .endif 6996 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6997 6998 @ optional op; may set condition codes 6999 orr r0, r0, r1 @ r0<- op, r0-r3 changed 7000 GET_INST_OPCODE(ip) @ extract opcode from rINST 7001 SET_VREG(r0, r9) @ vAA<- r0 7002 GOTO_OPCODE(ip) @ jump to next instruction 7003 /* 10-12 instructions */ 7004 7005 7006 7007/* ------------------------------ */ 7008 .balign 64 7009.L_OP_XOR_INT_LIT8: /* 0xdf */ 7010/* File: armv5te/OP_XOR_INT_LIT8.S */ 7011/* File: armv5te/binopLit8.S */ 7012 /* 7013 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7014 * that specifies an instruction that performs "result = r0 op r1". 7015 * This could be an ARM instruction or a function call. (If the result 7016 * comes back in a register other than r0, you can override "result".) 7017 * 7018 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7019 * vCC (r1). Useful for integer division and modulus. 7020 * 7021 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7022 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7023 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7024 */ 7025 /* binop/lit8 vAA, vBB, #+CC */ 7026 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7027 mov r9, rINST, lsr #8 @ r9<- AA 7028 and r2, r3, #255 @ r2<- BB 7029 GET_VREG(r0, r2) @ r0<- vBB 7030 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7031 .if 0 7032 @cmp r1, #0 @ is second operand zero? 7033 beq common_errDivideByZero 7034 .endif 7035 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7036 7037 @ optional op; may set condition codes 7038 eor r0, r0, r1 @ r0<- op, r0-r3 changed 7039 GET_INST_OPCODE(ip) @ extract opcode from rINST 7040 SET_VREG(r0, r9) @ vAA<- r0 7041 GOTO_OPCODE(ip) @ jump to next instruction 7042 /* 10-12 instructions */ 7043 7044 7045 7046/* ------------------------------ */ 7047 .balign 64 7048.L_OP_SHL_INT_LIT8: /* 0xe0 */ 7049/* File: armv5te/OP_SHL_INT_LIT8.S */ 7050/* File: armv5te/binopLit8.S */ 7051 /* 7052 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7053 * that specifies an instruction that performs "result = r0 op r1". 7054 * This could be an ARM instruction or a function call. (If the result 7055 * comes back in a register other than r0, you can override "result".) 7056 * 7057 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7058 * vCC (r1). Useful for integer division and modulus. 7059 * 7060 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7061 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7062 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7063 */ 7064 /* binop/lit8 vAA, vBB, #+CC */ 7065 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7066 mov r9, rINST, lsr #8 @ r9<- AA 7067 and r2, r3, #255 @ r2<- BB 7068 GET_VREG(r0, r2) @ r0<- vBB 7069 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7070 .if 0 7071 @cmp r1, #0 @ is second operand zero? 7072 beq common_errDivideByZero 7073 .endif 7074 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7075 7076 and r1, r1, #31 @ optional op; may set condition codes 7077 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 7078 GET_INST_OPCODE(ip) @ extract opcode from rINST 7079 SET_VREG(r0, r9) @ vAA<- r0 7080 GOTO_OPCODE(ip) @ jump to next instruction 7081 /* 10-12 instructions */ 7082 7083 7084 7085/* ------------------------------ */ 7086 .balign 64 7087.L_OP_SHR_INT_LIT8: /* 0xe1 */ 7088/* File: armv5te/OP_SHR_INT_LIT8.S */ 7089/* File: armv5te/binopLit8.S */ 7090 /* 7091 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7092 * that specifies an instruction that performs "result = r0 op r1". 7093 * This could be an ARM instruction or a function call. (If the result 7094 * comes back in a register other than r0, you can override "result".) 7095 * 7096 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7097 * vCC (r1). Useful for integer division and modulus. 7098 * 7099 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7100 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7101 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7102 */ 7103 /* binop/lit8 vAA, vBB, #+CC */ 7104 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7105 mov r9, rINST, lsr #8 @ r9<- AA 7106 and r2, r3, #255 @ r2<- BB 7107 GET_VREG(r0, r2) @ r0<- vBB 7108 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7109 .if 0 7110 @cmp r1, #0 @ is second operand zero? 7111 beq common_errDivideByZero 7112 .endif 7113 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7114 7115 and r1, r1, #31 @ optional op; may set condition codes 7116 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7117 GET_INST_OPCODE(ip) @ extract opcode from rINST 7118 SET_VREG(r0, r9) @ vAA<- r0 7119 GOTO_OPCODE(ip) @ jump to next instruction 7120 /* 10-12 instructions */ 7121 7122 7123 7124/* ------------------------------ */ 7125 .balign 64 7126.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7127/* File: armv5te/OP_USHR_INT_LIT8.S */ 7128/* File: armv5te/binopLit8.S */ 7129 /* 7130 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7131 * that specifies an instruction that performs "result = r0 op r1". 7132 * This could be an ARM instruction or a function call. (If the result 7133 * comes back in a register other than r0, you can override "result".) 7134 * 7135 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7136 * vCC (r1). Useful for integer division and modulus. 7137 * 7138 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7139 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7140 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7141 */ 7142 /* binop/lit8 vAA, vBB, #+CC */ 7143 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7144 mov r9, rINST, lsr #8 @ r9<- AA 7145 and r2, r3, #255 @ r2<- BB 7146 GET_VREG(r0, r2) @ r0<- vBB 7147 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7148 .if 0 7149 @cmp r1, #0 @ is second operand zero? 7150 beq common_errDivideByZero 7151 .endif 7152 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7153 7154 and r1, r1, #31 @ optional op; may set condition codes 7155 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7156 GET_INST_OPCODE(ip) @ extract opcode from rINST 7157 SET_VREG(r0, r9) @ vAA<- r0 7158 GOTO_OPCODE(ip) @ jump to next instruction 7159 /* 10-12 instructions */ 7160 7161 7162 7163/* ------------------------------ */ 7164 .balign 64 7165.L_OP_UNUSED_E3: /* 0xe3 */ 7166/* File: armv5te/OP_UNUSED_E3.S */ 7167/* File: armv5te/unused.S */ 7168 bl common_abort 7169 7170 7171 7172/* ------------------------------ */ 7173 .balign 64 7174.L_OP_UNUSED_E4: /* 0xe4 */ 7175/* File: armv5te/OP_UNUSED_E4.S */ 7176/* File: armv5te/unused.S */ 7177 bl common_abort 7178 7179 7180 7181/* ------------------------------ */ 7182 .balign 64 7183.L_OP_UNUSED_E5: /* 0xe5 */ 7184/* File: armv5te/OP_UNUSED_E5.S */ 7185/* File: armv5te/unused.S */ 7186 bl common_abort 7187 7188 7189 7190/* ------------------------------ */ 7191 .balign 64 7192.L_OP_UNUSED_E6: /* 0xe6 */ 7193/* File: armv5te/OP_UNUSED_E6.S */ 7194/* File: armv5te/unused.S */ 7195 bl common_abort 7196 7197 7198 7199/* ------------------------------ */ 7200 .balign 64 7201.L_OP_UNUSED_E7: /* 0xe7 */ 7202/* File: armv5te/OP_UNUSED_E7.S */ 7203/* File: armv5te/unused.S */ 7204 bl common_abort 7205 7206 7207 7208/* ------------------------------ */ 7209 .balign 64 7210.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */ 7211/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */ 7212/* File: armv5te/OP_IGET_WIDE.S */ 7213 /* 7214 * Wide 32-bit instance field get. 7215 */ 7216 /* iget-wide vA, vB, field@CCCC */ 7217 mov r0, rINST, lsr #12 @ r0<- B 7218 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7219 FETCH(r1, 1) @ r1<- field ref CCCC 7220 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7221 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7222 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7223 cmp r0, #0 @ is resolved entry null? 7224 bne .LOP_IGET_WIDE_VOLATILE_finish @ no, already resolved 72258: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7226 EXPORT_PC() @ resolve() could throw 7227 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7228 bl dvmResolveInstField @ r0<- resolved InstField ptr 7229 cmp r0, #0 7230 bne .LOP_IGET_WIDE_VOLATILE_finish 7231 b common_exceptionThrown 7232 7233 7234/* ------------------------------ */ 7235 .balign 64 7236.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */ 7237/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */ 7238/* File: armv5te/OP_IPUT_WIDE.S */ 7239 /* iput-wide vA, vB, field@CCCC */ 7240 mov r0, rINST, lsr #12 @ r0<- B 7241 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7242 FETCH(r1, 1) @ r1<- field ref CCCC 7243 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7244 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7245 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7246 cmp r0, #0 @ is resolved entry null? 7247 bne .LOP_IPUT_WIDE_VOLATILE_finish @ no, already resolved 72488: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7249 EXPORT_PC() @ resolve() could throw 7250 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7251 bl dvmResolveInstField @ r0<- resolved InstField ptr 7252 cmp r0, #0 @ success? 7253 bne .LOP_IPUT_WIDE_VOLATILE_finish @ yes, finish up 7254 b common_exceptionThrown 7255 7256 7257/* ------------------------------ */ 7258 .balign 64 7259.L_OP_SGET_WIDE_VOLATILE: /* 0xea */ 7260/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */ 7261/* File: armv5te/OP_SGET_WIDE.S */ 7262 /* 7263 * 64-bit SGET handler. 7264 */ 7265 /* sget-wide vAA, field@BBBB */ 7266 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7267 FETCH(r1, 1) @ r1<- field ref BBBB 7268 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7269 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7270 cmp r0, #0 @ is resolved entry null? 7271 beq .LOP_SGET_WIDE_VOLATILE_resolve @ yes, do resolve 7272.LOP_SGET_WIDE_VOLATILE_finish: 7273 mov r9, rINST, lsr #8 @ r9<- AA 7274 .if 1 7275 add r0, r0, #offStaticField_value @ r0<- pointer to data 7276 bl android_quasiatomic_read_64 @ r0/r1<- contents of field 7277 .else 7278 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 7279 .endif 7280 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7281 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7282 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 7283 GET_INST_OPCODE(ip) @ extract opcode from rINST 7284 GOTO_OPCODE(ip) @ jump to next instruction 7285 7286 7287/* ------------------------------ */ 7288 .balign 64 7289.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */ 7290/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */ 7291/* File: armv5te/OP_SPUT_WIDE.S */ 7292 /* 7293 * 64-bit SPUT handler. 7294 */ 7295 /* sput-wide vAA, field@BBBB */ 7296 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 7297 FETCH(r1, 1) @ r1<- field ref BBBB 7298 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 7299 mov r9, rINST, lsr #8 @ r9<- AA 7300 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 7301 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7302 cmp r2, #0 @ is resolved entry null? 7303 beq .LOP_SPUT_WIDE_VOLATILE_resolve @ yes, do resolve 7304.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9 7305 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7306 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 7307 GET_INST_OPCODE(r10) @ extract opcode from rINST 7308 .if 1 7309 add r2, r2, #offStaticField_value @ r2<- pointer to data 7310 bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2 7311 .else 7312 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 7313 .endif 7314 GOTO_OPCODE(r10) @ jump to next instruction 7315 7316 7317/* ------------------------------ */ 7318 .balign 64 7319.L_OP_BREAKPOINT: /* 0xec */ 7320/* File: armv5te/OP_BREAKPOINT.S */ 7321/* File: armv5te/unused.S */ 7322 bl common_abort 7323 7324 7325 7326/* ------------------------------ */ 7327 .balign 64 7328.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7329/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7330 /* 7331 * Handle a throw-verification-error instruction. This throws an 7332 * exception for an error discovered during verification. The 7333 * exception is indicated by AA, with some detail provided by BBBB. 7334 */ 7335 /* op AA, ref@BBBB */ 7336 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7337 FETCH(r2, 1) @ r2<- BBBB 7338 EXPORT_PC() @ export the PC 7339 mov r1, rINST, lsr #8 @ r1<- AA 7340 bl dvmThrowVerificationError @ always throws 7341 b common_exceptionThrown @ handle exception 7342 7343 7344/* ------------------------------ */ 7345 .balign 64 7346.L_OP_EXECUTE_INLINE: /* 0xee */ 7347/* File: armv5te/OP_EXECUTE_INLINE.S */ 7348 /* 7349 * Execute a "native inline" instruction. 7350 * 7351 * We need to call an InlineOp4Func: 7352 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7353 * 7354 * The first four args are in r0-r3, pointer to return value storage 7355 * is on the stack. The function's return value is a flag that tells 7356 * us if an exception was thrown. 7357 */ 7358 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7359 FETCH(r10, 1) @ r10<- BBBB 7360 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7361 EXPORT_PC() @ can throw 7362 sub sp, sp, #8 @ make room for arg, +64 bit align 7363 mov r0, rINST, lsr #12 @ r0<- B 7364 str r1, [sp] @ push &glue->retval 7365 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7366 add sp, sp, #8 @ pop stack 7367 cmp r0, #0 @ test boolean result of inline 7368 beq common_exceptionThrown @ returned false, handle exception 7369 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7370 GET_INST_OPCODE(ip) @ extract opcode from rINST 7371 GOTO_OPCODE(ip) @ jump to next instruction 7372 7373/* ------------------------------ */ 7374 .balign 64 7375.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ 7376/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */ 7377 /* 7378 * Execute a "native inline" instruction, using "/range" semantics. 7379 * Same idea as execute-inline, but we get the args differently. 7380 * 7381 * We need to call an InlineOp4Func: 7382 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7383 * 7384 * The first four args are in r0-r3, pointer to return value storage 7385 * is on the stack. The function's return value is a flag that tells 7386 * us if an exception was thrown. 7387 */ 7388 /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */ 7389 FETCH(r10, 1) @ r10<- BBBB 7390 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7391 EXPORT_PC() @ can throw 7392 sub sp, sp, #8 @ make room for arg, +64 bit align 7393 mov r0, rINST, lsr #8 @ r0<- AA 7394 str r1, [sp] @ push &glue->retval 7395 bl .LOP_EXECUTE_INLINE_RANGE_continue @ make call; will return after 7396 add sp, sp, #8 @ pop stack 7397 cmp r0, #0 @ test boolean result of inline 7398 beq common_exceptionThrown @ returned false, handle exception 7399 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7400 GET_INST_OPCODE(ip) @ extract opcode from rINST 7401 GOTO_OPCODE(ip) @ jump to next instruction 7402 7403/* ------------------------------ */ 7404 .balign 64 7405.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7406/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7407 /* 7408 * invoke-direct-empty is a no-op in a "standard" interpreter. 7409 */ 7410 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7411 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7412 GOTO_OPCODE(ip) @ execute it 7413 7414/* ------------------------------ */ 7415 .balign 64 7416.L_OP_UNUSED_F1: /* 0xf1 */ 7417/* File: armv5te/OP_UNUSED_F1.S */ 7418/* File: armv5te/unused.S */ 7419 bl common_abort 7420 7421 7422 7423/* ------------------------------ */ 7424 .balign 64 7425.L_OP_IGET_QUICK: /* 0xf2 */ 7426/* File: armv6t2/OP_IGET_QUICK.S */ 7427 /* For: iget-quick, iget-object-quick */ 7428 /* op vA, vB, offset@CCCC */ 7429 mov r2, rINST, lsr #12 @ r2<- B 7430 FETCH(r1, 1) @ r1<- field byte offset 7431 GET_VREG(r3, r2) @ r3<- object we're operating on 7432 ubfx r2, rINST, #8, #4 @ r2<- A 7433 cmp r3, #0 @ check object for null 7434 beq common_errNullObject @ object was null 7435 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7436 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7437 GET_INST_OPCODE(ip) @ extract opcode from rINST 7438 SET_VREG(r0, r2) @ fp[A]<- r0 7439 GOTO_OPCODE(ip) @ jump to next instruction 7440 7441 7442/* ------------------------------ */ 7443 .balign 64 7444.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7445/* File: armv6t2/OP_IGET_WIDE_QUICK.S */ 7446 /* iget-wide-quick vA, vB, offset@CCCC */ 7447 mov r2, rINST, lsr #12 @ r2<- B 7448 FETCH(r1, 1) @ r1<- field byte offset 7449 GET_VREG(r3, r2) @ r3<- object we're operating on 7450 ubfx r2, rINST, #8, #4 @ r2<- A 7451 cmp r3, #0 @ check object for null 7452 beq common_errNullObject @ object was null 7453 ldrd r0, [r3, r1] @ r0<- obj.field (64 bits, aligned) 7454 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7455 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7456 GET_INST_OPCODE(ip) @ extract opcode from rINST 7457 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7458 GOTO_OPCODE(ip) @ jump to next instruction 7459 7460 7461/* ------------------------------ */ 7462 .balign 64 7463.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7464/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7465/* File: armv5te/OP_IGET_QUICK.S */ 7466 /* For: iget-quick, iget-object-quick */ 7467 /* op vA, vB, offset@CCCC */ 7468 mov r2, rINST, lsr #12 @ r2<- B 7469 GET_VREG(r3, r2) @ r3<- object we're operating on 7470 FETCH(r1, 1) @ r1<- field byte offset 7471 cmp r3, #0 @ check object for null 7472 mov r2, rINST, lsr #8 @ r2<- A(+) 7473 beq common_errNullObject @ object was null 7474 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7475 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7476 and r2, r2, #15 7477 GET_INST_OPCODE(ip) @ extract opcode from rINST 7478 SET_VREG(r0, r2) @ fp[A]<- r0 7479 GOTO_OPCODE(ip) @ jump to next instruction 7480 7481 7482 7483/* ------------------------------ */ 7484 .balign 64 7485.L_OP_IPUT_QUICK: /* 0xf5 */ 7486/* File: armv6t2/OP_IPUT_QUICK.S */ 7487 /* For: iput-quick, iput-object-quick */ 7488 /* op vA, vB, offset@CCCC */ 7489 mov r2, rINST, lsr #12 @ r2<- B 7490 FETCH(r1, 1) @ r1<- field byte offset 7491 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7492 ubfx r2, rINST, #8, #4 @ r2<- A 7493 cmp r3, #0 @ check object for null 7494 beq common_errNullObject @ object was null 7495 GET_VREG(r0, r2) @ r0<- fp[A] 7496 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7497 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7498 GET_INST_OPCODE(ip) @ extract opcode from rINST 7499 GOTO_OPCODE(ip) @ jump to next instruction 7500 7501 7502/* ------------------------------ */ 7503 .balign 64 7504.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7505/* File: armv6t2/OP_IPUT_WIDE_QUICK.S */ 7506 /* iput-wide-quick vA, vB, offset@CCCC */ 7507 mov r1, rINST, lsr #12 @ r1<- B 7508 ubfx r0, rINST, #8, #4 @ r0<- A 7509 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7510 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7511 cmp r2, #0 @ check object for null 7512 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7513 beq common_errNullObject @ object was null 7514 FETCH(r3, 1) @ r3<- field byte offset 7515 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7516 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7517 GET_INST_OPCODE(ip) @ extract opcode from rINST 7518 GOTO_OPCODE(ip) @ jump to next instruction 7519 7520 7521/* ------------------------------ */ 7522 .balign 64 7523.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7524/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7525/* File: armv5te/OP_IPUT_QUICK.S */ 7526 /* For: iput-quick, iput-object-quick */ 7527 /* op vA, vB, offset@CCCC */ 7528 mov r2, rINST, lsr #12 @ r2<- B 7529 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7530 FETCH(r1, 1) @ r1<- field byte offset 7531 cmp r3, #0 @ check object for null 7532 mov r2, rINST, lsr #8 @ r2<- A(+) 7533 beq common_errNullObject @ object was null 7534 and r2, r2, #15 7535 GET_VREG(r0, r2) @ r0<- fp[A] 7536 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7537 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7538 GET_INST_OPCODE(ip) @ extract opcode from rINST 7539 GOTO_OPCODE(ip) @ jump to next instruction 7540 7541 7542 7543/* ------------------------------ */ 7544 .balign 64 7545.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7546/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7547 /* 7548 * Handle an optimized virtual method call. 7549 * 7550 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7551 */ 7552 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7553 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7554 FETCH(r3, 2) @ r3<- FEDC or CCCC 7555 FETCH(r1, 1) @ r1<- BBBB 7556 .if (!0) 7557 and r3, r3, #15 @ r3<- C (or stays CCCC) 7558 .endif 7559 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7560 cmp r2, #0 @ is "this" null? 7561 beq common_errNullObject @ null "this", throw exception 7562 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7563 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7564 EXPORT_PC() @ invoke must export 7565 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7566 bl common_invokeMethodNoRange @ continue on 7567 7568/* ------------------------------ */ 7569 .balign 64 7570.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7571/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7572/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7573 /* 7574 * Handle an optimized virtual method call. 7575 * 7576 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7577 */ 7578 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7579 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7580 FETCH(r3, 2) @ r3<- FEDC or CCCC 7581 FETCH(r1, 1) @ r1<- BBBB 7582 .if (!1) 7583 and r3, r3, #15 @ r3<- C (or stays CCCC) 7584 .endif 7585 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7586 cmp r2, #0 @ is "this" null? 7587 beq common_errNullObject @ null "this", throw exception 7588 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7589 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7590 EXPORT_PC() @ invoke must export 7591 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7592 bl common_invokeMethodRange @ continue on 7593 7594 7595/* ------------------------------ */ 7596 .balign 64 7597.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7598/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7599 /* 7600 * Handle an optimized "super" method call. 7601 * 7602 * for: [opt] invoke-super-quick, invoke-super-quick/range 7603 */ 7604 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7605 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7606 FETCH(r10, 2) @ r10<- GFED or CCCC 7607 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7608 .if (!0) 7609 and r10, r10, #15 @ r10<- D (or stays CCCC) 7610 .endif 7611 FETCH(r1, 1) @ r1<- BBBB 7612 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7613 EXPORT_PC() @ must export for invoke 7614 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7615 GET_VREG(r3, r10) @ r3<- "this" 7616 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7617 cmp r3, #0 @ null "this" ref? 7618 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7619 beq common_errNullObject @ "this" is null, throw exception 7620 bl common_invokeMethodNoRange @ continue on 7621 7622 7623/* ------------------------------ */ 7624 .balign 64 7625.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7626/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7627/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7628 /* 7629 * Handle an optimized "super" method call. 7630 * 7631 * for: [opt] invoke-super-quick, invoke-super-quick/range 7632 */ 7633 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7634 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7635 FETCH(r10, 2) @ r10<- GFED or CCCC 7636 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7637 .if (!1) 7638 and r10, r10, #15 @ r10<- D (or stays CCCC) 7639 .endif 7640 FETCH(r1, 1) @ r1<- BBBB 7641 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7642 EXPORT_PC() @ must export for invoke 7643 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7644 GET_VREG(r3, r10) @ r3<- "this" 7645 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7646 cmp r3, #0 @ null "this" ref? 7647 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7648 beq common_errNullObject @ "this" is null, throw exception 7649 bl common_invokeMethodRange @ continue on 7650 7651 7652 7653/* ------------------------------ */ 7654 .balign 64 7655.L_OP_UNUSED_FC: /* 0xfc */ 7656/* File: armv5te/OP_UNUSED_FC.S */ 7657/* File: armv5te/unused.S */ 7658 bl common_abort 7659 7660 7661 7662/* ------------------------------ */ 7663 .balign 64 7664.L_OP_UNUSED_FD: /* 0xfd */ 7665/* File: armv5te/OP_UNUSED_FD.S */ 7666/* File: armv5te/unused.S */ 7667 bl common_abort 7668 7669 7670 7671/* ------------------------------ */ 7672 .balign 64 7673.L_OP_UNUSED_FE: /* 0xfe */ 7674/* File: armv5te/OP_UNUSED_FE.S */ 7675/* File: armv5te/unused.S */ 7676 bl common_abort 7677 7678 7679 7680/* ------------------------------ */ 7681 .balign 64 7682.L_OP_UNUSED_FF: /* 0xff */ 7683/* File: armv5te/OP_UNUSED_FF.S */ 7684/* File: armv5te/unused.S */ 7685 bl common_abort 7686 7687 7688 7689 7690 .balign 64 7691 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7692 .global dvmAsmInstructionEnd 7693dvmAsmInstructionEnd: 7694 7695/* 7696 * =========================================================================== 7697 * Sister implementations 7698 * =========================================================================== 7699 */ 7700 .global dvmAsmSisterStart 7701 .type dvmAsmSisterStart, %function 7702 .text 7703 .balign 4 7704dvmAsmSisterStart: 7705 7706/* continuation for OP_CONST_STRING */ 7707 7708 /* 7709 * Continuation if the String has not yet been resolved. 7710 * r1: BBBB (String ref) 7711 * r9: target register 7712 */ 7713.LOP_CONST_STRING_resolve: 7714 EXPORT_PC() 7715 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7716 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7717 bl dvmResolveString @ r0<- String reference 7718 cmp r0, #0 @ failed? 7719 beq common_exceptionThrown @ yup, handle the exception 7720 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7721 GET_INST_OPCODE(ip) @ extract opcode from rINST 7722 SET_VREG(r0, r9) @ vAA<- r0 7723 GOTO_OPCODE(ip) @ jump to next instruction 7724 7725 7726/* continuation for OP_CONST_STRING_JUMBO */ 7727 7728 /* 7729 * Continuation if the String has not yet been resolved. 7730 * r1: BBBBBBBB (String ref) 7731 * r9: target register 7732 */ 7733.LOP_CONST_STRING_JUMBO_resolve: 7734 EXPORT_PC() 7735 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7736 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7737 bl dvmResolveString @ r0<- String reference 7738 cmp r0, #0 @ failed? 7739 beq common_exceptionThrown @ yup, handle the exception 7740 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7741 GET_INST_OPCODE(ip) @ extract opcode from rINST 7742 SET_VREG(r0, r9) @ vAA<- r0 7743 GOTO_OPCODE(ip) @ jump to next instruction 7744 7745 7746/* continuation for OP_CONST_CLASS */ 7747 7748 /* 7749 * Continuation if the Class has not yet been resolved. 7750 * r1: BBBB (Class ref) 7751 * r9: target register 7752 */ 7753.LOP_CONST_CLASS_resolve: 7754 EXPORT_PC() 7755 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7756 mov r2, #1 @ r2<- true 7757 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7758 bl dvmResolveClass @ r0<- Class reference 7759 cmp r0, #0 @ failed? 7760 beq common_exceptionThrown @ yup, handle the exception 7761 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7762 GET_INST_OPCODE(ip) @ extract opcode from rINST 7763 SET_VREG(r0, r9) @ vAA<- r0 7764 GOTO_OPCODE(ip) @ jump to next instruction 7765 7766 7767/* continuation for OP_CHECK_CAST */ 7768 7769 /* 7770 * Trivial test failed, need to perform full check. This is common. 7771 * r0 holds obj->clazz 7772 * r1 holds class resolved from BBBB 7773 * r9 holds object 7774 */ 7775.LOP_CHECK_CAST_fullcheck: 7776 bl dvmInstanceofNonTrivial @ r0<- boolean result 7777 cmp r0, #0 @ failed? 7778 bne .LOP_CHECK_CAST_okay @ no, success 7779 7780 @ A cast has failed. We need to throw a ClassCastException with the 7781 @ class of the object that failed to be cast. 7782 EXPORT_PC() @ about to throw 7783 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 7784 ldr r0, .LstrClassCastExceptionPtr 7785 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 7786 bl dvmThrowExceptionWithClassMessage 7787 b common_exceptionThrown 7788 7789 /* 7790 * Resolution required. This is the least-likely path. 7791 * 7792 * r2 holds BBBB 7793 * r9 holds object 7794 */ 7795.LOP_CHECK_CAST_resolve: 7796 EXPORT_PC() @ resolve() could throw 7797 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7798 mov r1, r2 @ r1<- BBBB 7799 mov r2, #0 @ r2<- false 7800 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7801 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7802 cmp r0, #0 @ got null? 7803 beq common_exceptionThrown @ yes, handle exception 7804 mov r1, r0 @ r1<- class resolved from BBB 7805 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7806 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7807 7808.LstrClassCastExceptionPtr: 7809 .word .LstrClassCastException 7810 7811 7812/* continuation for OP_INSTANCE_OF */ 7813 7814 /* 7815 * Trivial test failed, need to perform full check. This is common. 7816 * r0 holds obj->clazz 7817 * r1 holds class resolved from BBBB 7818 * r9 holds A 7819 */ 7820.LOP_INSTANCE_OF_fullcheck: 7821 bl dvmInstanceofNonTrivial @ r0<- boolean result 7822 @ fall through to OP_INSTANCE_OF_store 7823 7824 /* 7825 * r0 holds boolean result 7826 * r9 holds A 7827 */ 7828.LOP_INSTANCE_OF_store: 7829 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7830 SET_VREG(r0, r9) @ vA<- r0 7831 GET_INST_OPCODE(ip) @ extract opcode from rINST 7832 GOTO_OPCODE(ip) @ jump to next instruction 7833 7834 /* 7835 * Trivial test succeeded, save and bail. 7836 * r9 holds A 7837 */ 7838.LOP_INSTANCE_OF_trivial: 7839 mov r0, #1 @ indicate success 7840 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7841 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7842 SET_VREG(r0, r9) @ vA<- r0 7843 GET_INST_OPCODE(ip) @ extract opcode from rINST 7844 GOTO_OPCODE(ip) @ jump to next instruction 7845 7846 /* 7847 * Resolution required. This is the least-likely path. 7848 * 7849 * r3 holds BBBB 7850 * r9 holds A 7851 */ 7852.LOP_INSTANCE_OF_resolve: 7853 EXPORT_PC() @ resolve() could throw 7854 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7855 mov r1, r3 @ r1<- BBBB 7856 mov r2, #1 @ r2<- true 7857 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7858 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7859 cmp r0, #0 @ got null? 7860 beq common_exceptionThrown @ yes, handle exception 7861 mov r1, r0 @ r1<- class resolved from BBB 7862 mov r3, rINST, lsr #12 @ r3<- B 7863 GET_VREG(r0, r3) @ r0<- vB (object) 7864 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7865 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7866 7867 7868/* continuation for OP_NEW_INSTANCE */ 7869 7870 .balign 32 @ minimize cache lines 7871.LOP_NEW_INSTANCE_finish: @ r0=new object 7872 mov r3, rINST, lsr #8 @ r3<- AA 7873 cmp r0, #0 @ failed? 7874 beq common_exceptionThrown @ yes, handle the exception 7875 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7876 GET_INST_OPCODE(ip) @ extract opcode from rINST 7877 SET_VREG(r0, r3) @ vAA<- r0 7878 GOTO_OPCODE(ip) @ jump to next instruction 7879 7880 /* 7881 * Class initialization required. 7882 * 7883 * r0 holds class object 7884 */ 7885.LOP_NEW_INSTANCE_needinit: 7886 mov r9, r0 @ save r0 7887 bl dvmInitClass @ initialize class 7888 cmp r0, #0 @ check boolean result 7889 mov r0, r9 @ restore r0 7890 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7891 b common_exceptionThrown @ failed, deal with init exception 7892 7893 /* 7894 * Resolution required. This is the least-likely path. 7895 * 7896 * r1 holds BBBB 7897 */ 7898.LOP_NEW_INSTANCE_resolve: 7899 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7900 mov r2, #0 @ r2<- false 7901 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7902 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7903 cmp r0, #0 @ got null? 7904 bne .LOP_NEW_INSTANCE_resolved @ no, continue 7905 b common_exceptionThrown @ yes, handle exception 7906 7907.LstrInstantiationErrorPtr: 7908 .word .LstrInstantiationError 7909 7910 7911/* continuation for OP_NEW_ARRAY */ 7912 7913 7914 /* 7915 * Resolve class. (This is an uncommon case.) 7916 * 7917 * r1 holds array length 7918 * r2 holds class ref CCCC 7919 */ 7920.LOP_NEW_ARRAY_resolve: 7921 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7922 mov r9, r1 @ r9<- length (save) 7923 mov r1, r2 @ r1<- CCCC 7924 mov r2, #0 @ r2<- false 7925 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7926 bl dvmResolveClass @ r0<- call(clazz, ref) 7927 cmp r0, #0 @ got null? 7928 mov r1, r9 @ r1<- length (restore) 7929 beq common_exceptionThrown @ yes, handle exception 7930 @ fall through to OP_NEW_ARRAY_finish 7931 7932 /* 7933 * Finish allocation. 7934 * 7935 * r0 holds class 7936 * r1 holds array length 7937 */ 7938.LOP_NEW_ARRAY_finish: 7939 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 7940 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 7941 cmp r0, #0 @ failed? 7942 mov r2, rINST, lsr #8 @ r2<- A+ 7943 beq common_exceptionThrown @ yes, handle the exception 7944 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7945 and r2, r2, #15 @ r2<- A 7946 GET_INST_OPCODE(ip) @ extract opcode from rINST 7947 SET_VREG(r0, r2) @ vA<- r0 7948 GOTO_OPCODE(ip) @ jump to next instruction 7949 7950 7951/* continuation for OP_FILLED_NEW_ARRAY */ 7952 7953 /* 7954 * On entry: 7955 * r0 holds array class 7956 * r10 holds AA or BA 7957 */ 7958.LOP_FILLED_NEW_ARRAY_continue: 7959 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 7960 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 7961 ldrb r3, [r3, #1] @ r3<- descriptor[1] 7962 .if 0 7963 mov r1, r10 @ r1<- AA (length) 7964 .else 7965 mov r1, r10, lsr #4 @ r1<- B (length) 7966 .endif 7967 cmp r3, #'I' @ array of ints? 7968 cmpne r3, #'L' @ array of objects? 7969 cmpne r3, #'[' @ array of arrays? 7970 mov r9, r1 @ save length in r9 7971 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 7972 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 7973 cmp r0, #0 @ null return? 7974 beq common_exceptionThrown @ alloc failed, handle exception 7975 7976 FETCH(r1, 2) @ r1<- FEDC or CCCC 7977 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 7978 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 7979 subs r9, r9, #1 @ length--, check for neg 7980 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7981 bmi 2f @ was zero, bail 7982 7983 @ copy values from registers into the array 7984 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 7985 .if 0 7986 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 79871: ldr r3, [r2], #4 @ r3<- *r2++ 7988 subs r9, r9, #1 @ count-- 7989 str r3, [r0], #4 @ *contents++ = vX 7990 bpl 1b 7991 @ continue at 2 7992 .else 7993 cmp r9, #4 @ length was initially 5? 7994 and r2, r10, #15 @ r2<- A 7995 bne 1f @ <= 4 args, branch 7996 GET_VREG(r3, r2) @ r3<- vA 7997 sub r9, r9, #1 @ count-- 7998 str r3, [r0, #16] @ contents[4] = vA 79991: and r2, r1, #15 @ r2<- F/E/D/C 8000 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8001 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8002 subs r9, r9, #1 @ count-- 8003 str r3, [r0], #4 @ *contents++ = vX 8004 bpl 1b 8005 @ continue at 2 8006 .endif 8007 80082: 8009 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8010 GOTO_OPCODE(ip) @ execute it 8011 8012 /* 8013 * Throw an exception indicating that we have not implemented this 8014 * mode of filled-new-array. 8015 */ 8016.LOP_FILLED_NEW_ARRAY_notimpl: 8017 ldr r0, .L_strInternalError 8018 ldr r1, .L_strFilledNewArrayNotImpl 8019 bl dvmThrowException 8020 b common_exceptionThrown 8021 8022 .if (!0) @ define in one or the other, not both 8023.L_strFilledNewArrayNotImpl: 8024 .word .LstrFilledNewArrayNotImpl 8025.L_strInternalError: 8026 .word .LstrInternalError 8027 .endif 8028 8029 8030/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 8031 8032 /* 8033 * On entry: 8034 * r0 holds array class 8035 * r10 holds AA or BA 8036 */ 8037.LOP_FILLED_NEW_ARRAY_RANGE_continue: 8038 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8039 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8040 ldrb r3, [r3, #1] @ r3<- descriptor[1] 8041 .if 1 8042 mov r1, r10 @ r1<- AA (length) 8043 .else 8044 mov r1, r10, lsr #4 @ r1<- B (length) 8045 .endif 8046 cmp r3, #'I' @ array of ints? 8047 cmpne r3, #'L' @ array of objects? 8048 cmpne r3, #'[' @ array of arrays? 8049 mov r9, r1 @ save length in r9 8050 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 8051 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8052 cmp r0, #0 @ null return? 8053 beq common_exceptionThrown @ alloc failed, handle exception 8054 8055 FETCH(r1, 2) @ r1<- FEDC or CCCC 8056 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8057 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8058 subs r9, r9, #1 @ length--, check for neg 8059 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8060 bmi 2f @ was zero, bail 8061 8062 @ copy values from registers into the array 8063 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8064 .if 1 8065 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 80661: ldr r3, [r2], #4 @ r3<- *r2++ 8067 subs r9, r9, #1 @ count-- 8068 str r3, [r0], #4 @ *contents++ = vX 8069 bpl 1b 8070 @ continue at 2 8071 .else 8072 cmp r9, #4 @ length was initially 5? 8073 and r2, r10, #15 @ r2<- A 8074 bne 1f @ <= 4 args, branch 8075 GET_VREG(r3, r2) @ r3<- vA 8076 sub r9, r9, #1 @ count-- 8077 str r3, [r0, #16] @ contents[4] = vA 80781: and r2, r1, #15 @ r2<- F/E/D/C 8079 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8080 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8081 subs r9, r9, #1 @ count-- 8082 str r3, [r0], #4 @ *contents++ = vX 8083 bpl 1b 8084 @ continue at 2 8085 .endif 8086 80872: 8088 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8089 GOTO_OPCODE(ip) @ execute it 8090 8091 /* 8092 * Throw an exception indicating that we have not implemented this 8093 * mode of filled-new-array. 8094 */ 8095.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8096 ldr r0, .L_strInternalError 8097 ldr r1, .L_strFilledNewArrayNotImpl 8098 bl dvmThrowException 8099 b common_exceptionThrown 8100 8101 .if (!1) @ define in one or the other, not both 8102.L_strFilledNewArrayNotImpl: 8103 .word .LstrFilledNewArrayNotImpl 8104.L_strInternalError: 8105 .word .LstrInternalError 8106 .endif 8107 8108 8109/* continuation for OP_CMPL_FLOAT */ 8110.LOP_CMPL_FLOAT_finish: 8111 SET_VREG(r0, r9) @ vAA<- r0 8112 GOTO_OPCODE(ip) @ jump to next instruction 8113 8114 8115/* continuation for OP_CMPG_FLOAT */ 8116.LOP_CMPG_FLOAT_finish: 8117 SET_VREG(r0, r9) @ vAA<- r0 8118 GOTO_OPCODE(ip) @ jump to next instruction 8119 8120 8121/* continuation for OP_CMPL_DOUBLE */ 8122.LOP_CMPL_DOUBLE_finish: 8123 SET_VREG(r0, r9) @ vAA<- r0 8124 GOTO_OPCODE(ip) @ jump to next instruction 8125 8126 8127/* continuation for OP_CMPG_DOUBLE */ 8128.LOP_CMPG_DOUBLE_finish: 8129 SET_VREG(r0, r9) @ vAA<- r0 8130 GOTO_OPCODE(ip) @ jump to next instruction 8131 8132 8133/* continuation for OP_CMP_LONG */ 8134 8135.LOP_CMP_LONG_less: 8136 mvn r1, #0 @ r1<- -1 8137 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8138 @ instead, we just replicate the tail end. 8139 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8140 SET_VREG(r1, r9) @ vAA<- r1 8141 GET_INST_OPCODE(ip) @ extract opcode from rINST 8142 GOTO_OPCODE(ip) @ jump to next instruction 8143 8144.LOP_CMP_LONG_greater: 8145 mov r1, #1 @ r1<- 1 8146 @ fall through to _finish 8147 8148.LOP_CMP_LONG_finish: 8149 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8150 SET_VREG(r1, r9) @ vAA<- r1 8151 GET_INST_OPCODE(ip) @ extract opcode from rINST 8152 GOTO_OPCODE(ip) @ jump to next instruction 8153 8154 8155/* continuation for OP_AGET_WIDE */ 8156 8157.LOP_AGET_WIDE_finish: 8158 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8159 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8160 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8161 GET_INST_OPCODE(ip) @ extract opcode from rINST 8162 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8163 GOTO_OPCODE(ip) @ jump to next instruction 8164 8165 8166/* continuation for OP_APUT_WIDE */ 8167 8168.LOP_APUT_WIDE_finish: 8169 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8170 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8171 GET_INST_OPCODE(ip) @ extract opcode from rINST 8172 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8173 GOTO_OPCODE(ip) @ jump to next instruction 8174 8175 8176/* continuation for OP_APUT_OBJECT */ 8177 /* 8178 * On entry: 8179 * r1 = vBB (arrayObj) 8180 * r9 = vAA (obj) 8181 * r10 = offset into array (vBB + vCC * width) 8182 */ 8183.LOP_APUT_OBJECT_finish: 8184 cmp r9, #0 @ storing null reference? 8185 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8186 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8187 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz 8188 bl dvmCanPutArrayElement @ test object type vs. array type 8189 cmp r0, #0 @ okay? 8190 beq common_errArrayStore @ no 8191.LOP_APUT_OBJECT_skip_check: 8192 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8193 GET_INST_OPCODE(ip) @ extract opcode from rINST 8194 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8195 GOTO_OPCODE(ip) @ jump to next instruction 8196 8197 8198/* continuation for OP_IGET */ 8199 8200 /* 8201 * Currently: 8202 * r0 holds resolved field 8203 * r9 holds object 8204 */ 8205.LOP_IGET_finish: 8206 @bl common_squeak0 8207 cmp r9, #0 @ check object for null 8208 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8209 beq common_errNullObject @ object was null 8210 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8211 ubfx r2, rINST, #8, #4 @ r2<- A 8212 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8213 GET_INST_OPCODE(ip) @ extract opcode from rINST 8214 SET_VREG(r0, r2) @ fp[A]<- r0 8215 GOTO_OPCODE(ip) @ jump to next instruction 8216 8217 8218/* continuation for OP_IGET_WIDE */ 8219 8220 /* 8221 * Currently: 8222 * r0 holds resolved field 8223 * r9 holds object 8224 */ 8225.LOP_IGET_WIDE_finish: 8226 cmp r9, #0 @ check object for null 8227 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8228 beq common_errNullObject @ object was null 8229 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8230 ubfx r2, rINST, #8, #4 @ r2<- A 8231 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8232 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8233 GET_INST_OPCODE(ip) @ extract opcode from rINST 8234 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8235 GOTO_OPCODE(ip) @ jump to next instruction 8236 8237 8238/* continuation for OP_IGET_OBJECT */ 8239 8240 /* 8241 * Currently: 8242 * r0 holds resolved field 8243 * r9 holds object 8244 */ 8245.LOP_IGET_OBJECT_finish: 8246 @bl common_squeak0 8247 cmp r9, #0 @ check object for null 8248 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8249 beq common_errNullObject @ object was null 8250 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8251 mov r2, rINST, lsr #8 @ r2<- A+ 8252 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8253 and r2, r2, #15 @ r2<- A 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 8259/* continuation for OP_IGET_BOOLEAN */ 8260 8261 /* 8262 * Currently: 8263 * r0 holds resolved field 8264 * r9 holds object 8265 */ 8266.LOP_IGET_BOOLEAN_finish: 8267 @bl common_squeak1 8268 cmp r9, #0 @ check object for null 8269 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8270 beq common_errNullObject @ object was null 8271 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8272 mov r2, rINST, lsr #8 @ r2<- A+ 8273 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8274 and r2, r2, #15 @ r2<- A 8275 GET_INST_OPCODE(ip) @ extract opcode from rINST 8276 SET_VREG(r0, r2) @ fp[A]<- r0 8277 GOTO_OPCODE(ip) @ jump to next instruction 8278 8279 8280/* continuation for OP_IGET_BYTE */ 8281 8282 /* 8283 * Currently: 8284 * r0 holds resolved field 8285 * r9 holds object 8286 */ 8287.LOP_IGET_BYTE_finish: 8288 @bl common_squeak2 8289 cmp r9, #0 @ check object for null 8290 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8291 beq common_errNullObject @ object was null 8292 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8293 mov r2, rINST, lsr #8 @ r2<- A+ 8294 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8295 and r2, r2, #15 @ r2<- A 8296 GET_INST_OPCODE(ip) @ extract opcode from rINST 8297 SET_VREG(r0, r2) @ fp[A]<- r0 8298 GOTO_OPCODE(ip) @ jump to next instruction 8299 8300 8301/* continuation for OP_IGET_CHAR */ 8302 8303 /* 8304 * Currently: 8305 * r0 holds resolved field 8306 * r9 holds object 8307 */ 8308.LOP_IGET_CHAR_finish: 8309 @bl common_squeak3 8310 cmp r9, #0 @ check object for null 8311 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8312 beq common_errNullObject @ object was null 8313 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8314 mov r2, rINST, lsr #8 @ r2<- A+ 8315 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8316 and r2, r2, #15 @ r2<- A 8317 GET_INST_OPCODE(ip) @ extract opcode from rINST 8318 SET_VREG(r0, r2) @ fp[A]<- r0 8319 GOTO_OPCODE(ip) @ jump to next instruction 8320 8321 8322/* continuation for OP_IGET_SHORT */ 8323 8324 /* 8325 * Currently: 8326 * r0 holds resolved field 8327 * r9 holds object 8328 */ 8329.LOP_IGET_SHORT_finish: 8330 @bl common_squeak4 8331 cmp r9, #0 @ check object for null 8332 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8333 beq common_errNullObject @ object was null 8334 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8335 mov r2, rINST, lsr #8 @ r2<- A+ 8336 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8337 and r2, r2, #15 @ r2<- A 8338 GET_INST_OPCODE(ip) @ extract opcode from rINST 8339 SET_VREG(r0, r2) @ fp[A]<- r0 8340 GOTO_OPCODE(ip) @ jump to next instruction 8341 8342 8343/* continuation for OP_IPUT */ 8344 8345 /* 8346 * Currently: 8347 * r0 holds resolved field 8348 * r9 holds object 8349 */ 8350.LOP_IPUT_finish: 8351 @bl common_squeak0 8352 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8353 ubfx r1, rINST, #8, #4 @ r1<- A 8354 cmp r9, #0 @ check object for null 8355 GET_VREG(r0, r1) @ r0<- fp[A] 8356 beq common_errNullObject @ object was null 8357 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8358 GET_INST_OPCODE(ip) @ extract opcode from rINST 8359 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8360 GOTO_OPCODE(ip) @ jump to next instruction 8361 8362 8363/* continuation for OP_IPUT_WIDE */ 8364 8365 /* 8366 * Currently: 8367 * r0 holds resolved field 8368 * r9 holds object 8369 */ 8370.LOP_IPUT_WIDE_finish: 8371 ubfx r2, rINST, #8, #4 @ r2<- A 8372 cmp r9, #0 @ check object for null 8373 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8374 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8375 beq common_errNullObject @ object was null 8376 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8377 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8378 GET_INST_OPCODE(ip) @ extract opcode from rINST 8379 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0 8380 GOTO_OPCODE(ip) @ jump to next instruction 8381 8382 8383/* continuation for OP_IPUT_OBJECT */ 8384 8385 /* 8386 * Currently: 8387 * r0 holds resolved field 8388 * r9 holds object 8389 */ 8390.LOP_IPUT_OBJECT_finish: 8391 @bl common_squeak0 8392 mov r1, rINST, lsr #8 @ r1<- A+ 8393 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8394 and r1, r1, #15 @ r1<- A 8395 cmp r9, #0 @ check object for null 8396 GET_VREG(r0, r1) @ r0<- fp[A] 8397 beq common_errNullObject @ object was null 8398 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8399 GET_INST_OPCODE(ip) @ extract opcode from rINST 8400 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8401 GOTO_OPCODE(ip) @ jump to next instruction 8402 8403 8404/* continuation for OP_IPUT_BOOLEAN */ 8405 8406 /* 8407 * Currently: 8408 * r0 holds resolved field 8409 * r9 holds object 8410 */ 8411.LOP_IPUT_BOOLEAN_finish: 8412 @bl common_squeak1 8413 mov r1, rINST, lsr #8 @ r1<- A+ 8414 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8415 and r1, r1, #15 @ r1<- A 8416 cmp r9, #0 @ check object for null 8417 GET_VREG(r0, r1) @ r0<- fp[A] 8418 beq common_errNullObject @ object was null 8419 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8420 GET_INST_OPCODE(ip) @ extract opcode from rINST 8421 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8422 GOTO_OPCODE(ip) @ jump to next instruction 8423 8424 8425/* continuation for OP_IPUT_BYTE */ 8426 8427 /* 8428 * Currently: 8429 * r0 holds resolved field 8430 * r9 holds object 8431 */ 8432.LOP_IPUT_BYTE_finish: 8433 @bl common_squeak2 8434 mov r1, rINST, lsr #8 @ r1<- A+ 8435 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8436 and r1, r1, #15 @ r1<- A 8437 cmp r9, #0 @ check object for null 8438 GET_VREG(r0, r1) @ r0<- fp[A] 8439 beq common_errNullObject @ object was null 8440 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8441 GET_INST_OPCODE(ip) @ extract opcode from rINST 8442 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8443 GOTO_OPCODE(ip) @ jump to next instruction 8444 8445 8446/* continuation for OP_IPUT_CHAR */ 8447 8448 /* 8449 * Currently: 8450 * r0 holds resolved field 8451 * r9 holds object 8452 */ 8453.LOP_IPUT_CHAR_finish: 8454 @bl common_squeak3 8455 mov r1, rINST, lsr #8 @ r1<- A+ 8456 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8457 and r1, r1, #15 @ r1<- A 8458 cmp r9, #0 @ check object for null 8459 GET_VREG(r0, r1) @ r0<- fp[A] 8460 beq common_errNullObject @ object was null 8461 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8462 GET_INST_OPCODE(ip) @ extract opcode from rINST 8463 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8464 GOTO_OPCODE(ip) @ jump to next instruction 8465 8466 8467/* continuation for OP_IPUT_SHORT */ 8468 8469 /* 8470 * Currently: 8471 * r0 holds resolved field 8472 * r9 holds object 8473 */ 8474.LOP_IPUT_SHORT_finish: 8475 @bl common_squeak4 8476 mov r1, rINST, lsr #8 @ r1<- A+ 8477 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8478 and r1, r1, #15 @ r1<- A 8479 cmp r9, #0 @ check object for null 8480 GET_VREG(r0, r1) @ r0<- fp[A] 8481 beq common_errNullObject @ object was null 8482 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8483 GET_INST_OPCODE(ip) @ extract opcode from rINST 8484 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8485 GOTO_OPCODE(ip) @ jump to next instruction 8486 8487 8488/* continuation for OP_SGET */ 8489 8490 /* 8491 * Continuation if the field has not yet been resolved. 8492 * r1: BBBB field ref 8493 */ 8494.LOP_SGET_resolve: 8495 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8496 EXPORT_PC() @ resolve() could throw, so export now 8497 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8498 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8499 cmp r0, #0 @ success? 8500 bne .LOP_SGET_finish @ yes, finish 8501 b common_exceptionThrown @ no, handle exception 8502 8503 8504/* continuation for OP_SGET_WIDE */ 8505 8506 /* 8507 * Continuation if the field has not yet been resolved. 8508 * r1: BBBB field ref 8509 * 8510 * Returns StaticField pointer in r0. 8511 */ 8512.LOP_SGET_WIDE_resolve: 8513 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8514 EXPORT_PC() @ resolve() could throw, so export now 8515 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8516 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8517 cmp r0, #0 @ success? 8518 bne .LOP_SGET_WIDE_finish @ yes, finish 8519 b common_exceptionThrown @ no, handle exception 8520 8521 8522/* continuation for OP_SGET_OBJECT */ 8523 8524 /* 8525 * Continuation if the field has not yet been resolved. 8526 * r1: BBBB field ref 8527 */ 8528.LOP_SGET_OBJECT_resolve: 8529 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8530 EXPORT_PC() @ resolve() could throw, so export now 8531 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8532 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8533 cmp r0, #0 @ success? 8534 bne .LOP_SGET_OBJECT_finish @ yes, finish 8535 b common_exceptionThrown @ no, handle exception 8536 8537 8538/* continuation for OP_SGET_BOOLEAN */ 8539 8540 /* 8541 * Continuation if the field has not yet been resolved. 8542 * r1: BBBB field ref 8543 */ 8544.LOP_SGET_BOOLEAN_resolve: 8545 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8546 EXPORT_PC() @ resolve() could throw, so export now 8547 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8548 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8549 cmp r0, #0 @ success? 8550 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8551 b common_exceptionThrown @ no, handle exception 8552 8553 8554/* continuation for OP_SGET_BYTE */ 8555 8556 /* 8557 * Continuation if the field has not yet been resolved. 8558 * r1: BBBB field ref 8559 */ 8560.LOP_SGET_BYTE_resolve: 8561 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8562 EXPORT_PC() @ resolve() could throw, so export now 8563 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8564 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8565 cmp r0, #0 @ success? 8566 bne .LOP_SGET_BYTE_finish @ yes, finish 8567 b common_exceptionThrown @ no, handle exception 8568 8569 8570/* continuation for OP_SGET_CHAR */ 8571 8572 /* 8573 * Continuation if the field has not yet been resolved. 8574 * r1: BBBB field ref 8575 */ 8576.LOP_SGET_CHAR_resolve: 8577 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8578 EXPORT_PC() @ resolve() could throw, so export now 8579 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8580 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8581 cmp r0, #0 @ success? 8582 bne .LOP_SGET_CHAR_finish @ yes, finish 8583 b common_exceptionThrown @ no, handle exception 8584 8585 8586/* continuation for OP_SGET_SHORT */ 8587 8588 /* 8589 * Continuation if the field has not yet been resolved. 8590 * r1: BBBB field ref 8591 */ 8592.LOP_SGET_SHORT_resolve: 8593 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8594 EXPORT_PC() @ resolve() could throw, so export now 8595 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8596 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8597 cmp r0, #0 @ success? 8598 bne .LOP_SGET_SHORT_finish @ yes, finish 8599 b common_exceptionThrown @ no, handle exception 8600 8601 8602/* continuation for OP_SPUT */ 8603 8604 /* 8605 * Continuation if the field has not yet been resolved. 8606 * r1: BBBB field ref 8607 */ 8608.LOP_SPUT_resolve: 8609 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8610 EXPORT_PC() @ resolve() could throw, so export now 8611 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8612 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8613 cmp r0, #0 @ success? 8614 bne .LOP_SPUT_finish @ yes, finish 8615 b common_exceptionThrown @ no, handle exception 8616 8617 8618/* continuation for OP_SPUT_WIDE */ 8619 8620 /* 8621 * Continuation if the field has not yet been resolved. 8622 * r1: BBBB field ref 8623 * r9: &fp[AA] 8624 * 8625 * Returns StaticField pointer in r2. 8626 */ 8627.LOP_SPUT_WIDE_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 mov r2, r0 @ copy to r2 8634 bne .LOP_SPUT_WIDE_finish @ yes, finish 8635 b common_exceptionThrown @ no, handle exception 8636 8637 8638/* continuation for OP_SPUT_OBJECT */ 8639 8640 /* 8641 * Continuation if the field has not yet been resolved. 8642 * r1: BBBB field ref 8643 */ 8644.LOP_SPUT_OBJECT_resolve: 8645 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8646 EXPORT_PC() @ resolve() could throw, so export now 8647 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8648 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8649 cmp r0, #0 @ success? 8650 bne .LOP_SPUT_OBJECT_finish @ yes, finish 8651 b common_exceptionThrown @ no, handle exception 8652 8653 8654/* continuation for OP_SPUT_BOOLEAN */ 8655 8656 /* 8657 * Continuation if the field has not yet been resolved. 8658 * r1: BBBB field ref 8659 */ 8660.LOP_SPUT_BOOLEAN_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 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 8667 b common_exceptionThrown @ no, handle exception 8668 8669 8670/* continuation for OP_SPUT_BYTE */ 8671 8672 /* 8673 * Continuation if the field has not yet been resolved. 8674 * r1: BBBB field ref 8675 */ 8676.LOP_SPUT_BYTE_resolve: 8677 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8678 EXPORT_PC() @ resolve() could throw, so export now 8679 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8680 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8681 cmp r0, #0 @ success? 8682 bne .LOP_SPUT_BYTE_finish @ yes, finish 8683 b common_exceptionThrown @ no, handle exception 8684 8685 8686/* continuation for OP_SPUT_CHAR */ 8687 8688 /* 8689 * Continuation if the field has not yet been resolved. 8690 * r1: BBBB field ref 8691 */ 8692.LOP_SPUT_CHAR_resolve: 8693 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8694 EXPORT_PC() @ resolve() could throw, so export now 8695 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8696 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8697 cmp r0, #0 @ success? 8698 bne .LOP_SPUT_CHAR_finish @ yes, finish 8699 b common_exceptionThrown @ no, handle exception 8700 8701 8702/* continuation for OP_SPUT_SHORT */ 8703 8704 /* 8705 * Continuation if the field has not yet been resolved. 8706 * r1: BBBB field ref 8707 */ 8708.LOP_SPUT_SHORT_resolve: 8709 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8710 EXPORT_PC() @ resolve() could throw, so export now 8711 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8712 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8713 cmp r0, #0 @ success? 8714 bne .LOP_SPUT_SHORT_finish @ yes, finish 8715 b common_exceptionThrown @ no, handle exception 8716 8717 8718/* continuation for OP_INVOKE_VIRTUAL */ 8719 8720 /* 8721 * At this point: 8722 * r0 = resolved base method 8723 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8724 */ 8725.LOP_INVOKE_VIRTUAL_continue: 8726 GET_VREG(r1, r10) @ r1<- "this" ptr 8727 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8728 cmp r1, #0 @ is "this" null? 8729 beq common_errNullObject @ null "this", throw exception 8730 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8731 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8732 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8733 bl common_invokeMethodNoRange @ continue on 8734 8735 8736/* continuation for OP_INVOKE_SUPER */ 8737 8738 /* 8739 * At this point: 8740 * r0 = resolved base method 8741 * r9 = method->clazz 8742 */ 8743.LOP_INVOKE_SUPER_continue: 8744 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8745 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8746 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8747 EXPORT_PC() @ must export for invoke 8748 cmp r2, r3 @ compare (methodIndex, vtableCount) 8749 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 8750 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8751 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8752 bl common_invokeMethodNoRange @ continue on 8753 8754.LOP_INVOKE_SUPER_resolve: 8755 mov r0, r9 @ r0<- method->clazz 8756 mov r2, #METHOD_VIRTUAL @ resolver method type 8757 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8758 cmp r0, #0 @ got null? 8759 bne .LOP_INVOKE_SUPER_continue @ no, continue 8760 b common_exceptionThrown @ yes, handle exception 8761 8762 /* 8763 * Throw a NoSuchMethodError with the method name as the message. 8764 * r0 = resolved base method 8765 */ 8766.LOP_INVOKE_SUPER_nsm: 8767 ldr r1, [r0, #offMethod_name] @ r1<- method name 8768 b common_errNoSuchMethod 8769 8770 8771/* continuation for OP_INVOKE_DIRECT */ 8772 8773 /* 8774 * On entry: 8775 * r1 = reference (BBBB or CCCC) 8776 * r10 = "this" register 8777 */ 8778.LOP_INVOKE_DIRECT_resolve: 8779 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8780 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8781 mov r2, #METHOD_DIRECT @ resolver method type 8782 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8783 cmp r0, #0 @ got null? 8784 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8785 bne .LOP_INVOKE_DIRECT_finish @ no, continue 8786 b common_exceptionThrown @ yes, handle exception 8787 8788 8789/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 8790 8791 /* 8792 * At this point: 8793 * r0 = resolved base method 8794 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8795 */ 8796.LOP_INVOKE_VIRTUAL_RANGE_continue: 8797 GET_VREG(r1, r10) @ r1<- "this" ptr 8798 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8799 cmp r1, #0 @ is "this" null? 8800 beq common_errNullObject @ null "this", throw exception 8801 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8802 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8803 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8804 bl common_invokeMethodRange @ continue on 8805 8806 8807/* continuation for OP_INVOKE_SUPER_RANGE */ 8808 8809 /* 8810 * At this point: 8811 * r0 = resolved base method 8812 * r9 = method->clazz 8813 */ 8814.LOP_INVOKE_SUPER_RANGE_continue: 8815 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8816 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8817 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8818 EXPORT_PC() @ must export for invoke 8819 cmp r2, r3 @ compare (methodIndex, vtableCount) 8820 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 8821 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8822 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8823 bl common_invokeMethodRange @ continue on 8824 8825.LOP_INVOKE_SUPER_RANGE_resolve: 8826 mov r0, r9 @ r0<- method->clazz 8827 mov r2, #METHOD_VIRTUAL @ resolver method type 8828 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8829 cmp r0, #0 @ got null? 8830 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 8831 b common_exceptionThrown @ yes, handle exception 8832 8833 /* 8834 * Throw a NoSuchMethodError with the method name as the message. 8835 * r0 = resolved base method 8836 */ 8837.LOP_INVOKE_SUPER_RANGE_nsm: 8838 ldr r1, [r0, #offMethod_name] @ r1<- method name 8839 b common_errNoSuchMethod 8840 8841 8842/* continuation for OP_INVOKE_DIRECT_RANGE */ 8843 8844 /* 8845 * On entry: 8846 * r1 = reference (BBBB or CCCC) 8847 * r10 = "this" register 8848 */ 8849.LOP_INVOKE_DIRECT_RANGE_resolve: 8850 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8851 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8852 mov r2, #METHOD_DIRECT @ resolver method type 8853 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8854 cmp r0, #0 @ got null? 8855 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8856 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 8857 b common_exceptionThrown @ yes, handle exception 8858 8859 8860/* continuation for OP_FLOAT_TO_LONG */ 8861/* 8862 * Convert the float in r0 to a long in r0/r1. 8863 * 8864 * We have to clip values to long min/max per the specification. The 8865 * expected common case is a "reasonable" value that converts directly 8866 * to modest integer. The EABI convert function isn't doing this for us. 8867 */ 8868f2l_doconv: 8869 stmfd sp!, {r4, lr} 8870 mov r1, #0x5f000000 @ (float)maxlong 8871 mov r4, r0 8872 bl __aeabi_fcmpge @ is arg >= maxlong? 8873 cmp r0, #0 @ nonzero == yes 8874 mvnne r0, #0 @ return maxlong (7fffffff) 8875 mvnne r1, #0x80000000 8876 ldmnefd sp!, {r4, pc} 8877 8878 mov r0, r4 @ recover arg 8879 mov r1, #0xdf000000 @ (float)minlong 8880 bl __aeabi_fcmple @ is arg <= minlong? 8881 cmp r0, #0 @ nonzero == yes 8882 movne r0, #0 @ return minlong (80000000) 8883 movne r1, #0x80000000 8884 ldmnefd sp!, {r4, pc} 8885 8886 mov r0, r4 @ recover arg 8887 mov r1, r4 8888 bl __aeabi_fcmpeq @ is arg == self? 8889 cmp r0, #0 @ zero == no 8890 moveq r1, #0 @ return zero for NaN 8891 ldmeqfd sp!, {r4, pc} 8892 8893 mov r0, r4 @ recover arg 8894 bl __aeabi_f2lz @ convert float to long 8895 ldmfd sp!, {r4, pc} 8896 8897 8898/* continuation for OP_DOUBLE_TO_LONG */ 8899/* 8900 * Convert the double in r0/r1 to a long in r0/r1. 8901 * 8902 * We have to clip values to long min/max per the specification. The 8903 * expected common case is a "reasonable" value that converts directly 8904 * to modest integer. The EABI convert function isn't doing this for us. 8905 */ 8906d2l_doconv: 8907 stmfd sp!, {r4, r5, lr} @ save regs 8908 mov r3, #0x43000000 @ maxlong, as a double (high word) 8909 add r3, #0x00e00000 @ 0x43e00000 8910 mov r2, #0 @ maxlong, as a double (low word) 8911 sub sp, sp, #4 @ align for EABI 8912 mov r4, r0 @ save a copy of r0 8913 mov r5, r1 @ and r1 8914 bl __aeabi_dcmpge @ is arg >= maxlong? 8915 cmp r0, #0 @ nonzero == yes 8916 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 8917 mvnne r1, #0x80000000 8918 bne 1f 8919 8920 mov r0, r4 @ recover arg 8921 mov r1, r5 8922 mov r3, #0xc3000000 @ minlong, as a double (high word) 8923 add r3, #0x00e00000 @ 0xc3e00000 8924 mov r2, #0 @ minlong, as a double (low word) 8925 bl __aeabi_dcmple @ is arg <= minlong? 8926 cmp r0, #0 @ nonzero == yes 8927 movne r0, #0 @ return minlong (8000000000000000) 8928 movne r1, #0x80000000 8929 bne 1f 8930 8931 mov r0, r4 @ recover arg 8932 mov r1, r5 8933 mov r2, r4 @ compare against self 8934 mov r3, r5 8935 bl __aeabi_dcmpeq @ is arg == self? 8936 cmp r0, #0 @ zero == no 8937 moveq r1, #0 @ return zero for NaN 8938 beq 1f 8939 8940 mov r0, r4 @ recover arg 8941 mov r1, r5 8942 bl __aeabi_d2lz @ convert double to long 8943 89441: 8945 add sp, sp, #4 8946 ldmfd sp!, {r4, r5, pc} 8947 8948 8949/* continuation for OP_MUL_LONG */ 8950 8951.LOP_MUL_LONG_finish: 8952 GET_INST_OPCODE(ip) @ extract opcode from rINST 8953 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 8954 GOTO_OPCODE(ip) @ jump to next instruction 8955 8956 8957/* continuation for OP_SHL_LONG */ 8958 8959.LOP_SHL_LONG_finish: 8960 mov r0, r0, asl r2 @ r0<- r0 << r2 8961 GET_INST_OPCODE(ip) @ extract opcode from rINST 8962 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8963 GOTO_OPCODE(ip) @ jump to next instruction 8964 8965 8966/* continuation for OP_SHR_LONG */ 8967 8968.LOP_SHR_LONG_finish: 8969 mov r1, r1, asr r2 @ r1<- r1 >> r2 8970 GET_INST_OPCODE(ip) @ extract opcode from rINST 8971 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8972 GOTO_OPCODE(ip) @ jump to next instruction 8973 8974 8975/* continuation for OP_USHR_LONG */ 8976 8977.LOP_USHR_LONG_finish: 8978 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 8979 GET_INST_OPCODE(ip) @ extract opcode from rINST 8980 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8981 GOTO_OPCODE(ip) @ jump to next instruction 8982 8983 8984/* continuation for OP_SHL_LONG_2ADDR */ 8985 8986.LOP_SHL_LONG_2ADDR_finish: 8987 GET_INST_OPCODE(ip) @ extract opcode from rINST 8988 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8989 GOTO_OPCODE(ip) @ jump to next instruction 8990 8991 8992/* continuation for OP_SHR_LONG_2ADDR */ 8993 8994.LOP_SHR_LONG_2ADDR_finish: 8995 GET_INST_OPCODE(ip) @ extract opcode from rINST 8996 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8997 GOTO_OPCODE(ip) @ jump to next instruction 8998 8999 9000/* continuation for OP_USHR_LONG_2ADDR */ 9001 9002.LOP_USHR_LONG_2ADDR_finish: 9003 GET_INST_OPCODE(ip) @ extract opcode from rINST 9004 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9005 GOTO_OPCODE(ip) @ jump to next instruction 9006 9007 9008/* continuation for OP_IGET_WIDE_VOLATILE */ 9009 9010 /* 9011 * Currently: 9012 * r0 holds resolved field 9013 * r9 holds object 9014 */ 9015.LOP_IGET_WIDE_VOLATILE_finish: 9016 cmp r9, #0 @ check object for null 9017 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9018 beq common_errNullObject @ object was null 9019 .if 1 9020 add r0, r9, r3 @ r0<- address of field 9021 bl android_quasiatomic_read_64 @ r0/r1<- contents of field 9022 .else 9023 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 9024 .endif 9025 mov r2, rINST, lsr #8 @ r2<- A+ 9026 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9027 and r2, r2, #15 @ r2<- A 9028 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 9029 GET_INST_OPCODE(ip) @ extract opcode from rINST 9030 stmia r3, {r0-r1} @ fp[A]<- r0/r1 9031 GOTO_OPCODE(ip) @ jump to next instruction 9032 9033 9034/* continuation for OP_IPUT_WIDE_VOLATILE */ 9035 9036 /* 9037 * Currently: 9038 * r0 holds resolved field 9039 * r9 holds object 9040 */ 9041.LOP_IPUT_WIDE_VOLATILE_finish: 9042 mov r2, rINST, lsr #8 @ r2<- A+ 9043 cmp r9, #0 @ check object for null 9044 and r2, r2, #15 @ r2<- A 9045 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9046 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 9047 beq common_errNullObject @ object was null 9048 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9049 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 9050 GET_INST_OPCODE(r10) @ extract opcode from rINST 9051 .if 1 9052 add r2, r9, r3 @ r2<- target address 9053 bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2 9054 .else 9055 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 9056 .endif 9057 GOTO_OPCODE(r10) @ jump to next instruction 9058 9059 9060/* continuation for OP_SGET_WIDE_VOLATILE */ 9061 9062 /* 9063 * Continuation if the field has not yet been resolved. 9064 * r1: BBBB field ref 9065 * 9066 * Returns StaticField pointer in r0. 9067 */ 9068.LOP_SGET_WIDE_VOLATILE_resolve: 9069 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9070 EXPORT_PC() @ resolve() could throw, so export now 9071 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9072 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9073 cmp r0, #0 @ success? 9074 bne .LOP_SGET_WIDE_VOLATILE_finish @ yes, finish 9075 b common_exceptionThrown @ no, handle exception 9076 9077 9078/* continuation for OP_SPUT_WIDE_VOLATILE */ 9079 9080 /* 9081 * Continuation if the field has not yet been resolved. 9082 * r1: BBBB field ref 9083 * r9: &fp[AA] 9084 * 9085 * Returns StaticField pointer in r2. 9086 */ 9087.LOP_SPUT_WIDE_VOLATILE_resolve: 9088 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9089 EXPORT_PC() @ resolve() could throw, so export now 9090 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9091 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9092 cmp r0, #0 @ success? 9093 mov r2, r0 @ copy to r2 9094 bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish 9095 b common_exceptionThrown @ no, handle exception 9096 9097 9098/* continuation for OP_EXECUTE_INLINE */ 9099 9100 /* 9101 * Extract args, call function. 9102 * r0 = #of args (0-4) 9103 * r10 = call index 9104 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9105 * 9106 * Other ideas: 9107 * - Use a jump table from the main piece to jump directly into the 9108 * AND/LDR pairs. Costs a data load, saves a branch. 9109 * - Have five separate pieces that do the loading, so we can work the 9110 * interleave a little better. Increases code size. 9111 */ 9112.LOP_EXECUTE_INLINE_continue: 9113 rsb r0, r0, #4 @ r0<- 4-r0 9114 FETCH(r9, 2) @ r9<- FEDC 9115 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9116 bl common_abort @ (skipped due to ARM prefetch) 91174: and ip, r9, #0xf000 @ isolate F 9118 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 91193: and ip, r9, #0x0f00 @ isolate E 9120 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 91212: and ip, r9, #0x00f0 @ isolate D 9122 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 91231: and ip, r9, #0x000f @ isolate C 9124 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 91250: 9126 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 9127 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9128 @ (not reached) 9129 9130.LOP_EXECUTE_INLINE_table: 9131 .word gDvmInlineOpsTable 9132 9133 9134/* continuation for OP_EXECUTE_INLINE_RANGE */ 9135 9136 /* 9137 * Extract args, call function. 9138 * r0 = #of args (0-4) 9139 * r10 = call index 9140 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9141 */ 9142.LOP_EXECUTE_INLINE_RANGE_continue: 9143 rsb r0, r0, #4 @ r0<- 4-r0 9144 FETCH(r9, 2) @ r9<- CCCC 9145 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9146 bl common_abort @ (skipped due to ARM prefetch) 91474: add ip, r9, #3 @ base+3 9148 GET_VREG(r3, ip) @ r3<- vBase[3] 91493: add ip, r9, #2 @ base+2 9150 GET_VREG(r2, ip) @ r2<- vBase[2] 91512: add ip, r9, #1 @ base+1 9152 GET_VREG(r1, ip) @ r1<- vBase[1] 91531: add ip, r9, #0 @ (nop) 9154 GET_VREG(r0, ip) @ r0<- vBase[0] 91550: 9156 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation 9157 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9158 @ (not reached) 9159 9160.LOP_EXECUTE_INLINE_RANGE_table: 9161 .word gDvmInlineOpsTable 9162 9163 9164 .size dvmAsmSisterStart, .-dvmAsmSisterStart 9165 .global dvmAsmSisterEnd 9166dvmAsmSisterEnd: 9167 9168/* File: armv5te/footer.S */ 9169 9170/* 9171 * =========================================================================== 9172 * Common subroutines and data 9173 * =========================================================================== 9174 */ 9175 9176 9177 9178 .text 9179 .align 2 9180 9181#if defined(WITH_JIT) 9182#if defined(WITH_SELF_VERIFICATION) 9183 .global dvmJitToInterpPunt 9184dvmJitToInterpPunt: 9185 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9186 mov r2,#kSVSPunt @ r2<- interpreter entry point 9187 mov r3, #0 9188 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9189 b jitSVShadowRunEnd @ doesn't return 9190 9191 .global dvmJitToInterpSingleStep 9192dvmJitToInterpSingleStep: 9193 str lr,[rGLUE,#offGlue_jitResumeNPC] 9194 str r1,[rGLUE,#offGlue_jitResumeDPC] 9195 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 9196 b jitSVShadowRunEnd @ doesn't return 9197 9198 .global dvmJitToInterpTraceSelectNoChain 9199dvmJitToInterpTraceSelectNoChain: 9200 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9201 mov r0,rPC @ pass our target PC 9202 mov r2,#kSVSTraceSelectNoChain @ r2<- interpreter entry point 9203 mov r3, #0 9204 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9205 b jitSVShadowRunEnd @ doesn't return 9206 9207 .global dvmJitToInterpTraceSelect 9208dvmJitToInterpTraceSelect: 9209 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9210 ldr r0,[lr, #-1] @ pass our target PC 9211 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9212 mov r3, #0 9213 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9214 b jitSVShadowRunEnd @ doesn't return 9215 9216 .global dvmJitToInterpBackwardBranch 9217dvmJitToInterpBackwardBranch: 9218 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9219 ldr r0,[lr, #-1] @ pass our target PC 9220 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 9221 mov r3, #0 9222 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9223 b jitSVShadowRunEnd @ doesn't return 9224 9225 .global dvmJitToInterpNormal 9226dvmJitToInterpNormal: 9227 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9228 ldr r0,[lr, #-1] @ pass our target PC 9229 mov r2,#kSVSNormal @ r2<- interpreter entry point 9230 mov r3, #0 9231 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9232 b jitSVShadowRunEnd @ doesn't return 9233 9234 .global dvmJitToInterpNoChain 9235dvmJitToInterpNoChain: 9236 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9237 mov r0,rPC @ pass our target PC 9238 mov r2,#kSVSNoChain @ r2<- interpreter entry point 9239 mov r3, #0 9240 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9241 b jitSVShadowRunEnd @ doesn't return 9242#else 9243/* 9244 * Return from the translation cache to the interpreter when the compiler is 9245 * having issues translating/executing a Dalvik instruction. We have to skip 9246 * the code cache lookup otherwise it is possible to indefinitely bouce 9247 * between the interpreter and the code cache if the instruction that fails 9248 * to be compiled happens to be at a trace start. 9249 */ 9250 .global dvmJitToInterpPunt 9251dvmJitToInterpPunt: 9252 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9253 mov rPC, r0 9254#ifdef JIT_STATS 9255 mov r0,lr 9256 bl dvmBumpPunt; 9257#endif 9258 EXPORT_PC() 9259 mov r0, #0 9260 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9261 adrl rIBASE, dvmAsmInstructionStart 9262 FETCH_INST() 9263 GET_INST_OPCODE(ip) 9264 GOTO_OPCODE(ip) 9265 9266/* 9267 * Return to the interpreter to handle a single instruction. 9268 * On entry: 9269 * r0 <= PC 9270 * r1 <= PC of resume instruction 9271 * lr <= resume point in translation 9272 */ 9273 .global dvmJitToInterpSingleStep 9274dvmJitToInterpSingleStep: 9275 str lr,[rGLUE,#offGlue_jitResumeNPC] 9276 str r1,[rGLUE,#offGlue_jitResumeDPC] 9277 mov r1,#kInterpEntryInstr 9278 @ enum is 4 byte in aapcs-EABI 9279 str r1, [rGLUE, #offGlue_entryPoint] 9280 mov rPC,r0 9281 EXPORT_PC() 9282 9283 adrl rIBASE, dvmAsmInstructionStart 9284 mov r2,#kJitSingleStep @ Ask for single step and then revert 9285 str r2,[rGLUE,#offGlue_jitState] 9286 mov r1,#1 @ set changeInterp to bail to debug interp 9287 b common_gotoBail 9288 9289/* 9290 * Return from the translation cache and immediately request 9291 * a translation for the exit target. Commonly used for callees. 9292 */ 9293 .global dvmJitToInterpTraceSelectNoChain 9294dvmJitToInterpTraceSelectNoChain: 9295#ifdef JIT_STATS 9296 bl dvmBumpNoChain 9297#endif 9298 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9299 mov r0,rPC 9300 bl dvmJitGetCodeAddr @ Is there a translation? 9301 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9302 mov r1, rPC @ arg1 of translation may need this 9303 mov lr, #0 @ in case target is HANDLER_INTERPRET 9304 cmp r0,#0 9305 bxne r0 @ continue native execution if so 9306 b 2f 9307 9308/* 9309 * Return from the translation cache and immediately request 9310 * a translation for the exit target. Commonly used following 9311 * invokes. 9312 */ 9313 .global dvmJitToInterpTraceSelect 9314dvmJitToInterpTraceSelect: 9315 ldr rPC,[lr, #-1] @ get our target PC 9316 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9317 add rINST,lr,#-5 @ save start of chain branch 9318 mov r0,rPC 9319 bl dvmJitGetCodeAddr @ Is there a translation? 9320 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9321 cmp r0,#0 9322 beq 2f 9323 mov r1,rINST 9324 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9325 mov r1, rPC @ arg1 of translation may need this 9326 mov lr, #0 @ in case target is HANDLER_INTERPRET 9327 cmp r0,#0 @ successful chain? 9328 bxne r0 @ continue native execution 9329 b toInterpreter @ didn't chain - resume with interpreter 9330 9331/* No translation, so request one if profiling isn't disabled*/ 93322: 9333 adrl rIBASE, dvmAsmInstructionStart 9334 GET_JIT_PROF_TABLE(r0) 9335 FETCH_INST() 9336 cmp r0, #0 9337 movne r2,#kJitTSelectRequestHot @ ask for trace selection 9338 bne common_selectTrace 9339 GET_INST_OPCODE(ip) 9340 GOTO_OPCODE(ip) 9341 9342/* 9343 * Return from the translation cache to the interpreter. 9344 * The return was done with a BLX from thumb mode, and 9345 * the following 32-bit word contains the target rPC value. 9346 * Note that lr (r14) will have its low-order bit set to denote 9347 * its thumb-mode origin. 9348 * 9349 * We'll need to stash our lr origin away, recover the new 9350 * target and then check to see if there is a translation available 9351 * for our new target. If so, we do a translation chain and 9352 * go back to native execution. Otherwise, it's back to the 9353 * interpreter (after treating this entry as a potential 9354 * trace start). 9355 */ 9356 .global dvmJitToInterpNormal 9357dvmJitToInterpNormal: 9358 ldr rPC,[lr, #-1] @ get our target PC 9359 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9360 add rINST,lr,#-5 @ save start of chain branch 9361#ifdef JIT_STATS 9362 bl dvmBumpNormal 9363#endif 9364 mov r0,rPC 9365 bl dvmJitGetCodeAddr @ Is there a translation? 9366 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9367 cmp r0,#0 9368 beq toInterpreter @ go if not, otherwise do chain 9369 mov r1,rINST 9370 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9371 mov r1, rPC @ arg1 of translation may need this 9372 mov lr, #0 @ in case target is HANDLER_INTERPRET 9373 cmp r0,#0 @ successful chain? 9374 bxne r0 @ continue native execution 9375 b toInterpreter @ didn't chain - resume with interpreter 9376 9377/* 9378 * Return from the translation cache to the interpreter to do method invocation. 9379 * Check if translation exists for the callee, but don't chain to it. 9380 */ 9381 .global dvmJitToInterpNoChain 9382dvmJitToInterpNoChain: 9383#ifdef JIT_STATS 9384 bl dvmBumpNoChain 9385#endif 9386 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9387 mov r0,rPC 9388 bl dvmJitGetCodeAddr @ Is there a translation? 9389 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9390 mov r1, rPC @ arg1 of translation may need this 9391 mov lr, #0 @ in case target is HANDLER_INTERPRET 9392 cmp r0,#0 9393 bxne r0 @ continue native execution if so 9394#endif 9395 9396/* 9397 * No translation, restore interpreter regs and start interpreting. 9398 * rGLUE & rFP were preserved in the translated code, and rPC has 9399 * already been restored by the time we get here. We'll need to set 9400 * up rIBASE & rINST, and load the address of the JitTable into r0. 9401 */ 9402toInterpreter: 9403 EXPORT_PC() 9404 adrl rIBASE, dvmAsmInstructionStart 9405 FETCH_INST() 9406 GET_JIT_PROF_TABLE(r0) 9407 @ NOTE: intended fallthrough 9408/* 9409 * Common code to update potential trace start counter, and initiate 9410 * a trace-build if appropriate. On entry, rPC should point to the 9411 * next instruction to execute, and rINST should be already loaded with 9412 * the next opcode word, and r0 holds a pointer to the jit profile 9413 * table (pJitProfTable). 9414 */ 9415common_testUpdateProfile: 9416 cmp r0,#0 9417 GET_INST_OPCODE(ip) 9418 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 9419 9420common_updateProfile: 9421 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 9422 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits 9423 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter 9424 GET_INST_OPCODE(ip) 9425 subs r1,r1,#1 @ decrement counter 9426 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it 9427 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 9428 9429/* 9430 * Here, we switch to the debug interpreter to request 9431 * trace selection. First, though, check to see if there 9432 * is already a native translation in place (and, if so, 9433 * jump to it now). 9434 */ 9435 GET_JIT_THRESHOLD(r1) 9436 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9437 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter 9438 EXPORT_PC() 9439 mov r0,rPC 9440 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC) 9441 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9442 mov r1, rPC @ arg1 of translation may need this 9443 mov lr, #0 @ in case target is HANDLER_INTERPRET 9444 cmp r0,#0 9445#if !defined(WITH_SELF_VERIFICATION) 9446 bxne r0 @ jump to the translation 9447 mov r2,#kJitTSelectRequest @ ask for trace selection 9448 @ fall-through to common_selectTrace 9449#else 9450 moveq r2,#kJitTSelectRequest @ ask for trace selection 9451 beq common_selectTrace 9452 /* 9453 * At this point, we have a target translation. However, if 9454 * that translation is actually the interpret-only pseudo-translation 9455 * we want to treat it the same as no translation. 9456 */ 9457 mov r10, r0 @ save target 9458 bl dvmCompilerGetInterpretTemplate 9459 cmp r0, r10 @ special case? 9460 bne jitSVShadowRunStart @ set up self verification shadow space 9461 GET_INST_OPCODE(ip) 9462 GOTO_OPCODE(ip) 9463 /* no return */ 9464#endif 9465 9466/* 9467 * On entry: 9468 * r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot 9469 */ 9470common_selectTrace: 9471 str r2,[rGLUE,#offGlue_jitState] 9472 mov r2,#kInterpEntryInstr @ normal entry reason 9473 str r2,[rGLUE,#offGlue_entryPoint] 9474 mov r1,#1 @ set changeInterp 9475 b common_gotoBail 9476 9477#if defined(WITH_SELF_VERIFICATION) 9478/* 9479 * Save PC and registers to shadow memory for self verification mode 9480 * before jumping to native translation. 9481 * On entry: 9482 * rPC, rFP, rGLUE: the values that they should contain 9483 * r10: the address of the target translation. 9484 */ 9485jitSVShadowRunStart: 9486 mov r0,rPC @ r0<- program counter 9487 mov r1,rFP @ r1<- frame pointer 9488 mov r2,rGLUE @ r2<- InterpState pointer 9489 mov r3,r10 @ r3<- target translation 9490 bl dvmSelfVerificationSaveState @ save registers to shadow space 9491 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 9492 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 9493 bx r10 @ jump to the translation 9494 9495/* 9496 * Restore PC, registers, and interpState to original values 9497 * before jumping back to the interpreter. 9498 */ 9499jitSVShadowRunEnd: 9500 mov r1,rFP @ pass ending fp 9501 bl dvmSelfVerificationRestoreState @ restore pc and fp values 9502 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 9503 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 9504 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 9505 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 9506 cmp r1,#0 @ check for punt condition 9507 beq 1f 9508 mov r2,#kJitSelfVerification @ ask for self verification 9509 str r2,[rGLUE,#offGlue_jitState] 9510 mov r2,#kInterpEntryInstr @ normal entry reason 9511 str r2,[rGLUE,#offGlue_entryPoint] 9512 mov r1,#1 @ set changeInterp 9513 b common_gotoBail 9514 95151: @ exit to interpreter without check 9516 EXPORT_PC() 9517 adrl rIBASE, dvmAsmInstructionStart 9518 FETCH_INST() 9519 GET_INST_OPCODE(ip) 9520 GOTO_OPCODE(ip) 9521#endif 9522 9523#endif 9524 9525/* 9526 * Common code when a backward branch is taken. 9527 * 9528 * TODO: we could avoid a branch by just setting r0 and falling through 9529 * into the common_periodicChecks code, and having a test on r0 at the 9530 * end determine if we should return to the caller or update & branch to 9531 * the next instr. 9532 * 9533 * On entry: 9534 * r9 is PC adjustment *in bytes* 9535 */ 9536common_backwardBranch: 9537 mov r0, #kInterpEntryInstr 9538 bl common_periodicChecks 9539#if defined(WITH_JIT) 9540 GET_JIT_PROF_TABLE(r0) 9541 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9542 cmp r0,#0 9543 bne common_updateProfile 9544 GET_INST_OPCODE(ip) 9545 GOTO_OPCODE(ip) 9546#else 9547 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9548 GET_INST_OPCODE(ip) @ extract opcode from rINST 9549 GOTO_OPCODE(ip) @ jump to next instruction 9550#endif 9551 9552 9553/* 9554 * Need to see if the thread needs to be suspended or debugger/profiler 9555 * activity has begun. If so, we suspend the thread or side-exit to 9556 * the debug interpreter as appropriate. 9557 * 9558 * The common case is no activity on any of these, so we want to figure 9559 * that out quickly. If something is up, we can then sort out what. 9560 * 9561 * We want to be fast if the VM was built without debugger or profiler 9562 * support, but we also need to recognize that the system is usually 9563 * shipped with both of these enabled. 9564 * 9565 * TODO: reduce this so we're just checking a single location. 9566 * 9567 * On entry: 9568 * r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling) 9569 * r9 is trampoline PC adjustment *in bytes* 9570 */ 9571common_periodicChecks: 9572 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9573 9574#if defined(WITH_DEBUGGER) 9575 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9576#endif 9577#if defined(WITH_PROFILER) 9578 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9579#endif 9580 9581 ldr ip, [r3] @ ip<- suspendCount (int) 9582 9583#if defined(WITH_DEBUGGER) && defined(WITH_PROFILER) 9584 cmp r1, #0 @ debugger enabled? 9585 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9586 ldr r2, [r2] @ r2<- activeProfilers (int) 9587 orrne ip, ip, r1 @ ip<- suspendCount | debuggerActive 9588 orrs ip, ip, r2 @ ip<- suspend|debugger|profiler; set Z 9589#elif defined(WITH_DEBUGGER) 9590 cmp r1, #0 @ debugger enabled? 9591 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9592 orrsne ip, ip, r1 @ yes, ip<- suspend | debugger; set Z 9593 @ (if not enabled, Z was set by test for r1==0, which is what we want) 9594#elif defined (WITH_PROFILER) 9595 ldr r2, [r2] @ r2<- activeProfilers (int) 9596 orrs ip, ip, r2 @ ip<- suspendCount | activeProfilers 9597#else 9598 cmp ip, #0 @ not ORing anything in; set Z 9599#endif 9600 9601 bxeq lr @ all zero, return 9602 9603 /* 9604 * One or more interesting events have happened. Figure out what. 9605 * 9606 * If debugging or profiling are compiled in, we need to disambiguate. 9607 * 9608 * r0 still holds the reentry type. 9609 */ 9610#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 9611 ldr ip, [r3] @ ip<- suspendCount (int) 9612 cmp ip, #0 @ want suspend? 9613 beq 1f @ no, must be debugger/profiler 9614#endif 9615 9616 stmfd sp!, {r0, lr} @ preserve r0 and lr 9617#if defined(WITH_JIT) 9618 /* 9619 * Refresh the Jit's cached copy of profile table pointer. This pointer 9620 * doubles as the Jit's on/off switch. 9621 */ 9622 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable 9623 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9624 ldr r3, [r3] @ r3 <- pJitProfTable 9625 EXPORT_PC() @ need for precise GC 9626 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch 9627#else 9628 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9629 EXPORT_PC() @ need for precise GC 9630#endif 9631 bl dvmCheckSuspendPending @ do full check, suspend if necessary 9632 ldmfd sp!, {r0, lr} @ restore r0 and lr 9633 9634#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 9635 9636 /* 9637 * Reload the debugger/profiler enable flags. We're checking to see 9638 * if either of these got set while we were suspended. 9639 * 9640 * We can't really avoid the #ifdefs here, because the fields don't 9641 * exist when the feature is disabled. 9642 */ 9643#if defined(WITH_DEBUGGER) 9644 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9645 cmp r1, #0 @ debugger enabled? 9646 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9647#else 9648 mov r1, #0 9649#endif 9650#if defined(WITH_PROFILER) 9651 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9652 ldr r2, [r2] @ r2<- activeProfilers (int) 9653#else 9654 mov r2, #0 9655#endif 9656 9657 orrs r1, r1, r2 9658 beq 2f 9659 96601: @ debugger/profiler enabled, bail out; glue->entryPoint was set above 9661 str r0, [rGLUE, #offGlue_entryPoint] @ store r0, need for debug/prof 9662 add rPC, rPC, r9 @ update rPC 9663 mov r1, #1 @ "want switch" = true 9664 b common_gotoBail @ side exit 9665 9666#endif /*WITH_DEBUGGER || WITH_PROFILER*/ 9667 96682: 9669 bx lr @ nothing to do, return 9670 9671 9672/* 9673 * The equivalent of "goto bail", this calls through the "bail handler". 9674 * 9675 * State registers will be saved to the "glue" area before bailing. 9676 * 9677 * On entry: 9678 * r1 is "bool changeInterp", indicating if we want to switch to the 9679 * other interpreter or just bail all the way out 9680 */ 9681common_gotoBail: 9682 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9683 mov r0, rGLUE @ r0<- glue ptr 9684 b dvmMterpStdBail @ call(glue, changeInterp) 9685 9686 @add r1, r1, #1 @ using (boolean+1) 9687 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9688 @bl _longjmp @ does not return 9689 @bl common_abort 9690 9691 9692/* 9693 * Common code for method invocation with range. 9694 * 9695 * On entry: 9696 * r0 is "Method* methodToCall", the method we're trying to call 9697 */ 9698common_invokeMethodRange: 9699.LinvokeNewRange: 9700 @ prepare to copy args to "outs" area of current frame 9701 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9702 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9703 beq .LinvokeArgsDone @ if no args, skip the rest 9704 FETCH(r1, 2) @ r1<- CCCC 9705 9706 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9707 @ (very few methods have > 10 args; could unroll for common cases) 9708 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9709 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9710 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 97111: ldr r1, [r3], #4 @ val = *fp++ 9712 subs r2, r2, #1 @ count-- 9713 str r1, [r10], #4 @ *outs++ = val 9714 bne 1b @ ...while count != 0 9715 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9716 b .LinvokeArgsDone 9717 9718/* 9719 * Common code for method invocation without range. 9720 * 9721 * On entry: 9722 * r0 is "Method* methodToCall", the method we're trying to call 9723 */ 9724common_invokeMethodNoRange: 9725.LinvokeNewNoRange: 9726 @ prepare to copy args to "outs" area of current frame 9727 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9728 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9729 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9730 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9731 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9732 beq .LinvokeArgsDone 9733 9734 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9735.LinvokeNonRange: 9736 rsb r2, r2, #5 @ r2<- 5-r2 9737 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9738 bl common_abort @ (skipped due to ARM prefetch) 97395: and ip, rINST, #0x0f00 @ isolate A 9740 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 9741 mov r0, r0 @ nop 9742 str r2, [r10, #-4]! @ *--outs = vA 97434: and ip, r1, #0xf000 @ isolate G 9744 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 9745 mov r0, r0 @ nop 9746 str r2, [r10, #-4]! @ *--outs = vG 97473: and ip, r1, #0x0f00 @ isolate F 9748 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 9749 mov r0, r0 @ nop 9750 str r2, [r10, #-4]! @ *--outs = vF 97512: and ip, r1, #0x00f0 @ isolate E 9752 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 9753 mov r0, r0 @ nop 9754 str r2, [r10, #-4]! @ *--outs = vE 97551: and ip, r1, #0x000f @ isolate D 9756 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 9757 mov r0, r0 @ nop 9758 str r2, [r10, #-4]! @ *--outs = vD 97590: @ fall through to .LinvokeArgsDone 9760 9761.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 9762 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 9763 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 9764 @ find space for the new stack frame, check for overflow 9765 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 9766 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 9767 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 9768@ bl common_dumpRegs 9769 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 9770 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 9771 cmp r3, r9 @ bottom < interpStackEnd? 9772 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 9773 blo .LstackOverflow @ yes, this frame will overflow stack 9774 9775 @ set up newSaveArea 9776#ifdef EASY_GDB 9777 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 9778 str ip, [r10, #offStackSaveArea_prevSave] 9779#endif 9780 str rFP, [r10, #offStackSaveArea_prevFrame] 9781 str rPC, [r10, #offStackSaveArea_savedPc] 9782#if defined(WITH_JIT) 9783 mov r9, #0 9784 str r9, [r10, #offStackSaveArea_returnAddr] 9785#endif 9786 str r0, [r10, #offStackSaveArea_method] 9787 tst r3, #ACC_NATIVE 9788 bne .LinvokeNative 9789 9790 /* 9791 stmfd sp!, {r0-r3} 9792 bl common_printNewline 9793 mov r0, rFP 9794 mov r1, #0 9795 bl dvmDumpFp 9796 ldmfd sp!, {r0-r3} 9797 stmfd sp!, {r0-r3} 9798 mov r0, r1 9799 mov r1, r10 9800 bl dvmDumpFp 9801 bl common_printNewline 9802 ldmfd sp!, {r0-r3} 9803 */ 9804 9805 ldrh r9, [r2] @ r9 <- load INST from new PC 9806 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 9807 mov rPC, r2 @ publish new rPC 9808 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 9809 9810 @ Update "glue" values for the new method 9811 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 9812 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 9813 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 9814#if defined(WITH_JIT) 9815 GET_JIT_PROF_TABLE(r0) 9816 mov rFP, r1 @ fp = newFp 9817 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9818 mov rINST, r9 @ publish new rINST 9819 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9820 cmp r0,#0 9821 bne common_updateProfile 9822 GOTO_OPCODE(ip) @ jump to next instruction 9823#else 9824 mov rFP, r1 @ fp = newFp 9825 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9826 mov rINST, r9 @ publish new rINST 9827 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9828 GOTO_OPCODE(ip) @ jump to next instruction 9829#endif 9830 9831.LinvokeNative: 9832 @ Prep for the native call 9833 @ r0=methodToCall, r1=newFp, r10=newSaveArea 9834 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9835 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 9836 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 9837 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 9838 mov r9, r3 @ r9<- glue->self (preserve) 9839 9840 mov r2, r0 @ r2<- methodToCall 9841 mov r0, r1 @ r0<- newFp (points to args) 9842 add r1, rGLUE, #offGlue_retval @ r1<- &retval 9843 9844#ifdef ASSIST_DEBUGGER 9845 /* insert fake function header to help gdb find the stack frame */ 9846 b .Lskip 9847 .type dalvik_mterp, %function 9848dalvik_mterp: 9849 .fnstart 9850 MTERP_ENTRY1 9851 MTERP_ENTRY2 9852.Lskip: 9853#endif 9854 9855 @mov lr, pc @ set return addr 9856 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 9857 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 9858 9859#if defined(WITH_JIT) 9860 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status 9861#endif 9862 9863 @ native return; r9=self, r10=newSaveArea 9864 @ equivalent to dvmPopJniLocals 9865 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 9866 ldr r1, [r9, #offThread_exception] @ check for exception 9867#if defined(WITH_JIT) 9868 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable 9869#endif 9870 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 9871 cmp r1, #0 @ null? 9872 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 9873#if defined(WITH_JIT) 9874 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch 9875#endif 9876 bne common_exceptionThrown @ no, handle exception 9877 9878 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 9879 GET_INST_OPCODE(ip) @ extract opcode from rINST 9880 GOTO_OPCODE(ip) @ jump to next instruction 9881 9882.LstackOverflow: @ r0=methodToCall 9883 mov r1, r0 @ r1<- methodToCall 9884 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 9885 bl dvmHandleStackOverflow 9886 b common_exceptionThrown 9887#ifdef ASSIST_DEBUGGER 9888 .fnend 9889#endif 9890 9891 9892 /* 9893 * Common code for method invocation, calling through "glue code". 9894 * 9895 * TODO: now that we have range and non-range invoke handlers, this 9896 * needs to be split into two. Maybe just create entry points 9897 * that set r9 and jump here? 9898 * 9899 * On entry: 9900 * r0 is "Method* methodToCall", the method we're trying to call 9901 * r9 is "bool methodCallRange", indicating if this is a /range variant 9902 */ 9903 .if 0 9904.LinvokeOld: 9905 sub sp, sp, #8 @ space for args + pad 9906 FETCH(ip, 2) @ ip<- FEDC or CCCC 9907 mov r2, r0 @ A2<- methodToCall 9908 mov r0, rGLUE @ A0<- glue 9909 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9910 mov r1, r9 @ A1<- methodCallRange 9911 mov r3, rINST, lsr #8 @ A3<- AA 9912 str ip, [sp, #0] @ A4<- ip 9913 bl dvmMterp_invokeMethod @ call the C invokeMethod 9914 add sp, sp, #8 @ remove arg area 9915 b common_resumeAfterGlueCall @ continue to next instruction 9916 .endif 9917 9918 9919 9920/* 9921 * Common code for handling a return instruction. 9922 * 9923 * This does not return. 9924 */ 9925common_returnFromMethod: 9926.LreturnNew: 9927 mov r0, #kInterpEntryReturn 9928 mov r9, #0 9929 bl common_periodicChecks 9930 9931 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 9932 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 9933 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 9934 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 9935 @ r2<- method we're returning to 9936 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9937 cmp r2, #0 @ is this a break frame? 9938 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 9939 mov r1, #0 @ "want switch" = false 9940 beq common_gotoBail @ break frame, bail out completely 9941 9942 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 9943 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 9944 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 9945 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 9946#if defined(WITH_JIT) 9947 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr 9948 GET_JIT_PROF_TABLE(r0) 9949 mov rPC, r9 @ publish new rPC 9950 str r1, [rGLUE, #offGlue_methodClassDex] 9951 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land 9952 cmp r10, #0 @ caller is compiled code 9953 blxne r10 9954 GET_INST_OPCODE(ip) @ extract opcode from rINST 9955 cmp r0,#0 9956 bne common_updateProfile 9957 GOTO_OPCODE(ip) @ jump to next instruction 9958#else 9959 GET_INST_OPCODE(ip) @ extract opcode from rINST 9960 mov rPC, r9 @ publish new rPC 9961 str r1, [rGLUE, #offGlue_methodClassDex] 9962 GOTO_OPCODE(ip) @ jump to next instruction 9963#endif 9964 9965 /* 9966 * Return handling, calls through "glue code". 9967 */ 9968 .if 0 9969.LreturnOld: 9970 SAVE_PC_FP_TO_GLUE() @ export state 9971 mov r0, rGLUE @ arg to function 9972 bl dvmMterp_returnFromMethod 9973 b common_resumeAfterGlueCall 9974 .endif 9975 9976 9977/* 9978 * Somebody has thrown an exception. Handle it. 9979 * 9980 * If the exception processing code returns to us (instead of falling 9981 * out of the interpreter), continue with whatever the next instruction 9982 * now happens to be. 9983 * 9984 * This does not return. 9985 */ 9986 .global dvmMterpCommonExceptionThrown 9987dvmMterpCommonExceptionThrown: 9988common_exceptionThrown: 9989.LexceptionNew: 9990 mov r0, #kInterpEntryThrow 9991 mov r9, #0 9992 bl common_periodicChecks 9993 9994 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 9995 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 9996 mov r1, r10 @ r1<- self 9997 mov r0, r9 @ r0<- exception 9998 bl dvmAddTrackedAlloc @ don't let the exception be GCed 9999 mov r3, #0 @ r3<- NULL 10000 str r3, [r10, #offThread_exception] @ self->exception = NULL 10001 10002 /* set up args and a local for "&fp" */ 10003 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 10004 str rFP, [sp, #-4]! @ *--sp = fp 10005 mov ip, sp @ ip<- &fp 10006 mov r3, #0 @ r3<- false 10007 str ip, [sp, #-4]! @ *--sp = &fp 10008 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 10009 mov r0, r10 @ r0<- self 10010 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 10011 mov r2, r9 @ r2<- exception 10012 sub r1, rPC, r1 @ r1<- pc - method->insns 10013 mov r1, r1, asr #1 @ r1<- offset in code units 10014 10015 /* call, r0 gets catchRelPc (a code-unit offset) */ 10016 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 10017 10018 /* fix earlier stack overflow if necessary; may trash rFP */ 10019 ldrb r1, [r10, #offThread_stackOverflowed] 10020 cmp r1, #0 @ did we overflow earlier? 10021 beq 1f @ no, skip ahead 10022 mov rFP, r0 @ save relPc result in rFP 10023 mov r0, r10 @ r0<- self 10024 mov r1, r9 @ r1<- exception 10025 bl dvmCleanupStackOverflow @ call(self) 10026 mov r0, rFP @ restore result 100271: 10028 10029 /* update frame pointer and check result from dvmFindCatchBlock */ 10030 ldr rFP, [sp, #4] @ retrieve the updated rFP 10031 cmp r0, #0 @ is catchRelPc < 0? 10032 add sp, sp, #8 @ restore stack 10033 bmi .LnotCaughtLocally 10034 10035 /* adjust locals to match self->curFrame and updated PC */ 10036 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 10037 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 10038 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 10039 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 10040 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 10041 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 10042 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 10043 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 10044 10045 /* release the tracked alloc on the exception */ 10046 mov r0, r9 @ r0<- exception 10047 mov r1, r10 @ r1<- self 10048 bl dvmReleaseTrackedAlloc @ release the exception 10049 10050 /* restore the exception if the handler wants it */ 10051 FETCH_INST() @ load rINST from rPC 10052 GET_INST_OPCODE(ip) @ extract opcode from rINST 10053 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 10054 streq r9, [r10, #offThread_exception] @ yes, restore the exception 10055 GOTO_OPCODE(ip) @ jump to next instruction 10056 10057.LnotCaughtLocally: @ r9=exception, r10=self 10058 /* fix stack overflow if necessary */ 10059 ldrb r1, [r10, #offThread_stackOverflowed] 10060 cmp r1, #0 @ did we overflow earlier? 10061 movne r0, r10 @ if yes: r0<- self 10062 movne r1, r9 @ if yes: r1<- exception 10063 blne dvmCleanupStackOverflow @ if yes: call(self) 10064 10065 @ may want to show "not caught locally" debug messages here 10066#if DVM_SHOW_EXCEPTION >= 2 10067 /* call __android_log_print(prio, tag, format, ...) */ 10068 /* "Exception %s from %s:%d not caught locally" */ 10069 @ dvmLineNumFromPC(method, pc - method->insns) 10070 ldr r0, [rGLUE, #offGlue_method] 10071 ldr r1, [r0, #offMethod_insns] 10072 sub r1, rPC, r1 10073 asr r1, r1, #1 10074 bl dvmLineNumFromPC 10075 str r0, [sp, #-4]! 10076 @ dvmGetMethodSourceFile(method) 10077 ldr r0, [rGLUE, #offGlue_method] 10078 bl dvmGetMethodSourceFile 10079 str r0, [sp, #-4]! 10080 @ exception->clazz->descriptor 10081 ldr r3, [r9, #offObject_clazz] 10082 ldr r3, [r3, #offClassObject_descriptor] 10083 @ 10084 ldr r2, strExceptionNotCaughtLocally 10085 ldr r1, strLogTag 10086 mov r0, #3 @ LOG_DEBUG 10087 bl __android_log_print 10088#endif 10089 str r9, [r10, #offThread_exception] @ restore exception 10090 mov r0, r9 @ r0<- exception 10091 mov r1, r10 @ r1<- self 10092 bl dvmReleaseTrackedAlloc @ release the exception 10093 mov r1, #0 @ "want switch" = false 10094 b common_gotoBail @ bail out 10095 10096 10097 /* 10098 * Exception handling, calls through "glue code". 10099 */ 10100 .if 0 10101.LexceptionOld: 10102 SAVE_PC_FP_TO_GLUE() @ export state 10103 mov r0, rGLUE @ arg to function 10104 bl dvmMterp_exceptionThrown 10105 b common_resumeAfterGlueCall 10106 .endif 10107 10108 10109/* 10110 * After returning from a "glued" function, pull out the updated 10111 * values and start executing at the next instruction. 10112 */ 10113common_resumeAfterGlueCall: 10114 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 10115 FETCH_INST() @ load rINST from rPC 10116 GET_INST_OPCODE(ip) @ extract opcode from rINST 10117 GOTO_OPCODE(ip) @ jump to next instruction 10118 10119/* 10120 * Invalid array index. 10121 */ 10122common_errArrayIndex: 10123 EXPORT_PC() 10124 ldr r0, strArrayIndexException 10125 mov r1, #0 10126 bl dvmThrowException 10127 b common_exceptionThrown 10128 10129/* 10130 * Invalid array value. 10131 */ 10132common_errArrayStore: 10133 EXPORT_PC() 10134 ldr r0, strArrayStoreException 10135 mov r1, #0 10136 bl dvmThrowException 10137 b common_exceptionThrown 10138 10139/* 10140 * Integer divide or mod by zero. 10141 */ 10142common_errDivideByZero: 10143 EXPORT_PC() 10144 ldr r0, strArithmeticException 10145 ldr r1, strDivideByZero 10146 bl dvmThrowException 10147 b common_exceptionThrown 10148 10149/* 10150 * Attempt to allocate an array with a negative size. 10151 */ 10152common_errNegativeArraySize: 10153 EXPORT_PC() 10154 ldr r0, strNegativeArraySizeException 10155 mov r1, #0 10156 bl dvmThrowException 10157 b common_exceptionThrown 10158 10159/* 10160 * Invocation of a non-existent method. 10161 */ 10162common_errNoSuchMethod: 10163 EXPORT_PC() 10164 ldr r0, strNoSuchMethodError 10165 mov r1, #0 10166 bl dvmThrowException 10167 b common_exceptionThrown 10168 10169/* 10170 * We encountered a null object when we weren't expecting one. We 10171 * export the PC, throw a NullPointerException, and goto the exception 10172 * processing code. 10173 */ 10174common_errNullObject: 10175 EXPORT_PC() 10176 ldr r0, strNullPointerException 10177 mov r1, #0 10178 bl dvmThrowException 10179 b common_exceptionThrown 10180 10181/* 10182 * For debugging, cause an immediate fault. The source address will 10183 * be in lr (use a bl instruction to jump here). 10184 */ 10185common_abort: 10186 ldr pc, .LdeadFood 10187.LdeadFood: 10188 .word 0xdeadf00d 10189 10190/* 10191 * Spit out a "we were here", preserving all registers. (The attempt 10192 * to save ip won't work, but we need to save an even number of 10193 * registers for EABI 64-bit stack alignment.) 10194 */ 10195 .macro SQUEAK num 10196common_squeak\num: 10197 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10198 ldr r0, strSqueak 10199 mov r1, #\num 10200 bl printf 10201 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10202 bx lr 10203 .endm 10204 10205 SQUEAK 0 10206 SQUEAK 1 10207 SQUEAK 2 10208 SQUEAK 3 10209 SQUEAK 4 10210 SQUEAK 5 10211 10212/* 10213 * Spit out the number in r0, preserving registers. 10214 */ 10215common_printNum: 10216 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10217 mov r1, r0 10218 ldr r0, strSqueak 10219 bl printf 10220 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10221 bx lr 10222 10223/* 10224 * Print a newline, preserving registers. 10225 */ 10226common_printNewline: 10227 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10228 ldr r0, strNewline 10229 bl printf 10230 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10231 bx lr 10232 10233 /* 10234 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 10235 */ 10236common_printHex: 10237 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10238 mov r1, r0 10239 ldr r0, strPrintHex 10240 bl printf 10241 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10242 bx lr 10243 10244/* 10245 * Print the 64-bit quantity in r0-r1, preserving registers. 10246 */ 10247common_printLong: 10248 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10249 mov r3, r1 10250 mov r2, r0 10251 ldr r0, strPrintLong 10252 bl printf 10253 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10254 bx lr 10255 10256/* 10257 * Print full method info. Pass the Method* in r0. Preserves regs. 10258 */ 10259common_printMethod: 10260 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10261 bl dvmMterpPrintMethod 10262 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10263 bx lr 10264 10265/* 10266 * Call a C helper function that dumps regs and possibly some 10267 * additional info. Requires the C function to be compiled in. 10268 */ 10269 .if 0 10270common_dumpRegs: 10271 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10272 bl dvmMterpDumpArmRegs 10273 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10274 bx lr 10275 .endif 10276 10277#if 0 10278/* 10279 * Experiment on VFP mode. 10280 * 10281 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 10282 * 10283 * Updates the bits specified by "mask", setting them to the values in "val". 10284 */ 10285setFPSCR: 10286 and r0, r0, r1 @ make sure no stray bits are set 10287 fmrx r2, fpscr @ get VFP reg 10288 mvn r1, r1 @ bit-invert mask 10289 and r2, r2, r1 @ clear masked bits 10290 orr r2, r2, r0 @ set specified bits 10291 fmxr fpscr, r2 @ set VFP reg 10292 mov r0, r2 @ return new value 10293 bx lr 10294 10295 .align 2 10296 .global dvmConfigureFP 10297 .type dvmConfigureFP, %function 10298dvmConfigureFP: 10299 stmfd sp!, {ip, lr} 10300 /* 0x03000000 sets DN/FZ */ 10301 /* 0x00009f00 clears the six exception enable flags */ 10302 bl common_squeak0 10303 mov r0, #0x03000000 @ r0<- 0x03000000 10304 add r1, r0, #0x9f00 @ r1<- 0x03009f00 10305 bl setFPSCR 10306 ldmfd sp!, {ip, pc} 10307#endif 10308 10309 10310/* 10311 * String references, must be close to the code that uses them. 10312 */ 10313 .align 2 10314strArithmeticException: 10315 .word .LstrArithmeticException 10316strArrayIndexException: 10317 .word .LstrArrayIndexException 10318strArrayStoreException: 10319 .word .LstrArrayStoreException 10320strDivideByZero: 10321 .word .LstrDivideByZero 10322strNegativeArraySizeException: 10323 .word .LstrNegativeArraySizeException 10324strNoSuchMethodError: 10325 .word .LstrNoSuchMethodError 10326strNullPointerException: 10327 .word .LstrNullPointerException 10328 10329strLogTag: 10330 .word .LstrLogTag 10331strExceptionNotCaughtLocally: 10332 .word .LstrExceptionNotCaughtLocally 10333 10334strNewline: 10335 .word .LstrNewline 10336strSqueak: 10337 .word .LstrSqueak 10338strPrintHex: 10339 .word .LstrPrintHex 10340strPrintLong: 10341 .word .LstrPrintLong 10342 10343/* 10344 * Zero-terminated ASCII string data. 10345 * 10346 * On ARM we have two choices: do like gcc does, and LDR from a .word 10347 * with the address, or use an ADR pseudo-op to get the address 10348 * directly. ADR saves 4 bytes and an indirection, but it's using a 10349 * PC-relative addressing mode and hence has a limited range, which 10350 * makes it not work well with mergeable string sections. 10351 */ 10352 .section .rodata.str1.4,"aMS",%progbits,1 10353 10354.LstrBadEntryPoint: 10355 .asciz "Bad entry point %d\n" 10356.LstrArithmeticException: 10357 .asciz "Ljava/lang/ArithmeticException;" 10358.LstrArrayIndexException: 10359 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 10360.LstrArrayStoreException: 10361 .asciz "Ljava/lang/ArrayStoreException;" 10362.LstrClassCastException: 10363 .asciz "Ljava/lang/ClassCastException;" 10364.LstrDivideByZero: 10365 .asciz "divide by zero" 10366.LstrFilledNewArrayNotImpl: 10367 .asciz "filled-new-array only implemented for objects and 'int'" 10368.LstrInternalError: 10369 .asciz "Ljava/lang/InternalError;" 10370.LstrInstantiationError: 10371 .asciz "Ljava/lang/InstantiationError;" 10372.LstrNegativeArraySizeException: 10373 .asciz "Ljava/lang/NegativeArraySizeException;" 10374.LstrNoSuchMethodError: 10375 .asciz "Ljava/lang/NoSuchMethodError;" 10376.LstrNullPointerException: 10377 .asciz "Ljava/lang/NullPointerException;" 10378 10379.LstrLogTag: 10380 .asciz "mterp" 10381.LstrExceptionNotCaughtLocally: 10382 .asciz "Exception %s from %s:%d not caught locally\n" 10383 10384.LstrNewline: 10385 .asciz "\n" 10386.LstrSqueak: 10387 .asciz "<%d>" 10388.LstrPrintHex: 10389 .asciz "<0x%x>" 10390.LstrPrintLong: 10391 .asciz "<%lld>" 10392 10393 10394