InterpAsm-armv7-a.S revision 0890e5bf0b2a502ca1030e9773fabc16ef1b5981
1/* 2 * This file was generated automatically by gen-mterp.py for 'armv7-a'. 3 * 4 * --> DO NOT EDIT <-- 5 */ 6 7/* File: armv5te/header.S */ 8/* 9 * Copyright (C) 2008 The Android Open Source Project 10 * 11 * Licensed under the Apache License, Version 2.0 (the "License"); 12 * you may not use this file except in compliance with the License. 13 * You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 */ 23 24/* 25 * ARMv5 definitions and declarations. 26 */ 27 28/* 29ARM EABI general notes: 30 31r0-r3 hold first 4 args to a method; they are not preserved across method calls 32r4-r8 are available for general use 33r9 is given special treatment in some situations, but not for us 34r10 (sl) seems to be generally available 35r11 (fp) is used by gcc (unless -fomit-frame-pointer is set) 36r12 (ip) is scratch -- not preserved across method calls 37r13 (sp) should be managed carefully in case a signal arrives 38r14 (lr) must be preserved 39r15 (pc) can be tinkered with directly 40 41r0 holds returns of <= 4 bytes 42r0-r1 hold returns of 8 bytes, low word in r0 43 44Callee must save/restore r4+ (except r12) if it modifies them. If VFP 45is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved, 46s0-s15 (d0-d7, q0-a3) do not need to be. 47 48Stack is "full descending". Only the arguments that don't fit in the first 4 49registers are placed on the stack. "sp" points at the first stacked argument 50(i.e. the 5th arg). 51 52VFP: single-precision results in s0, double-precision results in d0. 53 54In the EABI, "sp" must be 64-bit aligned on entry to a function, and any 5564-bit quantities (long long, double) must be 64-bit aligned. 56*/ 57 58/* 59Mterp and ARM notes: 60 61The following registers have fixed assignments: 62 63 reg nick purpose 64 r4 rPC interpreted program counter, used for fetching instructions 65 r5 rFP interpreted frame pointer, used for accessing locals and args 66 r6 rGLUE MterpGlue pointer 67 r7 rINST first 16-bit code unit of current instruction 68 r8 rIBASE interpreted instruction base pointer, used for computed goto 69 70Macros are provided for common operations. Each macro MUST emit only 71one instruction to make instruction-counting easier. They MUST NOT alter 72unspecified registers or condition codes. 73*/ 74 75/* single-purpose registers, given names for clarity */ 76#define rPC r4 77#define rFP r5 78#define rGLUE r6 79#define rINST r7 80#define rIBASE r8 81 82/* save/restore the PC and/or FP from the glue struct */ 83#define LOAD_PC_FROM_GLUE() ldr rPC, [rGLUE, #offGlue_pc] 84#define SAVE_PC_TO_GLUE() str rPC, [rGLUE, #offGlue_pc] 85#define LOAD_FP_FROM_GLUE() ldr rFP, [rGLUE, #offGlue_fp] 86#define SAVE_FP_TO_GLUE() str rFP, [rGLUE, #offGlue_fp] 87#define LOAD_PC_FP_FROM_GLUE() ldmia rGLUE, {rPC, rFP} 88#define SAVE_PC_FP_TO_GLUE() stmia rGLUE, {rPC, rFP} 89 90/* 91 * "export" the PC to the stack frame, f/b/o future exception objects. Must 92 * be done *before* something calls dvmThrowException. 93 * 94 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e. 95 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc) 96 * 97 * It's okay to do this more than once. 98 */ 99#define EXPORT_PC() \ 100 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)] 101 102/* 103 * Given a frame pointer, find the stack save area. 104 * 105 * In C this is "((StackSaveArea*)(_fp) -1)". 106 */ 107#define SAVEAREA_FROM_FP(_reg, _fpreg) \ 108 sub _reg, _fpreg, #sizeofStackSaveArea 109 110/* 111 * Fetch the next instruction from rPC into rINST. Does not advance rPC. 112 */ 113#define FETCH_INST() ldrh rINST, [rPC] 114 115/* 116 * Fetch the next instruction from the specified offset. Advances rPC 117 * to point to the next instruction. "_count" is in 16-bit code units. 118 * 119 * Because of the limited size of immediate constants on ARM, this is only 120 * suitable for small forward movements (i.e. don't try to implement "goto" 121 * with this). 122 * 123 * This must come AFTER anything that can throw an exception, or the 124 * exception catch may miss. (This also implies that it must come after 125 * EXPORT_PC().) 126 */ 127#define FETCH_ADVANCE_INST(_count) ldrh rINST, [rPC, #(_count*2)]! 128 129/* 130 * The operation performed here is similar to FETCH_ADVANCE_INST, except the 131 * src and dest registers are parameterized (not hard-wired to rPC and rINST). 132 */ 133#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \ 134 ldrh _dreg, [_sreg, #(_count*2)]! 135 136/* 137 * Fetch the next instruction from an offset specified by _reg. Updates 138 * rPC to point to the next instruction. "_reg" must specify the distance 139 * in bytes, *not* 16-bit code units, and may be a signed value. 140 * 141 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the 142 * bits that hold the shift distance are used for the half/byte/sign flags. 143 * In some cases we can pre-double _reg for free, so we require a byte offset 144 * here. 145 */ 146#define FETCH_ADVANCE_INST_RB(_reg) ldrh rINST, [rPC, _reg]! 147 148/* 149 * Fetch a half-word code unit from an offset past the current PC. The 150 * "_count" value is in 16-bit code units. Does not advance rPC. 151 * 152 * The "_S" variant works the same but treats the value as signed. 153 */ 154#define FETCH(_reg, _count) ldrh _reg, [rPC, #(_count*2)] 155#define FETCH_S(_reg, _count) ldrsh _reg, [rPC, #(_count*2)] 156 157/* 158 * Fetch one byte from an offset past the current PC. Pass in the same 159 * "_count" as you would for FETCH, and an additional 0/1 indicating which 160 * byte of the halfword you want (lo/hi). 161 */ 162#define FETCH_B(_reg, _count, _byte) ldrb _reg, [rPC, #(_count*2+_byte)] 163 164/* 165 * Put the instruction's opcode field into the specified register. 166 */ 167#define GET_INST_OPCODE(_reg) and _reg, rINST, #255 168 169/* 170 * Put the prefetched instruction's opcode field into the specified register. 171 */ 172#define GET_PREFETCHED_OPCODE(_oreg, _ireg) and _oreg, _ireg, #255 173 174/* 175 * Begin executing the opcode in _reg. Because this only jumps within the 176 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork. 177 */ 178#define GOTO_OPCODE(_reg) add pc, rIBASE, _reg, lsl #6 179#define GOTO_OPCODE_IFEQ(_reg) addeq pc, rIBASE, _reg, lsl #6 180#define GOTO_OPCODE_IFNE(_reg) addne pc, rIBASE, _reg, lsl #6 181 182/* 183 * Get/set the 32-bit value from a Dalvik register. 184 */ 185#define GET_VREG(_reg, _vreg) ldr _reg, [rFP, _vreg, lsl #2] 186#define SET_VREG(_reg, _vreg) str _reg, [rFP, _vreg, lsl #2] 187 188#if defined(WITH_JIT) 189#define GET_JIT_PROF_TABLE(_reg) ldr _reg,[rGLUE,#offGlue_pJitProfTable] 190#define GET_JIT_THRESHOLD(_reg) ldr _reg,[rGLUE,#offGlue_jitThreshold] 191#endif 192 193/* 194 * Convert a virtual register index into an address. 195 */ 196#define VREG_INDEX_TO_ADDR(_reg, _vreg) \ 197 add _reg, rFP, _vreg, lsl #2 198 199/* 200 * This is a #include, not a %include, because we want the C pre-processor 201 * to expand the macros into assembler assignment statements. 202 */ 203#include "../common/asm-constants.h" 204 205#if defined(WITH_JIT) 206#include "../common/jit-config.h" 207#endif 208 209/* File: armv7-a/platform.S */ 210/* 211 * =========================================================================== 212 * CPU-version-specific defines 213 * =========================================================================== 214 */ 215 216/* 217 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5. Essentially a 218 * one-way branch. 219 * 220 * May modify IP. Does not modify LR. 221 */ 222.macro LDR_PC source 223 ldr pc, \source 224.endm 225 226/* 227 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5. 228 * Jump to subroutine. 229 * 230 * May modify IP and LR. 231 */ 232.macro LDR_PC_LR source 233 mov lr, pc 234 ldr pc, \source 235.endm 236 237/* 238 * Macro for "LDMFD SP!, {...regs...,PC}". 239 * 240 * May modify IP and LR. 241 */ 242.macro LDMFD_PC regs 243 ldmfd sp!, {\regs,pc} 244.endm 245 246#if !defined(ANDROID_SMP) 247# error "Must define ANDROID_SMP" 248#endif 249 250/* 251 * Macro for data memory barrier; not meaningful pre-ARMv6K. 252 * If the argument is nonzero, emit barrier; otherwise, emit nothing. 253 */ 254.macro SMP_DMB 255#if ANDROID_SMP != 0 256 dmb 257#else 258 /* not SMP */ 259#endif 260.endm 261 262/* File: armv5te/entry.S */ 263/* 264 * Copyright (C) 2008 The Android Open Source Project 265 * 266 * Licensed under the Apache License, Version 2.0 (the "License"); 267 * you may not use this file except in compliance with the License. 268 * You may obtain a copy of the License at 269 * 270 * http://www.apache.org/licenses/LICENSE-2.0 271 * 272 * Unless required by applicable law or agreed to in writing, software 273 * distributed under the License is distributed on an "AS IS" BASIS, 274 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 275 * See the License for the specific language governing permissions and 276 * limitations under the License. 277 */ 278/* 279 * Interpreter entry point. 280 */ 281 282/* 283 * We don't have formal stack frames, so gdb scans upward in the code 284 * to find the start of the function (a label with the %function type), 285 * and then looks at the next few instructions to figure out what 286 * got pushed onto the stack. From this it figures out how to restore 287 * the registers, including PC, for the previous stack frame. If gdb 288 * sees a non-function label, it stops scanning, so either we need to 289 * have nothing but assembler-local labels between the entry point and 290 * the break, or we need to fake it out. 291 * 292 * When this is defined, we add some stuff to make gdb less confused. 293 */ 294#define ASSIST_DEBUGGER 1 295 296 .text 297 .align 2 298 .global dvmMterpStdRun 299 .type dvmMterpStdRun, %function 300 301/* 302 * On entry: 303 * r0 MterpGlue* glue 304 * 305 * This function returns a boolean "changeInterp" value. The return comes 306 * via a call to dvmMterpStdBail(). 307 */ 308dvmMterpStdRun: 309#define MTERP_ENTRY1 \ 310 .save {r4-r10,fp,lr}; \ 311 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs 312#define MTERP_ENTRY2 \ 313 .pad #4; \ 314 sub sp, sp, #4 @ align 64 315 316 .fnstart 317 MTERP_ENTRY1 318 MTERP_ENTRY2 319 320 /* save stack pointer, add magic word for debuggerd */ 321 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return 322 323 /* set up "named" registers, figure out entry point */ 324 mov rGLUE, r0 @ set rGLUE 325 ldr r1, [r0, #offGlue_entryPoint] @ enum is 4 bytes in aapcs-EABI 326 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue" 327 adr rIBASE, dvmAsmInstructionStart @ set rIBASE 328 cmp r1, #kInterpEntryInstr @ usual case? 329 bne .Lnot_instr @ no, handle it 330 331#if defined(WITH_JIT) 332.LentryInstr: 333 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 334 /* Entry is always a possible trace start */ 335 GET_JIT_PROF_TABLE(r0) 336 FETCH_INST() 337 mov r1, #0 @ prepare the value for the new state 338 str r1, [r10, #offThread_inJitCodeCache] @ back to the interp land 339 cmp r0,#0 340 bne common_updateProfile 341 GET_INST_OPCODE(ip) 342 GOTO_OPCODE(ip) 343#else 344 /* start executing the instruction at rPC */ 345 FETCH_INST() @ load rINST from rPC 346 GET_INST_OPCODE(ip) @ extract opcode from rINST 347 GOTO_OPCODE(ip) @ jump to next instruction 348#endif 349 350.Lnot_instr: 351 cmp r1, #kInterpEntryReturn @ were we returning from a method? 352 beq common_returnFromMethod 353 354.Lnot_return: 355 cmp r1, #kInterpEntryThrow @ were we throwing an exception? 356 beq common_exceptionThrown 357 358#if defined(WITH_JIT) 359.Lnot_throw: 360 ldr r10,[rGLUE, #offGlue_jitResumeNPC] 361 ldr r2,[rGLUE, #offGlue_jitResumeDPC] 362 cmp r1, #kInterpEntryResume @ resuming after Jit single-step? 363 bne .Lbad_arg 364 cmp rPC,r2 365 bne .LentryInstr @ must have branched, don't resume 366#if defined(WITH_SELF_VERIFICATION) 367 @ glue->entryPoint will be set in dvmSelfVerificationSaveState 368 b jitSVShadowRunStart @ re-enter the translation after the 369 @ single-stepped instruction 370 @noreturn 371#endif 372 mov r1, #kInterpEntryInstr 373 str r1, [rGLUE, #offGlue_entryPoint] 374 bx r10 @ re-enter the translation 375#endif 376 377.Lbad_arg: 378 ldr r0, strBadEntryPoint 379 @ r1 holds value of entryPoint 380 bl printf 381 bl dvmAbort 382 .fnend 383 384 385 .global dvmMterpStdBail 386 .type dvmMterpStdBail, %function 387 388/* 389 * Restore the stack pointer and PC from the save point established on entry. 390 * This is essentially the same as a longjmp, but should be cheaper. The 391 * last instruction causes us to return to whoever called dvmMterpStdRun. 392 * 393 * We pushed some registers on the stack in dvmMterpStdRun, then saved 394 * SP and LR. Here we restore SP, restore the registers, and then restore 395 * LR to PC. 396 * 397 * On entry: 398 * r0 MterpGlue* glue 399 * r1 bool changeInterp 400 */ 401dvmMterpStdBail: 402 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 403 mov r0, r1 @ return the changeInterp value 404 add sp, sp, #4 @ un-align 64 405 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return 406 407 408/* 409 * String references. 410 */ 411strBadEntryPoint: 412 .word .LstrBadEntryPoint 413 414 415 .global dvmAsmInstructionStart 416 .type dvmAsmInstructionStart, %function 417dvmAsmInstructionStart = .L_OP_NOP 418 .text 419 420/* ------------------------------ */ 421 .balign 64 422.L_OP_NOP: /* 0x00 */ 423/* File: armv5te/OP_NOP.S */ 424 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST 425 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 426 GOTO_OPCODE(ip) @ execute it 427 428#ifdef ASSIST_DEBUGGER 429 /* insert fake function header to help gdb find the stack frame */ 430 .type dalvik_inst, %function 431dalvik_inst: 432 .fnstart 433 MTERP_ENTRY1 434 MTERP_ENTRY2 435 .fnend 436#endif 437 438/* ------------------------------ */ 439 .balign 64 440.L_OP_MOVE: /* 0x01 */ 441/* File: armv6t2/OP_MOVE.S */ 442 /* for move, move-object, long-to-int */ 443 /* op vA, vB */ 444 mov r1, rINST, lsr #12 @ r1<- B from 15:12 445 ubfx r0, rINST, #8, #4 @ r0<- A from 11:8 446 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 447 GET_VREG(r2, r1) @ r2<- fp[B] 448 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 449 SET_VREG(r2, r0) @ fp[A]<- r2 450 GOTO_OPCODE(ip) @ execute next instruction 451 452/* ------------------------------ */ 453 .balign 64 454.L_OP_MOVE_FROM16: /* 0x02 */ 455/* File: armv5te/OP_MOVE_FROM16.S */ 456 /* for: move/from16, move-object/from16 */ 457 /* op vAA, vBBBB */ 458 FETCH(r1, 1) @ r1<- BBBB 459 mov r0, rINST, lsr #8 @ r0<- AA 460 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 461 GET_VREG(r2, r1) @ r2<- fp[BBBB] 462 GET_INST_OPCODE(ip) @ extract opcode from rINST 463 SET_VREG(r2, r0) @ fp[AA]<- r2 464 GOTO_OPCODE(ip) @ jump to next instruction 465 466/* ------------------------------ */ 467 .balign 64 468.L_OP_MOVE_16: /* 0x03 */ 469/* File: armv5te/OP_MOVE_16.S */ 470 /* for: move/16, move-object/16 */ 471 /* op vAAAA, vBBBB */ 472 FETCH(r1, 2) @ r1<- BBBB 473 FETCH(r0, 1) @ r0<- AAAA 474 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 475 GET_VREG(r2, r1) @ r2<- fp[BBBB] 476 GET_INST_OPCODE(ip) @ extract opcode from rINST 477 SET_VREG(r2, r0) @ fp[AAAA]<- r2 478 GOTO_OPCODE(ip) @ jump to next instruction 479 480/* ------------------------------ */ 481 .balign 64 482.L_OP_MOVE_WIDE: /* 0x04 */ 483/* File: armv6t2/OP_MOVE_WIDE.S */ 484 /* move-wide vA, vB */ 485 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 486 mov r3, rINST, lsr #12 @ r3<- B 487 ubfx r2, rINST, #8, #4 @ r2<- A 488 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 489 add r2, rFP, r2, lsl #2 @ r2<- &fp[A] 490 ldmia r3, {r0-r1} @ r0/r1<- fp[B] 491 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 492 GET_INST_OPCODE(ip) @ extract opcode from rINST 493 stmia r2, {r0-r1} @ fp[A]<- r0/r1 494 GOTO_OPCODE(ip) @ jump to next instruction 495 496/* ------------------------------ */ 497 .balign 64 498.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 499/* File: armv5te/OP_MOVE_WIDE_FROM16.S */ 500 /* move-wide/from16 vAA, vBBBB */ 501 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 502 FETCH(r3, 1) @ r3<- BBBB 503 mov r2, rINST, lsr #8 @ r2<- AA 504 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 505 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 506 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 507 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 508 GET_INST_OPCODE(ip) @ extract opcode from rINST 509 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 510 GOTO_OPCODE(ip) @ jump to next instruction 511 512/* ------------------------------ */ 513 .balign 64 514.L_OP_MOVE_WIDE_16: /* 0x06 */ 515/* File: armv5te/OP_MOVE_WIDE_16.S */ 516 /* move-wide/16 vAAAA, vBBBB */ 517 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 518 FETCH(r3, 2) @ r3<- BBBB 519 FETCH(r2, 1) @ r2<- AAAA 520 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 521 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA] 522 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 523 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 524 GET_INST_OPCODE(ip) @ extract opcode from rINST 525 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1 526 GOTO_OPCODE(ip) @ jump to next instruction 527 528/* ------------------------------ */ 529 .balign 64 530.L_OP_MOVE_OBJECT: /* 0x07 */ 531/* File: armv5te/OP_MOVE_OBJECT.S */ 532/* File: armv5te/OP_MOVE.S */ 533 /* for move, move-object, long-to-int */ 534 /* op vA, vB */ 535 mov r1, rINST, lsr #12 @ r1<- B from 15:12 536 mov r0, rINST, lsr #8 @ r0<- A from 11:8 537 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 538 GET_VREG(r2, r1) @ r2<- fp[B] 539 and r0, r0, #15 540 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 541 SET_VREG(r2, r0) @ fp[A]<- r2 542 GOTO_OPCODE(ip) @ execute next instruction 543 544 545/* ------------------------------ */ 546 .balign 64 547.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 548/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */ 549/* File: armv5te/OP_MOVE_FROM16.S */ 550 /* for: move/from16, move-object/from16 */ 551 /* op vAA, vBBBB */ 552 FETCH(r1, 1) @ r1<- BBBB 553 mov r0, rINST, lsr #8 @ r0<- AA 554 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 555 GET_VREG(r2, r1) @ r2<- fp[BBBB] 556 GET_INST_OPCODE(ip) @ extract opcode from rINST 557 SET_VREG(r2, r0) @ fp[AA]<- r2 558 GOTO_OPCODE(ip) @ jump to next instruction 559 560 561/* ------------------------------ */ 562 .balign 64 563.L_OP_MOVE_OBJECT_16: /* 0x09 */ 564/* File: armv5te/OP_MOVE_OBJECT_16.S */ 565/* File: armv5te/OP_MOVE_16.S */ 566 /* for: move/16, move-object/16 */ 567 /* op vAAAA, vBBBB */ 568 FETCH(r1, 2) @ r1<- BBBB 569 FETCH(r0, 1) @ r0<- AAAA 570 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 571 GET_VREG(r2, r1) @ r2<- fp[BBBB] 572 GET_INST_OPCODE(ip) @ extract opcode from rINST 573 SET_VREG(r2, r0) @ fp[AAAA]<- r2 574 GOTO_OPCODE(ip) @ jump to next instruction 575 576 577/* ------------------------------ */ 578 .balign 64 579.L_OP_MOVE_RESULT: /* 0x0a */ 580/* File: armv5te/OP_MOVE_RESULT.S */ 581 /* for: move-result, move-result-object */ 582 /* op vAA */ 583 mov r2, rINST, lsr #8 @ r2<- AA 584 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 585 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 586 GET_INST_OPCODE(ip) @ extract opcode from rINST 587 SET_VREG(r0, r2) @ fp[AA]<- r0 588 GOTO_OPCODE(ip) @ jump to next instruction 589 590/* ------------------------------ */ 591 .balign 64 592.L_OP_MOVE_RESULT_WIDE: /* 0x0b */ 593/* File: armv5te/OP_MOVE_RESULT_WIDE.S */ 594 /* move-result-wide vAA */ 595 mov r2, rINST, lsr #8 @ r2<- AA 596 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 597 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 598 ldmia r3, {r0-r1} @ r0/r1<- retval.j 599 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 600 GET_INST_OPCODE(ip) @ extract opcode from rINST 601 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 602 GOTO_OPCODE(ip) @ jump to next instruction 603 604/* ------------------------------ */ 605 .balign 64 606.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 607/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */ 608/* File: armv5te/OP_MOVE_RESULT.S */ 609 /* for: move-result, move-result-object */ 610 /* op vAA */ 611 mov r2, rINST, lsr #8 @ r2<- AA 612 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 613 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 614 GET_INST_OPCODE(ip) @ extract opcode from rINST 615 SET_VREG(r0, r2) @ fp[AA]<- r0 616 GOTO_OPCODE(ip) @ jump to next instruction 617 618 619/* ------------------------------ */ 620 .balign 64 621.L_OP_MOVE_EXCEPTION: /* 0x0d */ 622/* File: armv5te/OP_MOVE_EXCEPTION.S */ 623 /* move-exception vAA */ 624 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 625 mov r2, rINST, lsr #8 @ r2<- AA 626 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass 627 mov r1, #0 @ r1<- 0 628 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 629 SET_VREG(r3, r2) @ fp[AA]<- exception obj 630 GET_INST_OPCODE(ip) @ extract opcode from rINST 631 str r1, [r0, #offThread_exception] @ dvmClearException bypass 632 GOTO_OPCODE(ip) @ jump to next instruction 633 634/* ------------------------------ */ 635 .balign 64 636.L_OP_RETURN_VOID: /* 0x0e */ 637/* File: armv5te/OP_RETURN_VOID.S */ 638 b common_returnFromMethod 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 .balign 64 658.L_OP_RETURN_WIDE: /* 0x10 */ 659/* File: armv5te/OP_RETURN_WIDE.S */ 660 /* 661 * Return a 64-bit value. Copies the return value into the "glue" 662 * structure, then jumps to the return handler. 663 */ 664 /* return-wide vAA */ 665 mov r2, rINST, lsr #8 @ r2<- AA 666 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 667 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 668 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1 669 stmia r3, {r0-r1} @ retval<- r0/r1 670 b common_returnFromMethod 671 672/* ------------------------------ */ 673 .balign 64 674.L_OP_RETURN_OBJECT: /* 0x11 */ 675/* File: armv5te/OP_RETURN_OBJECT.S */ 676/* File: armv5te/OP_RETURN.S */ 677 /* 678 * Return a 32-bit value. Copies the return value into the "glue" 679 * structure, then jumps to the return handler. 680 * 681 * for: return, return-object 682 */ 683 /* op vAA */ 684 mov r2, rINST, lsr #8 @ r2<- AA 685 GET_VREG(r0, r2) @ r0<- vAA 686 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 687 b common_returnFromMethod 688 689 690/* ------------------------------ */ 691 .balign 64 692.L_OP_CONST_4: /* 0x12 */ 693/* File: armv6t2/OP_CONST_4.S */ 694 /* const/4 vA, #+B */ 695 mov r1, rINST, lsl #16 @ r1<- Bxxx0000 696 ubfx r0, rINST, #8, #4 @ r0<- A 697 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 698 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended) 699 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 700 SET_VREG(r1, r0) @ fp[A]<- r1 701 GOTO_OPCODE(ip) @ execute next instruction 702 703/* ------------------------------ */ 704 .balign 64 705.L_OP_CONST_16: /* 0x13 */ 706/* File: armv5te/OP_CONST_16.S */ 707 /* const/16 vAA, #+BBBB */ 708 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 709 mov r3, rINST, lsr #8 @ r3<- AA 710 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 711 SET_VREG(r0, r3) @ vAA<- r0 712 GET_INST_OPCODE(ip) @ extract opcode from rINST 713 GOTO_OPCODE(ip) @ jump to next instruction 714 715/* ------------------------------ */ 716 .balign 64 717.L_OP_CONST: /* 0x14 */ 718/* File: armv5te/OP_CONST.S */ 719 /* const vAA, #+BBBBbbbb */ 720 mov r3, rINST, lsr #8 @ r3<- AA 721 FETCH(r0, 1) @ r0<- bbbb (low) 722 FETCH(r1, 2) @ r1<- BBBB (high) 723 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 724 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 725 GET_INST_OPCODE(ip) @ extract opcode from rINST 726 SET_VREG(r0, r3) @ vAA<- r0 727 GOTO_OPCODE(ip) @ jump to next instruction 728 729/* ------------------------------ */ 730 .balign 64 731.L_OP_CONST_HIGH16: /* 0x15 */ 732/* File: armv5te/OP_CONST_HIGH16.S */ 733 /* const/high16 vAA, #+BBBB0000 */ 734 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended) 735 mov r3, rINST, lsr #8 @ r3<- AA 736 mov r0, r0, lsl #16 @ r0<- BBBB0000 737 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 738 SET_VREG(r0, r3) @ vAA<- r0 739 GET_INST_OPCODE(ip) @ extract opcode from rINST 740 GOTO_OPCODE(ip) @ jump to next instruction 741 742/* ------------------------------ */ 743 .balign 64 744.L_OP_CONST_WIDE_16: /* 0x16 */ 745/* File: armv5te/OP_CONST_WIDE_16.S */ 746 /* const-wide/16 vAA, #+BBBB */ 747 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 748 mov r3, rINST, lsr #8 @ r3<- AA 749 mov r1, r0, asr #31 @ r1<- ssssssss 750 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 751 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 752 GET_INST_OPCODE(ip) @ extract opcode from rINST 753 stmia r3, {r0-r1} @ vAA<- r0/r1 754 GOTO_OPCODE(ip) @ jump to next instruction 755 756/* ------------------------------ */ 757 .balign 64 758.L_OP_CONST_WIDE_32: /* 0x17 */ 759/* File: armv5te/OP_CONST_WIDE_32.S */ 760 /* const-wide/32 vAA, #+BBBBbbbb */ 761 FETCH(r0, 1) @ r0<- 0000bbbb (low) 762 mov r3, rINST, lsr #8 @ r3<- AA 763 FETCH_S(r2, 2) @ r2<- ssssBBBB (high) 764 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 765 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb 766 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 767 mov r1, r0, asr #31 @ r1<- ssssssss 768 GET_INST_OPCODE(ip) @ extract opcode from rINST 769 stmia r3, {r0-r1} @ vAA<- r0/r1 770 GOTO_OPCODE(ip) @ jump to next instruction 771 772/* ------------------------------ */ 773 .balign 64 774.L_OP_CONST_WIDE: /* 0x18 */ 775/* File: armv5te/OP_CONST_WIDE.S */ 776 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 777 FETCH(r0, 1) @ r0<- bbbb (low) 778 FETCH(r1, 2) @ r1<- BBBB (low middle) 779 FETCH(r2, 3) @ r2<- hhhh (high middle) 780 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word) 781 FETCH(r3, 4) @ r3<- HHHH (high) 782 mov r9, rINST, lsr #8 @ r9<- AA 783 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word) 784 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 785 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 786 GET_INST_OPCODE(ip) @ extract opcode from rINST 787 stmia r9, {r0-r1} @ vAA<- r0/r1 788 GOTO_OPCODE(ip) @ jump to next instruction 789 790/* ------------------------------ */ 791 .balign 64 792.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 793/* File: armv5te/OP_CONST_WIDE_HIGH16.S */ 794 /* const-wide/high16 vAA, #+BBBB000000000000 */ 795 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended) 796 mov r3, rINST, lsr #8 @ r3<- AA 797 mov r0, #0 @ r0<- 00000000 798 mov r1, r1, lsl #16 @ r1<- BBBB0000 799 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 800 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 801 GET_INST_OPCODE(ip) @ extract opcode from rINST 802 stmia r3, {r0-r1} @ vAA<- r0/r1 803 GOTO_OPCODE(ip) @ jump to next instruction 804 805/* ------------------------------ */ 806 .balign 64 807.L_OP_CONST_STRING: /* 0x1a */ 808/* File: armv5te/OP_CONST_STRING.S */ 809 /* const/string vAA, String@BBBB */ 810 FETCH(r1, 1) @ r1<- BBBB 811 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 812 mov r9, rINST, lsr #8 @ r9<- AA 813 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 814 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 815 cmp r0, #0 @ not yet resolved? 816 beq .LOP_CONST_STRING_resolve 817 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 818 GET_INST_OPCODE(ip) @ extract opcode from rINST 819 SET_VREG(r0, r9) @ vAA<- r0 820 GOTO_OPCODE(ip) @ jump to next instruction 821 822/* ------------------------------ */ 823 .balign 64 824.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 825/* File: armv5te/OP_CONST_STRING_JUMBO.S */ 826 /* const/string vAA, String@BBBBBBBB */ 827 FETCH(r0, 1) @ r0<- bbbb (low) 828 FETCH(r1, 2) @ r1<- BBBB (high) 829 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 830 mov r9, rINST, lsr #8 @ r9<- AA 831 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 832 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 833 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 834 cmp r0, #0 835 beq .LOP_CONST_STRING_JUMBO_resolve 836 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 837 GET_INST_OPCODE(ip) @ extract opcode from rINST 838 SET_VREG(r0, r9) @ vAA<- r0 839 GOTO_OPCODE(ip) @ jump to next instruction 840 841/* ------------------------------ */ 842 .balign 64 843.L_OP_CONST_CLASS: /* 0x1c */ 844/* File: armv5te/OP_CONST_CLASS.S */ 845 /* const/class vAA, Class@BBBB */ 846 FETCH(r1, 1) @ r1<- BBBB 847 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 848 mov r9, rINST, lsr #8 @ r9<- AA 849 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 850 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB] 851 cmp r0, #0 @ not yet resolved? 852 beq .LOP_CONST_CLASS_resolve 853 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 854 GET_INST_OPCODE(ip) @ extract opcode from rINST 855 SET_VREG(r0, r9) @ vAA<- r0 856 GOTO_OPCODE(ip) @ jump to next instruction 857 858/* ------------------------------ */ 859 .balign 64 860.L_OP_MONITOR_ENTER: /* 0x1d */ 861/* File: armv5te/OP_MONITOR_ENTER.S */ 862 /* 863 * Synchronize on an object. 864 */ 865 /* monitor-enter vAA */ 866 mov r2, rINST, lsr #8 @ r2<- AA 867 GET_VREG(r1, r2) @ r1<- vAA (object) 868 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 869 cmp r1, #0 @ null object? 870 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING 871 beq common_errNullObject @ null object, throw an exception 872 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 873 bl dvmLockObject @ call(self, obj) 874#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ 875 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 876 ldr r1, [r0, #offThread_exception] @ check for exception 877 cmp r1, #0 878 bne common_exceptionThrown @ exception raised, bail out 879#endif 880 GET_INST_OPCODE(ip) @ extract opcode from rINST 881 GOTO_OPCODE(ip) @ jump to next instruction 882 883/* ------------------------------ */ 884 .balign 64 885.L_OP_MONITOR_EXIT: /* 0x1e */ 886/* File: armv5te/OP_MONITOR_EXIT.S */ 887 /* 888 * Unlock an object. 889 * 890 * Exceptions that occur when unlocking a monitor need to appear as 891 * if they happened at the following instruction. See the Dalvik 892 * instruction spec. 893 */ 894 /* monitor-exit vAA */ 895 mov r2, rINST, lsr #8 @ r2<- AA 896 EXPORT_PC() @ before fetch: export the PC 897 GET_VREG(r1, r2) @ r1<- vAA (object) 898 cmp r1, #0 @ null object? 899 beq 1f @ yes 900 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 901 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 902 cmp r0, #0 @ failed? 903 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 904 beq common_exceptionThrown @ yes, exception is pending 905 GET_INST_OPCODE(ip) @ extract opcode from rINST 906 GOTO_OPCODE(ip) @ jump to next instruction 9071: 908 FETCH_ADVANCE_INST(1) @ advance before throw 909 b common_errNullObject 910 911/* ------------------------------ */ 912 .balign 64 913.L_OP_CHECK_CAST: /* 0x1f */ 914/* File: armv5te/OP_CHECK_CAST.S */ 915 /* 916 * Check to see if a cast from one class to another is allowed. 917 */ 918 /* check-cast vAA, class@BBBB */ 919 mov r3, rINST, lsr #8 @ r3<- AA 920 FETCH(r2, 1) @ r2<- BBBB 921 GET_VREG(r9, r3) @ r9<- object 922 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 923 cmp r9, #0 @ is object null? 924 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 925 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 926 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 927 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 928 cmp r1, #0 @ have we resolved this before? 929 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 930.LOP_CHECK_CAST_resolved: 931 cmp r0, r1 @ same class (trivial success)? 932 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 933.LOP_CHECK_CAST_okay: 934 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 935 GET_INST_OPCODE(ip) @ extract opcode from rINST 936 GOTO_OPCODE(ip) @ jump to next instruction 937 938/* ------------------------------ */ 939 .balign 64 940.L_OP_INSTANCE_OF: /* 0x20 */ 941/* File: armv5te/OP_INSTANCE_OF.S */ 942 /* 943 * Check to see if an object reference is an instance of a class. 944 * 945 * Most common situation is a non-null object, being compared against 946 * an already-resolved class. 947 */ 948 /* instance-of vA, vB, class@CCCC */ 949 mov r3, rINST, lsr #12 @ r3<- B 950 mov r9, rINST, lsr #8 @ r9<- A+ 951 GET_VREG(r0, r3) @ r0<- vB (object) 952 and r9, r9, #15 @ r9<- A 953 cmp r0, #0 @ is object null? 954 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 955 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 956 FETCH(r3, 1) @ r3<- CCCC 957 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 958 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 959 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 960 cmp r1, #0 @ have we resolved this before? 961 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 962.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 963 cmp r0, r1 @ same class (trivial success)? 964 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 965 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 966 967/* ------------------------------ */ 968 .balign 64 969.L_OP_ARRAY_LENGTH: /* 0x21 */ 970/* File: armv6t2/OP_ARRAY_LENGTH.S */ 971 /* 972 * Return the length of an array. 973 */ 974 mov r1, rINST, lsr #12 @ r1<- B 975 ubfx r2, rINST, #8, #4 @ r2<- A 976 GET_VREG(r0, r1) @ r0<- vB (object ref) 977 cmp r0, #0 @ is object null? 978 beq common_errNullObject @ yup, fail 979 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 980 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 981 GET_INST_OPCODE(ip) @ extract opcode from rINST 982 SET_VREG(r3, r2) @ vB<- length 983 GOTO_OPCODE(ip) @ jump to next instruction 984 985/* ------------------------------ */ 986 .balign 64 987.L_OP_NEW_INSTANCE: /* 0x22 */ 988/* File: armv5te/OP_NEW_INSTANCE.S */ 989 /* 990 * Create a new instance of a class. 991 */ 992 /* new-instance vAA, class@BBBB */ 993 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 994 FETCH(r1, 1) @ r1<- BBBB 995 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 996 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 997 EXPORT_PC() @ req'd for init, resolve, alloc 998 cmp r0, #0 @ already resolved? 999 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 1000.LOP_NEW_INSTANCE_resolved: @ r0=class 1001 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 1002 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 1003 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 1004.LOP_NEW_INSTANCE_initialized: @ r0=class 1005 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 1006 bl dvmAllocObject @ r0<- new object 1007 b .LOP_NEW_INSTANCE_finish @ continue 1008 1009/* ------------------------------ */ 1010 .balign 64 1011.L_OP_NEW_ARRAY: /* 0x23 */ 1012/* File: armv5te/OP_NEW_ARRAY.S */ 1013 /* 1014 * Allocate an array of objects, specified with the array class 1015 * and a count. 1016 * 1017 * The verifier guarantees that this is an array class, so we don't 1018 * check for it here. 1019 */ 1020 /* new-array vA, vB, class@CCCC */ 1021 mov r0, rINST, lsr #12 @ r0<- B 1022 FETCH(r2, 1) @ r2<- CCCC 1023 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1024 GET_VREG(r1, r0) @ r1<- vB (array length) 1025 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1026 cmp r1, #0 @ check length 1027 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 1028 bmi common_errNegativeArraySize @ negative length, bail 1029 cmp r0, #0 @ already resolved? 1030 EXPORT_PC() @ req'd for resolve, alloc 1031 bne .LOP_NEW_ARRAY_finish @ resolved, continue 1032 b .LOP_NEW_ARRAY_resolve @ do resolve now 1033 1034/* ------------------------------ */ 1035 .balign 64 1036.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1037/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1038 /* 1039 * Create a new array with elements filled from registers. 1040 * 1041 * for: filled-new-array, filled-new-array/range 1042 */ 1043 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1044 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1045 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1046 FETCH(r1, 1) @ r1<- BBBB 1047 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1048 EXPORT_PC() @ need for resolve and alloc 1049 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1050 mov r10, rINST, lsr #8 @ r10<- AA or BA 1051 cmp r0, #0 @ already resolved? 1052 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10538: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1054 mov r2, #0 @ r2<- false 1055 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1056 bl dvmResolveClass @ r0<- call(clazz, ref) 1057 cmp r0, #0 @ got null? 1058 beq common_exceptionThrown @ yes, handle exception 1059 b .LOP_FILLED_NEW_ARRAY_continue 1060 1061/* ------------------------------ */ 1062 .balign 64 1063.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1064/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1065/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1066 /* 1067 * Create a new array with elements filled from registers. 1068 * 1069 * for: filled-new-array, filled-new-array/range 1070 */ 1071 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1072 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1073 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1074 FETCH(r1, 1) @ r1<- BBBB 1075 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1076 EXPORT_PC() @ need for resolve and alloc 1077 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1078 mov r10, rINST, lsr #8 @ r10<- AA or BA 1079 cmp r0, #0 @ already resolved? 1080 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10818: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1082 mov r2, #0 @ r2<- false 1083 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1084 bl dvmResolveClass @ r0<- call(clazz, ref) 1085 cmp r0, #0 @ got null? 1086 beq common_exceptionThrown @ yes, handle exception 1087 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1088 1089 1090/* ------------------------------ */ 1091 .balign 64 1092.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1093/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1094 /* fill-array-data vAA, +BBBBBBBB */ 1095 FETCH(r0, 1) @ r0<- bbbb (lo) 1096 FETCH(r1, 2) @ r1<- BBBB (hi) 1097 mov r3, rINST, lsr #8 @ r3<- AA 1098 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1099 GET_VREG(r0, r3) @ r0<- vAA (array object) 1100 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1101 EXPORT_PC(); 1102 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1103 cmp r0, #0 @ 0 means an exception is thrown 1104 beq common_exceptionThrown @ has exception 1105 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1106 GET_INST_OPCODE(ip) @ extract opcode from rINST 1107 GOTO_OPCODE(ip) @ jump to next instruction 1108 1109/* ------------------------------ */ 1110 .balign 64 1111.L_OP_THROW: /* 0x27 */ 1112/* File: armv5te/OP_THROW.S */ 1113 /* 1114 * Throw an exception object in the current thread. 1115 */ 1116 /* throw vAA */ 1117 mov r2, rINST, lsr #8 @ r2<- AA 1118 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1119 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1120 EXPORT_PC() @ exception handler can throw 1121 cmp r1, #0 @ null object? 1122 beq common_errNullObject @ yes, throw an NPE instead 1123 @ bypass dvmSetException, just store it 1124 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1125 b common_exceptionThrown 1126 1127/* ------------------------------ */ 1128 .balign 64 1129.L_OP_GOTO: /* 0x28 */ 1130/* File: armv5te/OP_GOTO.S */ 1131 /* 1132 * Unconditional branch, 8-bit offset. 1133 * 1134 * The branch distance is a signed code-unit offset, which we need to 1135 * double to get a byte offset. 1136 */ 1137 /* goto +AA */ 1138 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1139 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1140 mov r9, r9, lsl #1 @ r9<- byte offset 1141 bmi common_backwardBranch @ backward branch, do periodic checks 1142#if defined(WITH_JIT) 1143 GET_JIT_PROF_TABLE(r0) 1144 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1145 cmp r0,#0 1146 bne common_updateProfile 1147 GET_INST_OPCODE(ip) @ extract opcode from rINST 1148 GOTO_OPCODE(ip) @ jump to next instruction 1149#else 1150 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1151 GET_INST_OPCODE(ip) @ extract opcode from rINST 1152 GOTO_OPCODE(ip) @ jump to next instruction 1153#endif 1154 1155/* ------------------------------ */ 1156 .balign 64 1157.L_OP_GOTO_16: /* 0x29 */ 1158/* File: armv5te/OP_GOTO_16.S */ 1159 /* 1160 * Unconditional branch, 16-bit offset. 1161 * 1162 * The branch distance is a signed code-unit offset, which we need to 1163 * double to get a byte offset. 1164 */ 1165 /* goto/16 +AAAA */ 1166 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1167 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1168 bmi common_backwardBranch @ backward branch, do periodic checks 1169#if defined(WITH_JIT) 1170 GET_JIT_PROF_TABLE(r0) 1171 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1172 cmp r0,#0 1173 bne common_updateProfile 1174 GET_INST_OPCODE(ip) @ extract opcode from rINST 1175 GOTO_OPCODE(ip) @ jump to next instruction 1176#else 1177 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1178 GET_INST_OPCODE(ip) @ extract opcode from rINST 1179 GOTO_OPCODE(ip) @ jump to next instruction 1180#endif 1181 1182/* ------------------------------ */ 1183 .balign 64 1184.L_OP_GOTO_32: /* 0x2a */ 1185/* File: armv5te/OP_GOTO_32.S */ 1186 /* 1187 * Unconditional branch, 32-bit offset. 1188 * 1189 * The branch distance is a signed code-unit offset, which we need to 1190 * double to get a byte offset. 1191 * 1192 * Unlike most opcodes, this one is allowed to branch to itself, so 1193 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1194 * instruction doesn't affect the V flag, so we need to clear it 1195 * explicitly. 1196 */ 1197 /* goto/32 +AAAAAAAA */ 1198 FETCH(r0, 1) @ r0<- aaaa (lo) 1199 FETCH(r1, 2) @ r1<- AAAA (hi) 1200 cmp ip, ip @ (clear V flag during stall) 1201 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1202 mov r9, r0, asl #1 @ r9<- byte offset 1203 ble common_backwardBranch @ backward branch, do periodic checks 1204#if defined(WITH_JIT) 1205 GET_JIT_PROF_TABLE(r0) 1206 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1207 cmp r0,#0 1208 bne common_updateProfile 1209 GET_INST_OPCODE(ip) @ extract opcode from rINST 1210 GOTO_OPCODE(ip) @ jump to next instruction 1211#else 1212 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1213 GET_INST_OPCODE(ip) @ extract opcode from rINST 1214 GOTO_OPCODE(ip) @ jump to next instruction 1215#endif 1216 1217/* ------------------------------ */ 1218 .balign 64 1219.L_OP_PACKED_SWITCH: /* 0x2b */ 1220/* File: armv5te/OP_PACKED_SWITCH.S */ 1221 /* 1222 * Handle a packed-switch or sparse-switch instruction. In both cases 1223 * we decode it and hand it off to a helper function. 1224 * 1225 * We don't really expect backward branches in a switch statement, but 1226 * they're perfectly legal, so we check for them here. 1227 * 1228 * for: packed-switch, sparse-switch 1229 */ 1230 /* op vAA, +BBBB */ 1231 FETCH(r0, 1) @ r0<- bbbb (lo) 1232 FETCH(r1, 2) @ r1<- BBBB (hi) 1233 mov r3, rINST, lsr #8 @ r3<- AA 1234 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1235 GET_VREG(r1, r3) @ r1<- vAA 1236 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1237 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1238 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1239 bmi common_backwardBranch @ backward branch, do periodic checks 1240 beq common_backwardBranch @ (want to use BLE but V is unknown) 1241#if defined(WITH_JIT) 1242 GET_JIT_PROF_TABLE(r0) 1243 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1244 cmp r0,#0 1245 bne common_updateProfile 1246 GET_INST_OPCODE(ip) @ extract opcode from rINST 1247 GOTO_OPCODE(ip) @ jump to next instruction 1248#else 1249 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1250 GET_INST_OPCODE(ip) @ extract opcode from rINST 1251 GOTO_OPCODE(ip) @ jump to next instruction 1252#endif 1253 1254/* ------------------------------ */ 1255 .balign 64 1256.L_OP_SPARSE_SWITCH: /* 0x2c */ 1257/* File: armv5te/OP_SPARSE_SWITCH.S */ 1258/* File: armv5te/OP_PACKED_SWITCH.S */ 1259 /* 1260 * Handle a packed-switch or sparse-switch instruction. In both cases 1261 * we decode it and hand it off to a helper function. 1262 * 1263 * We don't really expect backward branches in a switch statement, but 1264 * they're perfectly legal, so we check for them here. 1265 * 1266 * for: packed-switch, sparse-switch 1267 */ 1268 /* op vAA, +BBBB */ 1269 FETCH(r0, 1) @ r0<- bbbb (lo) 1270 FETCH(r1, 2) @ r1<- BBBB (hi) 1271 mov r3, rINST, lsr #8 @ r3<- AA 1272 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1273 GET_VREG(r1, r3) @ r1<- vAA 1274 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1275 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1276 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1277 bmi common_backwardBranch @ backward branch, do periodic checks 1278 beq common_backwardBranch @ (want to use BLE but V is unknown) 1279#if defined(WITH_JIT) 1280 GET_JIT_PROF_TABLE(r0) 1281 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1282 cmp r0,#0 1283 bne common_updateProfile 1284 GET_INST_OPCODE(ip) @ extract opcode from rINST 1285 GOTO_OPCODE(ip) @ jump to next instruction 1286#else 1287 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1288 GET_INST_OPCODE(ip) @ extract opcode from rINST 1289 GOTO_OPCODE(ip) @ jump to next instruction 1290#endif 1291 1292 1293/* ------------------------------ */ 1294 .balign 64 1295.L_OP_CMPL_FLOAT: /* 0x2d */ 1296/* File: arm-vfp/OP_CMPL_FLOAT.S */ 1297 /* 1298 * Compare two floating-point values. Puts 0, 1, or -1 into the 1299 * destination register based on the results of the comparison. 1300 * 1301 * int compare(x, y) { 1302 * if (x == y) { 1303 * return 0; 1304 * } else if (x > y) { 1305 * return 1; 1306 * } else if (x < y) { 1307 * return -1; 1308 * } else { 1309 * return -1; 1310 * } 1311 * } 1312 */ 1313 /* op vAA, vBB, vCC */ 1314 FETCH(r0, 1) @ r0<- CCBB 1315 mov r9, rINST, lsr #8 @ r9<- AA 1316 and r2, r0, #255 @ r2<- BB 1317 mov r3, r0, lsr #8 @ r3<- CC 1318 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1319 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1320 flds s0, [r2] @ s0<- vBB 1321 flds s1, [r3] @ s1<- vCC 1322 fcmpes s0, s1 @ compare (vBB, vCC) 1323 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1324 mvn r0, #0 @ r0<- -1 (default) 1325 GET_INST_OPCODE(ip) @ extract opcode from rINST 1326 fmstat @ export status flags 1327 movgt r0, #1 @ (greater than) r1<- 1 1328 moveq r0, #0 @ (equal) r1<- 0 1329 b .LOP_CMPL_FLOAT_finish @ argh 1330 1331 1332/* ------------------------------ */ 1333 .balign 64 1334.L_OP_CMPG_FLOAT: /* 0x2e */ 1335/* File: arm-vfp/OP_CMPG_FLOAT.S */ 1336 /* 1337 * Compare two floating-point values. Puts 0, 1, or -1 into the 1338 * destination register based on the results of the comparison. 1339 * 1340 * int compare(x, y) { 1341 * if (x == y) { 1342 * return 0; 1343 * } else if (x < y) { 1344 * return -1; 1345 * } else if (x > y) { 1346 * return 1; 1347 * } else { 1348 * return 1; 1349 * } 1350 * } 1351 */ 1352 /* op vAA, vBB, vCC */ 1353 FETCH(r0, 1) @ r0<- CCBB 1354 mov r9, rINST, lsr #8 @ r9<- AA 1355 and r2, r0, #255 @ r2<- BB 1356 mov r3, r0, lsr #8 @ r3<- CC 1357 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1358 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1359 flds s0, [r2] @ s0<- vBB 1360 flds s1, [r3] @ s1<- vCC 1361 fcmpes s0, s1 @ compare (vBB, vCC) 1362 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1363 mov r0, #1 @ r0<- 1 (default) 1364 GET_INST_OPCODE(ip) @ extract opcode from rINST 1365 fmstat @ export status flags 1366 mvnmi r0, #0 @ (less than) r1<- -1 1367 moveq r0, #0 @ (equal) r1<- 0 1368 b .LOP_CMPG_FLOAT_finish @ argh 1369 1370 1371/* ------------------------------ */ 1372 .balign 64 1373.L_OP_CMPL_DOUBLE: /* 0x2f */ 1374/* File: arm-vfp/OP_CMPL_DOUBLE.S */ 1375 /* 1376 * Compare two floating-point values. Puts 0, 1, or -1 into the 1377 * destination register based on the results of the comparison. 1378 * 1379 * int compare(x, y) { 1380 * if (x == y) { 1381 * return 0; 1382 * } else if (x > y) { 1383 * return 1; 1384 * } else if (x < y) { 1385 * return -1; 1386 * } else { 1387 * return -1; 1388 * } 1389 * } 1390 */ 1391 /* op vAA, vBB, vCC */ 1392 FETCH(r0, 1) @ r0<- CCBB 1393 mov r9, rINST, lsr #8 @ r9<- AA 1394 and r2, r0, #255 @ r2<- BB 1395 mov r3, r0, lsr #8 @ r3<- CC 1396 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1397 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1398 fldd d0, [r2] @ d0<- vBB 1399 fldd d1, [r3] @ d1<- vCC 1400 fcmped d0, d1 @ compare (vBB, vCC) 1401 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1402 mvn r0, #0 @ r0<- -1 (default) 1403 GET_INST_OPCODE(ip) @ extract opcode from rINST 1404 fmstat @ export status flags 1405 movgt r0, #1 @ (greater than) r1<- 1 1406 moveq r0, #0 @ (equal) r1<- 0 1407 b .LOP_CMPL_DOUBLE_finish @ argh 1408 1409 1410/* ------------------------------ */ 1411 .balign 64 1412.L_OP_CMPG_DOUBLE: /* 0x30 */ 1413/* File: arm-vfp/OP_CMPG_DOUBLE.S */ 1414 /* 1415 * Compare two floating-point values. Puts 0, 1, or -1 into the 1416 * destination register based on the results of the comparison. 1417 * 1418 * int compare(x, y) { 1419 * if (x == y) { 1420 * return 0; 1421 * } else if (x < y) { 1422 * return -1; 1423 * } else if (x > y) { 1424 * return 1; 1425 * } else { 1426 * return 1; 1427 * } 1428 * } 1429 */ 1430 /* op vAA, vBB, vCC */ 1431 FETCH(r0, 1) @ r0<- CCBB 1432 mov r9, rINST, lsr #8 @ r9<- AA 1433 and r2, r0, #255 @ r2<- BB 1434 mov r3, r0, lsr #8 @ r3<- CC 1435 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1436 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1437 fldd d0, [r2] @ d0<- vBB 1438 fldd d1, [r3] @ d1<- vCC 1439 fcmped d0, d1 @ compare (vBB, vCC) 1440 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1441 mov r0, #1 @ r0<- 1 (default) 1442 GET_INST_OPCODE(ip) @ extract opcode from rINST 1443 fmstat @ export status flags 1444 mvnmi r0, #0 @ (less than) r1<- -1 1445 moveq r0, #0 @ (equal) r1<- 0 1446 b .LOP_CMPG_DOUBLE_finish @ argh 1447 1448 1449/* ------------------------------ */ 1450 .balign 64 1451.L_OP_CMP_LONG: /* 0x31 */ 1452/* File: armv5te/OP_CMP_LONG.S */ 1453 /* 1454 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1455 * register based on the results of the comparison. 1456 * 1457 * We load the full values with LDM, but in practice many values could 1458 * be resolved by only looking at the high word. This could be made 1459 * faster or slower by splitting the LDM into a pair of LDRs. 1460 * 1461 * If we just wanted to set condition flags, we could do this: 1462 * subs ip, r0, r2 1463 * sbcs ip, r1, r3 1464 * subeqs ip, r0, r2 1465 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1466 * integer value, which we can do with 2 conditional mov/mvn instructions 1467 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1468 * us a constant 5-cycle path plus a branch at the end to the 1469 * instruction epilogue code. The multi-compare approach below needs 1470 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1471 * in the worst case (the 64-bit values are equal). 1472 */ 1473 /* cmp-long vAA, vBB, vCC */ 1474 FETCH(r0, 1) @ r0<- CCBB 1475 mov r9, rINST, lsr #8 @ r9<- AA 1476 and r2, r0, #255 @ r2<- BB 1477 mov r3, r0, lsr #8 @ r3<- CC 1478 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1479 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1480 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1481 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1482 cmp r1, r3 @ compare (vBB+1, vCC+1) 1483 blt .LOP_CMP_LONG_less @ signed compare on high part 1484 bgt .LOP_CMP_LONG_greater 1485 subs r1, r0, r2 @ r1<- r0 - r2 1486 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1487 bne .LOP_CMP_LONG_less 1488 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1489 1490/* ------------------------------ */ 1491 .balign 64 1492.L_OP_IF_EQ: /* 0x32 */ 1493/* File: armv6t2/OP_IF_EQ.S */ 1494/* File: armv6t2/bincmp.S */ 1495 /* 1496 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1497 * fragment that specifies the *reverse* comparison to perform, e.g. 1498 * for "if-le" you would use "gt". 1499 * 1500 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1501 */ 1502 /* if-cmp vA, vB, +CCCC */ 1503 mov r1, rINST, lsr #12 @ r1<- B 1504 ubfx r0, rINST, #8, #4 @ r0<- A 1505 GET_VREG(r3, r1) @ r3<- vB 1506 GET_VREG(r2, r0) @ r2<- vA 1507 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1508 cmp r2, r3 @ compare (vA, vB) 1509 bne 1f @ branch to 1 if comparison failed 1510 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1511 movs r9, r9, asl #1 @ convert to bytes, check sign 1512 bmi common_backwardBranch @ yes, do periodic checks 15131: 1514#if defined(WITH_JIT) 1515 GET_JIT_PROF_TABLE(r0) 1516 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1517 b common_testUpdateProfile 1518#else 1519 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1520 GET_INST_OPCODE(ip) @ extract opcode from rINST 1521 GOTO_OPCODE(ip) @ jump to next instruction 1522#endif 1523 1524 1525/* ------------------------------ */ 1526 .balign 64 1527.L_OP_IF_NE: /* 0x33 */ 1528/* File: armv6t2/OP_IF_NE.S */ 1529/* File: armv6t2/bincmp.S */ 1530 /* 1531 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1532 * fragment that specifies the *reverse* comparison to perform, e.g. 1533 * for "if-le" you would use "gt". 1534 * 1535 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1536 */ 1537 /* if-cmp vA, vB, +CCCC */ 1538 mov r1, rINST, lsr #12 @ r1<- B 1539 ubfx r0, rINST, #8, #4 @ r0<- A 1540 GET_VREG(r3, r1) @ r3<- vB 1541 GET_VREG(r2, r0) @ r2<- vA 1542 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1543 cmp r2, r3 @ compare (vA, vB) 1544 beq 1f @ branch to 1 if comparison failed 1545 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1546 movs r9, r9, asl #1 @ convert to bytes, check sign 1547 bmi common_backwardBranch @ yes, do periodic checks 15481: 1549#if defined(WITH_JIT) 1550 GET_JIT_PROF_TABLE(r0) 1551 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1552 b common_testUpdateProfile 1553#else 1554 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1555 GET_INST_OPCODE(ip) @ extract opcode from rINST 1556 GOTO_OPCODE(ip) @ jump to next instruction 1557#endif 1558 1559 1560/* ------------------------------ */ 1561 .balign 64 1562.L_OP_IF_LT: /* 0x34 */ 1563/* File: armv6t2/OP_IF_LT.S */ 1564/* File: armv6t2/bincmp.S */ 1565 /* 1566 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1567 * fragment that specifies the *reverse* comparison to perform, e.g. 1568 * for "if-le" you would use "gt". 1569 * 1570 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1571 */ 1572 /* if-cmp vA, vB, +CCCC */ 1573 mov r1, rINST, lsr #12 @ r1<- B 1574 ubfx r0, rINST, #8, #4 @ r0<- A 1575 GET_VREG(r3, r1) @ r3<- vB 1576 GET_VREG(r2, r0) @ r2<- vA 1577 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1578 cmp r2, r3 @ compare (vA, vB) 1579 bge 1f @ branch to 1 if comparison failed 1580 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1581 movs r9, r9, asl #1 @ convert to bytes, check sign 1582 bmi common_backwardBranch @ yes, do periodic checks 15831: 1584#if defined(WITH_JIT) 1585 GET_JIT_PROF_TABLE(r0) 1586 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1587 b common_testUpdateProfile 1588#else 1589 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1590 GET_INST_OPCODE(ip) @ extract opcode from rINST 1591 GOTO_OPCODE(ip) @ jump to next instruction 1592#endif 1593 1594 1595/* ------------------------------ */ 1596 .balign 64 1597.L_OP_IF_GE: /* 0x35 */ 1598/* File: armv6t2/OP_IF_GE.S */ 1599/* File: armv6t2/bincmp.S */ 1600 /* 1601 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1602 * fragment that specifies the *reverse* comparison to perform, e.g. 1603 * for "if-le" you would use "gt". 1604 * 1605 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1606 */ 1607 /* if-cmp vA, vB, +CCCC */ 1608 mov r1, rINST, lsr #12 @ r1<- B 1609 ubfx r0, rINST, #8, #4 @ r0<- A 1610 GET_VREG(r3, r1) @ r3<- vB 1611 GET_VREG(r2, r0) @ r2<- vA 1612 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1613 cmp r2, r3 @ compare (vA, vB) 1614 blt 1f @ branch to 1 if comparison failed 1615 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1616 movs r9, r9, asl #1 @ convert to bytes, check sign 1617 bmi common_backwardBranch @ yes, do periodic checks 16181: 1619#if defined(WITH_JIT) 1620 GET_JIT_PROF_TABLE(r0) 1621 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1622 b common_testUpdateProfile 1623#else 1624 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1625 GET_INST_OPCODE(ip) @ extract opcode from rINST 1626 GOTO_OPCODE(ip) @ jump to next instruction 1627#endif 1628 1629 1630/* ------------------------------ */ 1631 .balign 64 1632.L_OP_IF_GT: /* 0x36 */ 1633/* File: armv6t2/OP_IF_GT.S */ 1634/* File: armv6t2/bincmp.S */ 1635 /* 1636 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1637 * fragment that specifies the *reverse* comparison to perform, e.g. 1638 * for "if-le" you would use "gt". 1639 * 1640 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1641 */ 1642 /* if-cmp vA, vB, +CCCC */ 1643 mov r1, rINST, lsr #12 @ r1<- B 1644 ubfx r0, rINST, #8, #4 @ r0<- A 1645 GET_VREG(r3, r1) @ r3<- vB 1646 GET_VREG(r2, r0) @ r2<- vA 1647 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1648 cmp r2, r3 @ compare (vA, vB) 1649 ble 1f @ branch to 1 if comparison failed 1650 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1651 movs r9, r9, asl #1 @ convert to bytes, check sign 1652 bmi common_backwardBranch @ yes, do periodic checks 16531: 1654#if defined(WITH_JIT) 1655 GET_JIT_PROF_TABLE(r0) 1656 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1657 b common_testUpdateProfile 1658#else 1659 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1660 GET_INST_OPCODE(ip) @ extract opcode from rINST 1661 GOTO_OPCODE(ip) @ jump to next instruction 1662#endif 1663 1664 1665/* ------------------------------ */ 1666 .balign 64 1667.L_OP_IF_LE: /* 0x37 */ 1668/* File: armv6t2/OP_IF_LE.S */ 1669/* File: armv6t2/bincmp.S */ 1670 /* 1671 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1672 * fragment that specifies the *reverse* comparison to perform, e.g. 1673 * for "if-le" you would use "gt". 1674 * 1675 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1676 */ 1677 /* if-cmp vA, vB, +CCCC */ 1678 mov r1, rINST, lsr #12 @ r1<- B 1679 ubfx r0, rINST, #8, #4 @ r0<- A 1680 GET_VREG(r3, r1) @ r3<- vB 1681 GET_VREG(r2, r0) @ r2<- vA 1682 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1683 cmp r2, r3 @ compare (vA, vB) 1684 bgt 1f @ branch to 1 if comparison failed 1685 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1686 movs r9, r9, asl #1 @ convert to bytes, check sign 1687 bmi common_backwardBranch @ yes, do periodic checks 16881: 1689#if defined(WITH_JIT) 1690 GET_JIT_PROF_TABLE(r0) 1691 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1692 b common_testUpdateProfile 1693#else 1694 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1695 GET_INST_OPCODE(ip) @ extract opcode from rINST 1696 GOTO_OPCODE(ip) @ jump to next instruction 1697#endif 1698 1699 1700/* ------------------------------ */ 1701 .balign 64 1702.L_OP_IF_EQZ: /* 0x38 */ 1703/* File: armv5te/OP_IF_EQZ.S */ 1704/* File: armv5te/zcmp.S */ 1705 /* 1706 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1707 * fragment that specifies the *reverse* comparison to perform, e.g. 1708 * for "if-le" you would use "gt". 1709 * 1710 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1711 */ 1712 /* if-cmp vAA, +BBBB */ 1713 mov r0, rINST, lsr #8 @ r0<- AA 1714 GET_VREG(r2, r0) @ r2<- vAA 1715 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1716 cmp r2, #0 @ compare (vA, 0) 1717 bne 1f @ branch to 1 if comparison failed 1718 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1719 movs r9, r9, asl #1 @ convert to bytes, check sign 1720 bmi common_backwardBranch @ backward branch, do periodic checks 17211: 1722#if defined(WITH_JIT) 1723 GET_JIT_PROF_TABLE(r0) 1724 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1725 cmp r0,#0 1726 bne common_updateProfile 1727 GET_INST_OPCODE(ip) @ extract opcode from rINST 1728 GOTO_OPCODE(ip) @ jump to next instruction 1729#else 1730 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1731 GET_INST_OPCODE(ip) @ extract opcode from rINST 1732 GOTO_OPCODE(ip) @ jump to next instruction 1733#endif 1734 1735 1736/* ------------------------------ */ 1737 .balign 64 1738.L_OP_IF_NEZ: /* 0x39 */ 1739/* File: armv5te/OP_IF_NEZ.S */ 1740/* File: armv5te/zcmp.S */ 1741 /* 1742 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1743 * fragment that specifies the *reverse* comparison to perform, e.g. 1744 * for "if-le" you would use "gt". 1745 * 1746 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1747 */ 1748 /* if-cmp vAA, +BBBB */ 1749 mov r0, rINST, lsr #8 @ r0<- AA 1750 GET_VREG(r2, r0) @ r2<- vAA 1751 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1752 cmp r2, #0 @ compare (vA, 0) 1753 beq 1f @ branch to 1 if comparison failed 1754 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1755 movs r9, r9, asl #1 @ convert to bytes, check sign 1756 bmi common_backwardBranch @ backward branch, do periodic checks 17571: 1758#if defined(WITH_JIT) 1759 GET_JIT_PROF_TABLE(r0) 1760 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1761 cmp r0,#0 1762 bne common_updateProfile 1763 GET_INST_OPCODE(ip) @ extract opcode from rINST 1764 GOTO_OPCODE(ip) @ jump to next instruction 1765#else 1766 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1767 GET_INST_OPCODE(ip) @ extract opcode from rINST 1768 GOTO_OPCODE(ip) @ jump to next instruction 1769#endif 1770 1771 1772/* ------------------------------ */ 1773 .balign 64 1774.L_OP_IF_LTZ: /* 0x3a */ 1775/* File: armv5te/OP_IF_LTZ.S */ 1776/* File: armv5te/zcmp.S */ 1777 /* 1778 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1779 * fragment that specifies the *reverse* comparison to perform, e.g. 1780 * for "if-le" you would use "gt". 1781 * 1782 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1783 */ 1784 /* if-cmp vAA, +BBBB */ 1785 mov r0, rINST, lsr #8 @ r0<- AA 1786 GET_VREG(r2, r0) @ r2<- vAA 1787 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1788 cmp r2, #0 @ compare (vA, 0) 1789 bge 1f @ branch to 1 if comparison failed 1790 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1791 movs r9, r9, asl #1 @ convert to bytes, check sign 1792 bmi common_backwardBranch @ backward branch, do periodic checks 17931: 1794#if defined(WITH_JIT) 1795 GET_JIT_PROF_TABLE(r0) 1796 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1797 cmp r0,#0 1798 bne common_updateProfile 1799 GET_INST_OPCODE(ip) @ extract opcode from rINST 1800 GOTO_OPCODE(ip) @ jump to next instruction 1801#else 1802 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1803 GET_INST_OPCODE(ip) @ extract opcode from rINST 1804 GOTO_OPCODE(ip) @ jump to next instruction 1805#endif 1806 1807 1808/* ------------------------------ */ 1809 .balign 64 1810.L_OP_IF_GEZ: /* 0x3b */ 1811/* File: armv5te/OP_IF_GEZ.S */ 1812/* File: armv5te/zcmp.S */ 1813 /* 1814 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1815 * fragment that specifies the *reverse* comparison to perform, e.g. 1816 * for "if-le" you would use "gt". 1817 * 1818 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1819 */ 1820 /* if-cmp vAA, +BBBB */ 1821 mov r0, rINST, lsr #8 @ r0<- AA 1822 GET_VREG(r2, r0) @ r2<- vAA 1823 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1824 cmp r2, #0 @ compare (vA, 0) 1825 blt 1f @ branch to 1 if comparison failed 1826 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1827 movs r9, r9, asl #1 @ convert to bytes, check sign 1828 bmi common_backwardBranch @ backward branch, do periodic checks 18291: 1830#if defined(WITH_JIT) 1831 GET_JIT_PROF_TABLE(r0) 1832 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1833 cmp r0,#0 1834 bne common_updateProfile 1835 GET_INST_OPCODE(ip) @ extract opcode from rINST 1836 GOTO_OPCODE(ip) @ jump to next instruction 1837#else 1838 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1839 GET_INST_OPCODE(ip) @ extract opcode from rINST 1840 GOTO_OPCODE(ip) @ jump to next instruction 1841#endif 1842 1843 1844/* ------------------------------ */ 1845 .balign 64 1846.L_OP_IF_GTZ: /* 0x3c */ 1847/* File: armv5te/OP_IF_GTZ.S */ 1848/* File: armv5te/zcmp.S */ 1849 /* 1850 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1851 * fragment that specifies the *reverse* comparison to perform, e.g. 1852 * for "if-le" you would use "gt". 1853 * 1854 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1855 */ 1856 /* if-cmp vAA, +BBBB */ 1857 mov r0, rINST, lsr #8 @ r0<- AA 1858 GET_VREG(r2, r0) @ r2<- vAA 1859 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1860 cmp r2, #0 @ compare (vA, 0) 1861 ble 1f @ branch to 1 if comparison failed 1862 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1863 movs r9, r9, asl #1 @ convert to bytes, check sign 1864 bmi common_backwardBranch @ backward branch, do periodic checks 18651: 1866#if defined(WITH_JIT) 1867 GET_JIT_PROF_TABLE(r0) 1868 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1869 cmp r0,#0 1870 bne common_updateProfile 1871 GET_INST_OPCODE(ip) @ extract opcode from rINST 1872 GOTO_OPCODE(ip) @ jump to next instruction 1873#else 1874 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1875 GET_INST_OPCODE(ip) @ extract opcode from rINST 1876 GOTO_OPCODE(ip) @ jump to next instruction 1877#endif 1878 1879 1880/* ------------------------------ */ 1881 .balign 64 1882.L_OP_IF_LEZ: /* 0x3d */ 1883/* File: armv5te/OP_IF_LEZ.S */ 1884/* File: armv5te/zcmp.S */ 1885 /* 1886 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1887 * fragment that specifies the *reverse* comparison to perform, e.g. 1888 * for "if-le" you would use "gt". 1889 * 1890 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1891 */ 1892 /* if-cmp vAA, +BBBB */ 1893 mov r0, rINST, lsr #8 @ r0<- AA 1894 GET_VREG(r2, r0) @ r2<- vAA 1895 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1896 cmp r2, #0 @ compare (vA, 0) 1897 bgt 1f @ branch to 1 if comparison failed 1898 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1899 movs r9, r9, asl #1 @ convert to bytes, check sign 1900 bmi common_backwardBranch @ backward branch, do periodic checks 19011: 1902#if defined(WITH_JIT) 1903 GET_JIT_PROF_TABLE(r0) 1904 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1905 cmp r0,#0 1906 bne common_updateProfile 1907 GET_INST_OPCODE(ip) @ extract opcode from rINST 1908 GOTO_OPCODE(ip) @ jump to next instruction 1909#else 1910 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1911 GET_INST_OPCODE(ip) @ extract opcode from rINST 1912 GOTO_OPCODE(ip) @ jump to next instruction 1913#endif 1914 1915 1916/* ------------------------------ */ 1917 .balign 64 1918.L_OP_UNUSED_3E: /* 0x3e */ 1919/* File: armv5te/OP_UNUSED_3E.S */ 1920/* File: armv5te/unused.S */ 1921 bl common_abort 1922 1923 1924/* ------------------------------ */ 1925 .balign 64 1926.L_OP_UNUSED_3F: /* 0x3f */ 1927/* File: armv5te/OP_UNUSED_3F.S */ 1928/* File: armv5te/unused.S */ 1929 bl common_abort 1930 1931 1932/* ------------------------------ */ 1933 .balign 64 1934.L_OP_UNUSED_40: /* 0x40 */ 1935/* File: armv5te/OP_UNUSED_40.S */ 1936/* File: armv5te/unused.S */ 1937 bl common_abort 1938 1939 1940/* ------------------------------ */ 1941 .balign 64 1942.L_OP_UNUSED_41: /* 0x41 */ 1943/* File: armv5te/OP_UNUSED_41.S */ 1944/* File: armv5te/unused.S */ 1945 bl common_abort 1946 1947 1948/* ------------------------------ */ 1949 .balign 64 1950.L_OP_UNUSED_42: /* 0x42 */ 1951/* File: armv5te/OP_UNUSED_42.S */ 1952/* File: armv5te/unused.S */ 1953 bl common_abort 1954 1955 1956/* ------------------------------ */ 1957 .balign 64 1958.L_OP_UNUSED_43: /* 0x43 */ 1959/* File: armv5te/OP_UNUSED_43.S */ 1960/* File: armv5te/unused.S */ 1961 bl common_abort 1962 1963 1964/* ------------------------------ */ 1965 .balign 64 1966.L_OP_AGET: /* 0x44 */ 1967/* File: armv5te/OP_AGET.S */ 1968 /* 1969 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1970 * 1971 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1972 * instructions. We use a pair of FETCH_Bs instead. 1973 * 1974 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1975 */ 1976 /* op vAA, vBB, vCC */ 1977 FETCH_B(r2, 1, 0) @ r2<- BB 1978 mov r9, rINST, lsr #8 @ r9<- AA 1979 FETCH_B(r3, 1, 1) @ r3<- CC 1980 GET_VREG(r0, r2) @ r0<- vBB (array object) 1981 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1982 cmp r0, #0 @ null array object? 1983 beq common_errNullObject @ yes, bail 1984 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1985 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 1986 cmp r1, r3 @ compare unsigned index, length 1987 bcs common_errArrayIndex @ index >= length, bail 1988 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1989 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 1990 GET_INST_OPCODE(ip) @ extract opcode from rINST 1991 SET_VREG(r2, r9) @ vAA<- r2 1992 GOTO_OPCODE(ip) @ jump to next instruction 1993 1994/* ------------------------------ */ 1995 .balign 64 1996.L_OP_AGET_WIDE: /* 0x45 */ 1997/* File: armv5te/OP_AGET_WIDE.S */ 1998 /* 1999 * Array get, 64 bits. vAA <- vBB[vCC]. 2000 * 2001 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 2002 */ 2003 /* aget-wide vAA, vBB, vCC */ 2004 FETCH(r0, 1) @ r0<- CCBB 2005 mov r9, rINST, lsr #8 @ r9<- AA 2006 and r2, r0, #255 @ r2<- BB 2007 mov r3, r0, lsr #8 @ r3<- CC 2008 GET_VREG(r0, r2) @ r0<- vBB (array object) 2009 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2010 cmp r0, #0 @ null array object? 2011 beq common_errNullObject @ yes, bail 2012 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2013 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2014 cmp r1, r3 @ compare unsigned index, length 2015 bcc .LOP_AGET_WIDE_finish @ okay, continue below 2016 b common_errArrayIndex @ index >= length, bail 2017 @ May want to swap the order of these two branches depending on how the 2018 @ branch prediction (if any) handles conditional forward branches vs. 2019 @ unconditional forward branches. 2020 2021/* ------------------------------ */ 2022 .balign 64 2023.L_OP_AGET_OBJECT: /* 0x46 */ 2024/* File: armv5te/OP_AGET_OBJECT.S */ 2025/* File: armv5te/OP_AGET.S */ 2026 /* 2027 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2028 * 2029 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2030 * instructions. We use a pair of FETCH_Bs instead. 2031 * 2032 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2033 */ 2034 /* op vAA, vBB, vCC */ 2035 FETCH_B(r2, 1, 0) @ r2<- BB 2036 mov r9, rINST, lsr #8 @ r9<- AA 2037 FETCH_B(r3, 1, 1) @ r3<- CC 2038 GET_VREG(r0, r2) @ r0<- vBB (array object) 2039 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2040 cmp r0, #0 @ null array object? 2041 beq common_errNullObject @ yes, bail 2042 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2043 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2044 cmp r1, r3 @ compare unsigned index, length 2045 bcs common_errArrayIndex @ index >= length, bail 2046 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2047 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2048 GET_INST_OPCODE(ip) @ extract opcode from rINST 2049 SET_VREG(r2, r9) @ vAA<- r2 2050 GOTO_OPCODE(ip) @ jump to next instruction 2051 2052 2053/* ------------------------------ */ 2054 .balign 64 2055.L_OP_AGET_BOOLEAN: /* 0x47 */ 2056/* File: armv5te/OP_AGET_BOOLEAN.S */ 2057/* File: armv5te/OP_AGET.S */ 2058 /* 2059 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2060 * 2061 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2062 * instructions. We use a pair of FETCH_Bs instead. 2063 * 2064 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2065 */ 2066 /* op vAA, vBB, vCC */ 2067 FETCH_B(r2, 1, 0) @ r2<- BB 2068 mov r9, rINST, lsr #8 @ r9<- AA 2069 FETCH_B(r3, 1, 1) @ r3<- CC 2070 GET_VREG(r0, r2) @ r0<- vBB (array object) 2071 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2072 cmp r0, #0 @ null array object? 2073 beq common_errNullObject @ yes, bail 2074 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2075 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2076 cmp r1, r3 @ compare unsigned index, length 2077 bcs common_errArrayIndex @ index >= length, bail 2078 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2079 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2080 GET_INST_OPCODE(ip) @ extract opcode from rINST 2081 SET_VREG(r2, r9) @ vAA<- r2 2082 GOTO_OPCODE(ip) @ jump to next instruction 2083 2084 2085/* ------------------------------ */ 2086 .balign 64 2087.L_OP_AGET_BYTE: /* 0x48 */ 2088/* File: armv5te/OP_AGET_BYTE.S */ 2089/* File: armv5te/OP_AGET.S */ 2090 /* 2091 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2092 * 2093 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2094 * instructions. We use a pair of FETCH_Bs instead. 2095 * 2096 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2097 */ 2098 /* op vAA, vBB, vCC */ 2099 FETCH_B(r2, 1, 0) @ r2<- BB 2100 mov r9, rINST, lsr #8 @ r9<- AA 2101 FETCH_B(r3, 1, 1) @ r3<- CC 2102 GET_VREG(r0, r2) @ r0<- vBB (array object) 2103 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2104 cmp r0, #0 @ null array object? 2105 beq common_errNullObject @ yes, bail 2106 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2107 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2108 cmp r1, r3 @ compare unsigned index, length 2109 bcs common_errArrayIndex @ index >= length, bail 2110 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2111 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2112 GET_INST_OPCODE(ip) @ extract opcode from rINST 2113 SET_VREG(r2, r9) @ vAA<- r2 2114 GOTO_OPCODE(ip) @ jump to next instruction 2115 2116 2117/* ------------------------------ */ 2118 .balign 64 2119.L_OP_AGET_CHAR: /* 0x49 */ 2120/* File: armv5te/OP_AGET_CHAR.S */ 2121/* File: armv5te/OP_AGET.S */ 2122 /* 2123 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2124 * 2125 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2126 * instructions. We use a pair of FETCH_Bs instead. 2127 * 2128 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2129 */ 2130 /* op vAA, vBB, vCC */ 2131 FETCH_B(r2, 1, 0) @ r2<- BB 2132 mov r9, rINST, lsr #8 @ r9<- AA 2133 FETCH_B(r3, 1, 1) @ r3<- CC 2134 GET_VREG(r0, r2) @ r0<- vBB (array object) 2135 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2136 cmp r0, #0 @ null array object? 2137 beq common_errNullObject @ yes, bail 2138 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2139 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2140 cmp r1, r3 @ compare unsigned index, length 2141 bcs common_errArrayIndex @ index >= length, bail 2142 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2143 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2144 GET_INST_OPCODE(ip) @ extract opcode from rINST 2145 SET_VREG(r2, r9) @ vAA<- r2 2146 GOTO_OPCODE(ip) @ jump to next instruction 2147 2148 2149/* ------------------------------ */ 2150 .balign 64 2151.L_OP_AGET_SHORT: /* 0x4a */ 2152/* File: armv5te/OP_AGET_SHORT.S */ 2153/* File: armv5te/OP_AGET.S */ 2154 /* 2155 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2156 * 2157 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2158 * instructions. We use a pair of FETCH_Bs instead. 2159 * 2160 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2161 */ 2162 /* op vAA, vBB, vCC */ 2163 FETCH_B(r2, 1, 0) @ r2<- BB 2164 mov r9, rINST, lsr #8 @ r9<- AA 2165 FETCH_B(r3, 1, 1) @ r3<- CC 2166 GET_VREG(r0, r2) @ r0<- vBB (array object) 2167 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2168 cmp r0, #0 @ null array object? 2169 beq common_errNullObject @ yes, bail 2170 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2171 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2172 cmp r1, r3 @ compare unsigned index, length 2173 bcs common_errArrayIndex @ index >= length, bail 2174 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2175 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2176 GET_INST_OPCODE(ip) @ extract opcode from rINST 2177 SET_VREG(r2, r9) @ vAA<- r2 2178 GOTO_OPCODE(ip) @ jump to next instruction 2179 2180 2181/* ------------------------------ */ 2182 .balign 64 2183.L_OP_APUT: /* 0x4b */ 2184/* File: armv5te/OP_APUT.S */ 2185 /* 2186 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2187 * 2188 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2189 * instructions. We use a pair of FETCH_Bs instead. 2190 * 2191 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2192 */ 2193 /* op vAA, vBB, vCC */ 2194 FETCH_B(r2, 1, 0) @ r2<- BB 2195 mov r9, rINST, lsr #8 @ r9<- AA 2196 FETCH_B(r3, 1, 1) @ r3<- CC 2197 GET_VREG(r0, r2) @ r0<- vBB (array object) 2198 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2199 cmp r0, #0 @ null array object? 2200 beq common_errNullObject @ yes, bail 2201 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2202 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2203 cmp r1, r3 @ compare unsigned index, length 2204 bcs common_errArrayIndex @ index >= length, bail 2205 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2206 GET_VREG(r2, r9) @ r2<- vAA 2207 GET_INST_OPCODE(ip) @ extract opcode from rINST 2208 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2209 GOTO_OPCODE(ip) @ jump to next instruction 2210 2211/* ------------------------------ */ 2212 .balign 64 2213.L_OP_APUT_WIDE: /* 0x4c */ 2214/* File: armv5te/OP_APUT_WIDE.S */ 2215 /* 2216 * Array put, 64 bits. vBB[vCC] <- vAA. 2217 * 2218 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 2219 */ 2220 /* aput-wide vAA, vBB, vCC */ 2221 FETCH(r0, 1) @ r0<- CCBB 2222 mov r9, rINST, lsr #8 @ r9<- AA 2223 and r2, r0, #255 @ r2<- BB 2224 mov r3, r0, lsr #8 @ r3<- CC 2225 GET_VREG(r0, r2) @ r0<- vBB (array object) 2226 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2227 cmp r0, #0 @ null array object? 2228 beq common_errNullObject @ yes, bail 2229 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2230 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2231 cmp r1, r3 @ compare unsigned index, length 2232 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2233 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2234 b common_errArrayIndex @ index >= length, bail 2235 @ May want to swap the order of these two branches depending on how the 2236 @ branch prediction (if any) handles conditional forward branches vs. 2237 @ unconditional forward branches. 2238 2239/* ------------------------------ */ 2240 .balign 64 2241.L_OP_APUT_OBJECT: /* 0x4d */ 2242/* File: armv5te/OP_APUT_OBJECT.S */ 2243 /* 2244 * Store an object into an array. vBB[vCC] <- vAA. 2245 * 2246 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2247 * instructions. We use a pair of FETCH_Bs instead. 2248 */ 2249 /* op vAA, vBB, vCC */ 2250 FETCH(r0, 1) @ r0<- CCBB 2251 mov r9, rINST, lsr #8 @ r9<- AA 2252 and r2, r0, #255 @ r2<- BB 2253 mov r3, r0, lsr #8 @ r3<- CC 2254 GET_VREG(r1, r2) @ r1<- vBB (array object) 2255 GET_VREG(r0, r3) @ r0<- vCC (requested index) 2256 cmp r1, #0 @ null array object? 2257 GET_VREG(r9, r9) @ r9<- vAA 2258 beq common_errNullObject @ yes, bail 2259 ldr r3, [r1, #offArrayObject_length] @ r3<- arrayObj->length 2260 add r10, r1, r0, lsl #2 @ r10<- arrayObj + index*width 2261 cmp r0, r3 @ compare unsigned index, length 2262 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2263 b common_errArrayIndex @ index >= length, bail 2264 2265 2266/* ------------------------------ */ 2267 .balign 64 2268.L_OP_APUT_BOOLEAN: /* 0x4e */ 2269/* File: armv5te/OP_APUT_BOOLEAN.S */ 2270/* File: armv5te/OP_APUT.S */ 2271 /* 2272 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2273 * 2274 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2275 * instructions. We use a pair of FETCH_Bs instead. 2276 * 2277 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2278 */ 2279 /* op vAA, vBB, vCC */ 2280 FETCH_B(r2, 1, 0) @ r2<- BB 2281 mov r9, rINST, lsr #8 @ r9<- AA 2282 FETCH_B(r3, 1, 1) @ r3<- CC 2283 GET_VREG(r0, r2) @ r0<- vBB (array object) 2284 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2285 cmp r0, #0 @ null array object? 2286 beq common_errNullObject @ yes, bail 2287 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2288 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2289 cmp r1, r3 @ compare unsigned index, length 2290 bcs common_errArrayIndex @ index >= length, bail 2291 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2292 GET_VREG(r2, r9) @ r2<- vAA 2293 GET_INST_OPCODE(ip) @ extract opcode from rINST 2294 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2295 GOTO_OPCODE(ip) @ jump to next instruction 2296 2297 2298/* ------------------------------ */ 2299 .balign 64 2300.L_OP_APUT_BYTE: /* 0x4f */ 2301/* File: armv5te/OP_APUT_BYTE.S */ 2302/* File: armv5te/OP_APUT.S */ 2303 /* 2304 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2305 * 2306 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2307 * instructions. We use a pair of FETCH_Bs instead. 2308 * 2309 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2310 */ 2311 /* op vAA, vBB, vCC */ 2312 FETCH_B(r2, 1, 0) @ r2<- BB 2313 mov r9, rINST, lsr #8 @ r9<- AA 2314 FETCH_B(r3, 1, 1) @ r3<- CC 2315 GET_VREG(r0, r2) @ r0<- vBB (array object) 2316 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2317 cmp r0, #0 @ null array object? 2318 beq common_errNullObject @ yes, bail 2319 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2320 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2321 cmp r1, r3 @ compare unsigned index, length 2322 bcs common_errArrayIndex @ index >= length, bail 2323 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2324 GET_VREG(r2, r9) @ r2<- vAA 2325 GET_INST_OPCODE(ip) @ extract opcode from rINST 2326 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2327 GOTO_OPCODE(ip) @ jump to next instruction 2328 2329 2330/* ------------------------------ */ 2331 .balign 64 2332.L_OP_APUT_CHAR: /* 0x50 */ 2333/* File: armv5te/OP_APUT_CHAR.S */ 2334/* File: armv5te/OP_APUT.S */ 2335 /* 2336 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2337 * 2338 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2339 * instructions. We use a pair of FETCH_Bs instead. 2340 * 2341 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2342 */ 2343 /* op vAA, vBB, vCC */ 2344 FETCH_B(r2, 1, 0) @ r2<- BB 2345 mov r9, rINST, lsr #8 @ r9<- AA 2346 FETCH_B(r3, 1, 1) @ r3<- CC 2347 GET_VREG(r0, r2) @ r0<- vBB (array object) 2348 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2349 cmp r0, #0 @ null array object? 2350 beq common_errNullObject @ yes, bail 2351 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2352 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2353 cmp r1, r3 @ compare unsigned index, length 2354 bcs common_errArrayIndex @ index >= length, bail 2355 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2356 GET_VREG(r2, r9) @ r2<- vAA 2357 GET_INST_OPCODE(ip) @ extract opcode from rINST 2358 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2359 GOTO_OPCODE(ip) @ jump to next instruction 2360 2361 2362/* ------------------------------ */ 2363 .balign 64 2364.L_OP_APUT_SHORT: /* 0x51 */ 2365/* File: armv5te/OP_APUT_SHORT.S */ 2366/* File: armv5te/OP_APUT.S */ 2367 /* 2368 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2369 * 2370 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2371 * instructions. We use a pair of FETCH_Bs instead. 2372 * 2373 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2374 */ 2375 /* op vAA, vBB, vCC */ 2376 FETCH_B(r2, 1, 0) @ r2<- BB 2377 mov r9, rINST, lsr #8 @ r9<- AA 2378 FETCH_B(r3, 1, 1) @ r3<- CC 2379 GET_VREG(r0, r2) @ r0<- vBB (array object) 2380 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2381 cmp r0, #0 @ null array object? 2382 beq common_errNullObject @ yes, bail 2383 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2384 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2385 cmp r1, r3 @ compare unsigned index, length 2386 bcs common_errArrayIndex @ index >= length, bail 2387 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2388 GET_VREG(r2, r9) @ r2<- vAA 2389 GET_INST_OPCODE(ip) @ extract opcode from rINST 2390 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2391 GOTO_OPCODE(ip) @ jump to next instruction 2392 2393 2394/* ------------------------------ */ 2395 .balign 64 2396.L_OP_IGET: /* 0x52 */ 2397/* File: armv6t2/OP_IGET.S */ 2398 /* 2399 * General 32-bit instance field get. 2400 * 2401 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2402 */ 2403 /* op vA, vB, field@CCCC */ 2404 mov r0, rINST, lsr #12 @ r0<- B 2405 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2406 FETCH(r1, 1) @ r1<- field ref CCCC 2407 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2408 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2409 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2410 cmp r0, #0 @ is resolved entry null? 2411 bne .LOP_IGET_finish @ no, already resolved 24128: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2413 EXPORT_PC() @ resolve() could throw 2414 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2415 bl dvmResolveInstField @ r0<- resolved InstField ptr 2416 cmp r0, #0 2417 bne .LOP_IGET_finish 2418 b common_exceptionThrown 2419 2420/* ------------------------------ */ 2421 .balign 64 2422.L_OP_IGET_WIDE: /* 0x53 */ 2423/* File: armv6t2/OP_IGET_WIDE.S */ 2424 /* 2425 * Wide 32-bit instance field get. 2426 */ 2427 /* iget-wide vA, vB, field@CCCC */ 2428 mov r0, rINST, lsr #12 @ r0<- B 2429 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2430 FETCH(r1, 1) @ r1<- field ref CCCC 2431 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2432 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2433 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2434 cmp r0, #0 @ is resolved entry null? 2435 bne .LOP_IGET_WIDE_finish @ no, already resolved 24368: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2437 EXPORT_PC() @ resolve() could throw 2438 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2439 bl dvmResolveInstField @ r0<- resolved InstField ptr 2440 cmp r0, #0 2441 bne .LOP_IGET_WIDE_finish 2442 b common_exceptionThrown 2443 2444/* ------------------------------ */ 2445 .balign 64 2446.L_OP_IGET_OBJECT: /* 0x54 */ 2447/* File: armv5te/OP_IGET_OBJECT.S */ 2448/* File: armv5te/OP_IGET.S */ 2449 /* 2450 * General 32-bit instance field get. 2451 * 2452 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2453 */ 2454 /* op vA, vB, field@CCCC */ 2455 mov r0, rINST, lsr #12 @ r0<- B 2456 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2457 FETCH(r1, 1) @ r1<- field ref CCCC 2458 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2459 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2460 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2461 cmp r0, #0 @ is resolved entry null? 2462 bne .LOP_IGET_OBJECT_finish @ no, already resolved 24638: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2464 EXPORT_PC() @ resolve() could throw 2465 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2466 bl dvmResolveInstField @ r0<- resolved InstField ptr 2467 cmp r0, #0 2468 bne .LOP_IGET_OBJECT_finish 2469 b common_exceptionThrown 2470 2471 2472/* ------------------------------ */ 2473 .balign 64 2474.L_OP_IGET_BOOLEAN: /* 0x55 */ 2475/* File: armv5te/OP_IGET_BOOLEAN.S */ 2476@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2477/* File: armv5te/OP_IGET.S */ 2478 /* 2479 * General 32-bit instance field get. 2480 * 2481 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2482 */ 2483 /* op vA, vB, field@CCCC */ 2484 mov r0, rINST, lsr #12 @ r0<- B 2485 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2486 FETCH(r1, 1) @ r1<- field ref CCCC 2487 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2488 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2489 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2490 cmp r0, #0 @ is resolved entry null? 2491 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 24928: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2493 EXPORT_PC() @ resolve() could throw 2494 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2495 bl dvmResolveInstField @ r0<- resolved InstField ptr 2496 cmp r0, #0 2497 bne .LOP_IGET_BOOLEAN_finish 2498 b common_exceptionThrown 2499 2500 2501/* ------------------------------ */ 2502 .balign 64 2503.L_OP_IGET_BYTE: /* 0x56 */ 2504/* File: armv5te/OP_IGET_BYTE.S */ 2505@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2506/* File: armv5te/OP_IGET.S */ 2507 /* 2508 * General 32-bit instance field get. 2509 * 2510 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2511 */ 2512 /* op vA, vB, field@CCCC */ 2513 mov r0, rINST, lsr #12 @ r0<- B 2514 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2515 FETCH(r1, 1) @ r1<- field ref CCCC 2516 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2517 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2518 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2519 cmp r0, #0 @ is resolved entry null? 2520 bne .LOP_IGET_BYTE_finish @ no, already resolved 25218: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2522 EXPORT_PC() @ resolve() could throw 2523 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2524 bl dvmResolveInstField @ r0<- resolved InstField ptr 2525 cmp r0, #0 2526 bne .LOP_IGET_BYTE_finish 2527 b common_exceptionThrown 2528 2529 2530/* ------------------------------ */ 2531 .balign 64 2532.L_OP_IGET_CHAR: /* 0x57 */ 2533/* File: armv5te/OP_IGET_CHAR.S */ 2534@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2535/* File: armv5te/OP_IGET.S */ 2536 /* 2537 * General 32-bit instance field get. 2538 * 2539 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2540 */ 2541 /* op vA, vB, field@CCCC */ 2542 mov r0, rINST, lsr #12 @ r0<- B 2543 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2544 FETCH(r1, 1) @ r1<- field ref CCCC 2545 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2546 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2547 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2548 cmp r0, #0 @ is resolved entry null? 2549 bne .LOP_IGET_CHAR_finish @ no, already resolved 25508: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2551 EXPORT_PC() @ resolve() could throw 2552 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2553 bl dvmResolveInstField @ r0<- resolved InstField ptr 2554 cmp r0, #0 2555 bne .LOP_IGET_CHAR_finish 2556 b common_exceptionThrown 2557 2558 2559/* ------------------------------ */ 2560 .balign 64 2561.L_OP_IGET_SHORT: /* 0x58 */ 2562/* File: armv5te/OP_IGET_SHORT.S */ 2563@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2564/* File: armv5te/OP_IGET.S */ 2565 /* 2566 * General 32-bit instance field get. 2567 * 2568 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2569 */ 2570 /* op vA, vB, field@CCCC */ 2571 mov r0, rINST, lsr #12 @ r0<- B 2572 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2573 FETCH(r1, 1) @ r1<- field ref CCCC 2574 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2575 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2576 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2577 cmp r0, #0 @ is resolved entry null? 2578 bne .LOP_IGET_SHORT_finish @ no, already resolved 25798: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2580 EXPORT_PC() @ resolve() could throw 2581 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2582 bl dvmResolveInstField @ r0<- resolved InstField ptr 2583 cmp r0, #0 2584 bne .LOP_IGET_SHORT_finish 2585 b common_exceptionThrown 2586 2587 2588/* ------------------------------ */ 2589 .balign 64 2590.L_OP_IPUT: /* 0x59 */ 2591/* File: armv6t2/OP_IPUT.S */ 2592 /* 2593 * General 32-bit instance field put. 2594 * 2595 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2596 */ 2597 /* op vA, vB, field@CCCC */ 2598 mov r0, rINST, lsr #12 @ r0<- B 2599 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2600 FETCH(r1, 1) @ r1<- field ref CCCC 2601 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2602 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2603 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2604 cmp r0, #0 @ is resolved entry null? 2605 bne .LOP_IPUT_finish @ no, already resolved 26068: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2607 EXPORT_PC() @ resolve() could throw 2608 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2609 bl dvmResolveInstField @ r0<- resolved InstField ptr 2610 cmp r0, #0 @ success? 2611 bne .LOP_IPUT_finish @ yes, finish up 2612 b common_exceptionThrown 2613 2614/* ------------------------------ */ 2615 .balign 64 2616.L_OP_IPUT_WIDE: /* 0x5a */ 2617/* File: armv6t2/OP_IPUT_WIDE.S */ 2618 /* iput-wide vA, vB, field@CCCC */ 2619 mov r0, rINST, lsr #12 @ r0<- B 2620 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2621 FETCH(r1, 1) @ r1<- field ref CCCC 2622 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2623 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2624 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2625 cmp r0, #0 @ is resolved entry null? 2626 bne .LOP_IPUT_WIDE_finish @ no, already resolved 26278: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2628 EXPORT_PC() @ resolve() could throw 2629 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2630 bl dvmResolveInstField @ r0<- resolved InstField ptr 2631 cmp r0, #0 @ success? 2632 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2633 b common_exceptionThrown 2634 2635/* ------------------------------ */ 2636 .balign 64 2637.L_OP_IPUT_OBJECT: /* 0x5b */ 2638/* File: armv5te/OP_IPUT_OBJECT.S */ 2639/* File: armv5te/OP_IPUT.S */ 2640 /* 2641 * General 32-bit instance field put. 2642 * 2643 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2644 */ 2645 /* op vA, vB, field@CCCC */ 2646 mov r0, rINST, lsr #12 @ r0<- B 2647 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2648 FETCH(r1, 1) @ r1<- field ref CCCC 2649 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2650 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2651 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2652 cmp r0, #0 @ is resolved entry null? 2653 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 26548: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2655 EXPORT_PC() @ resolve() could throw 2656 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2657 bl dvmResolveInstField @ r0<- resolved InstField ptr 2658 cmp r0, #0 @ success? 2659 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2660 b common_exceptionThrown 2661 2662 2663/* ------------------------------ */ 2664 .balign 64 2665.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2666/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2667@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2668/* File: armv5te/OP_IPUT.S */ 2669 /* 2670 * General 32-bit instance field put. 2671 * 2672 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2673 */ 2674 /* op vA, vB, field@CCCC */ 2675 mov r0, rINST, lsr #12 @ r0<- B 2676 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2677 FETCH(r1, 1) @ r1<- field ref CCCC 2678 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2679 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2680 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2681 cmp r0, #0 @ is resolved entry null? 2682 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 26838: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2684 EXPORT_PC() @ resolve() could throw 2685 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2686 bl dvmResolveInstField @ r0<- resolved InstField ptr 2687 cmp r0, #0 @ success? 2688 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2689 b common_exceptionThrown 2690 2691 2692/* ------------------------------ */ 2693 .balign 64 2694.L_OP_IPUT_BYTE: /* 0x5d */ 2695/* File: armv5te/OP_IPUT_BYTE.S */ 2696@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2697/* File: armv5te/OP_IPUT.S */ 2698 /* 2699 * General 32-bit instance field put. 2700 * 2701 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2702 */ 2703 /* op vA, vB, field@CCCC */ 2704 mov r0, rINST, lsr #12 @ r0<- B 2705 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2706 FETCH(r1, 1) @ r1<- field ref CCCC 2707 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2708 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2709 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2710 cmp r0, #0 @ is resolved entry null? 2711 bne .LOP_IPUT_BYTE_finish @ no, already resolved 27128: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2713 EXPORT_PC() @ resolve() could throw 2714 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2715 bl dvmResolveInstField @ r0<- resolved InstField ptr 2716 cmp r0, #0 @ success? 2717 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2718 b common_exceptionThrown 2719 2720 2721/* ------------------------------ */ 2722 .balign 64 2723.L_OP_IPUT_CHAR: /* 0x5e */ 2724/* File: armv5te/OP_IPUT_CHAR.S */ 2725@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2726/* File: armv5te/OP_IPUT.S */ 2727 /* 2728 * General 32-bit instance field put. 2729 * 2730 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2731 */ 2732 /* op vA, vB, field@CCCC */ 2733 mov r0, rINST, lsr #12 @ r0<- B 2734 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2735 FETCH(r1, 1) @ r1<- field ref CCCC 2736 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2737 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2738 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2739 cmp r0, #0 @ is resolved entry null? 2740 bne .LOP_IPUT_CHAR_finish @ no, already resolved 27418: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2742 EXPORT_PC() @ resolve() could throw 2743 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2744 bl dvmResolveInstField @ r0<- resolved InstField ptr 2745 cmp r0, #0 @ success? 2746 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2747 b common_exceptionThrown 2748 2749 2750/* ------------------------------ */ 2751 .balign 64 2752.L_OP_IPUT_SHORT: /* 0x5f */ 2753/* File: armv5te/OP_IPUT_SHORT.S */ 2754@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2755/* File: armv5te/OP_IPUT.S */ 2756 /* 2757 * General 32-bit instance field put. 2758 * 2759 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2760 */ 2761 /* op vA, vB, field@CCCC */ 2762 mov r0, rINST, lsr #12 @ r0<- B 2763 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2764 FETCH(r1, 1) @ r1<- field ref CCCC 2765 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2766 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2767 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2768 cmp r0, #0 @ is resolved entry null? 2769 bne .LOP_IPUT_SHORT_finish @ no, already resolved 27708: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2771 EXPORT_PC() @ resolve() could throw 2772 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2773 bl dvmResolveInstField @ r0<- resolved InstField ptr 2774 cmp r0, #0 @ success? 2775 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2776 b common_exceptionThrown 2777 2778 2779/* ------------------------------ */ 2780 .balign 64 2781.L_OP_SGET: /* 0x60 */ 2782/* File: armv5te/OP_SGET.S */ 2783 /* 2784 * General 32-bit SGET handler. 2785 * 2786 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2787 */ 2788 /* op vAA, field@BBBB */ 2789 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2790 FETCH(r1, 1) @ r1<- field ref BBBB 2791 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2792 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2793 cmp r0, #0 @ is resolved entry null? 2794 beq .LOP_SGET_resolve @ yes, do resolve 2795.LOP_SGET_finish: @ field ptr in r0 2796 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2797 @ no-op @ acquiring load 2798 mov r2, rINST, lsr #8 @ r2<- AA 2799 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2800 SET_VREG(r1, r2) @ fp[AA]<- r1 2801 GET_INST_OPCODE(ip) @ extract opcode from rINST 2802 GOTO_OPCODE(ip) @ jump to next instruction 2803 2804/* ------------------------------ */ 2805 .balign 64 2806.L_OP_SGET_WIDE: /* 0x61 */ 2807/* File: armv5te/OP_SGET_WIDE.S */ 2808 /* 2809 * 64-bit SGET handler. 2810 */ 2811 /* sget-wide vAA, field@BBBB */ 2812 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2813 FETCH(r1, 1) @ r1<- field ref BBBB 2814 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2815 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2816 cmp r0, #0 @ is resolved entry null? 2817 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2818.LOP_SGET_WIDE_finish: 2819 mov r9, rINST, lsr #8 @ r9<- AA 2820 .if 0 2821 add r0, r0, #offStaticField_value @ r0<- pointer to data 2822 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 2823 .else 2824 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 2825 .endif 2826 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2827 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2828 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 2829 GET_INST_OPCODE(ip) @ extract opcode from rINST 2830 GOTO_OPCODE(ip) @ jump to next instruction 2831 2832/* ------------------------------ */ 2833 .balign 64 2834.L_OP_SGET_OBJECT: /* 0x62 */ 2835/* File: armv5te/OP_SGET_OBJECT.S */ 2836/* File: armv5te/OP_SGET.S */ 2837 /* 2838 * General 32-bit SGET handler. 2839 * 2840 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2841 */ 2842 /* op vAA, field@BBBB */ 2843 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2844 FETCH(r1, 1) @ r1<- field ref BBBB 2845 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2846 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2847 cmp r0, #0 @ is resolved entry null? 2848 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2849.LOP_SGET_OBJECT_finish: @ field ptr in r0 2850 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2851 @ no-op @ acquiring load 2852 mov r2, rINST, lsr #8 @ r2<- AA 2853 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2854 SET_VREG(r1, r2) @ fp[AA]<- r1 2855 GET_INST_OPCODE(ip) @ extract opcode from rINST 2856 GOTO_OPCODE(ip) @ jump to next instruction 2857 2858 2859/* ------------------------------ */ 2860 .balign 64 2861.L_OP_SGET_BOOLEAN: /* 0x63 */ 2862/* File: armv5te/OP_SGET_BOOLEAN.S */ 2863/* File: armv5te/OP_SGET.S */ 2864 /* 2865 * General 32-bit SGET handler. 2866 * 2867 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2868 */ 2869 /* op vAA, field@BBBB */ 2870 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2871 FETCH(r1, 1) @ r1<- field ref BBBB 2872 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2873 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2874 cmp r0, #0 @ is resolved entry null? 2875 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2876.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2877 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2878 @ no-op @ acquiring load 2879 mov r2, rINST, lsr #8 @ r2<- AA 2880 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2881 SET_VREG(r1, r2) @ fp[AA]<- r1 2882 GET_INST_OPCODE(ip) @ extract opcode from rINST 2883 GOTO_OPCODE(ip) @ jump to next instruction 2884 2885 2886/* ------------------------------ */ 2887 .balign 64 2888.L_OP_SGET_BYTE: /* 0x64 */ 2889/* File: armv5te/OP_SGET_BYTE.S */ 2890/* File: armv5te/OP_SGET.S */ 2891 /* 2892 * General 32-bit SGET handler. 2893 * 2894 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2895 */ 2896 /* op vAA, field@BBBB */ 2897 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2898 FETCH(r1, 1) @ r1<- field ref BBBB 2899 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2900 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2901 cmp r0, #0 @ is resolved entry null? 2902 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2903.LOP_SGET_BYTE_finish: @ field ptr in r0 2904 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2905 @ no-op @ acquiring load 2906 mov r2, rINST, lsr #8 @ r2<- AA 2907 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2908 SET_VREG(r1, r2) @ fp[AA]<- r1 2909 GET_INST_OPCODE(ip) @ extract opcode from rINST 2910 GOTO_OPCODE(ip) @ jump to next instruction 2911 2912 2913/* ------------------------------ */ 2914 .balign 64 2915.L_OP_SGET_CHAR: /* 0x65 */ 2916/* File: armv5te/OP_SGET_CHAR.S */ 2917/* File: armv5te/OP_SGET.S */ 2918 /* 2919 * General 32-bit SGET handler. 2920 * 2921 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2922 */ 2923 /* op vAA, field@BBBB */ 2924 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2925 FETCH(r1, 1) @ r1<- field ref BBBB 2926 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2927 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2928 cmp r0, #0 @ is resolved entry null? 2929 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2930.LOP_SGET_CHAR_finish: @ field ptr in r0 2931 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2932 @ no-op @ acquiring load 2933 mov r2, rINST, lsr #8 @ r2<- AA 2934 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2935 SET_VREG(r1, r2) @ fp[AA]<- r1 2936 GET_INST_OPCODE(ip) @ extract opcode from rINST 2937 GOTO_OPCODE(ip) @ jump to next instruction 2938 2939 2940/* ------------------------------ */ 2941 .balign 64 2942.L_OP_SGET_SHORT: /* 0x66 */ 2943/* File: armv5te/OP_SGET_SHORT.S */ 2944/* File: armv5te/OP_SGET.S */ 2945 /* 2946 * General 32-bit SGET handler. 2947 * 2948 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2949 */ 2950 /* op vAA, field@BBBB */ 2951 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2952 FETCH(r1, 1) @ r1<- field ref BBBB 2953 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2954 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2955 cmp r0, #0 @ is resolved entry null? 2956 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 2957.LOP_SGET_SHORT_finish: @ field ptr in r0 2958 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2959 @ no-op @ acquiring load 2960 mov r2, rINST, lsr #8 @ r2<- AA 2961 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2962 SET_VREG(r1, r2) @ fp[AA]<- r1 2963 GET_INST_OPCODE(ip) @ extract opcode from rINST 2964 GOTO_OPCODE(ip) @ jump to next instruction 2965 2966 2967/* ------------------------------ */ 2968 .balign 64 2969.L_OP_SPUT: /* 0x67 */ 2970/* File: armv5te/OP_SPUT.S */ 2971 /* 2972 * General 32-bit SPUT handler. 2973 * 2974 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2975 */ 2976 /* op vAA, field@BBBB */ 2977 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2978 FETCH(r1, 1) @ r1<- field ref BBBB 2979 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2980 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2981 cmp r0, #0 @ is resolved entry null? 2982 beq .LOP_SPUT_resolve @ yes, do resolve 2983.LOP_SPUT_finish: @ field ptr in r0 2984 mov r2, rINST, lsr #8 @ r2<- AA 2985 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2986 GET_VREG(r1, r2) @ r1<- fp[AA] 2987 GET_INST_OPCODE(ip) @ extract opcode from rINST 2988 @ no-op @ releasing store 2989 str r1, [r0, #offStaticField_value] @ field<- vAA 2990 GOTO_OPCODE(ip) @ jump to next instruction 2991 2992/* ------------------------------ */ 2993 .balign 64 2994.L_OP_SPUT_WIDE: /* 0x68 */ 2995/* File: armv5te/OP_SPUT_WIDE.S */ 2996 /* 2997 * 64-bit SPUT handler. 2998 */ 2999 /* sput-wide vAA, field@BBBB */ 3000 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 3001 FETCH(r1, 1) @ r1<- field ref BBBB 3002 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 3003 mov r9, rINST, lsr #8 @ r9<- AA 3004 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 3005 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 3006 cmp r2, #0 @ is resolved entry null? 3007 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 3008.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9 3009 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3010 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 3011 GET_INST_OPCODE(r10) @ extract opcode from rINST 3012 .if 0 3013 add r2, r2, #offStaticField_value @ r2<- pointer to data 3014 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 3015 .else 3016 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 3017 .endif 3018 GOTO_OPCODE(r10) @ jump to next instruction 3019 3020/* ------------------------------ */ 3021 .balign 64 3022.L_OP_SPUT_OBJECT: /* 0x69 */ 3023/* File: armv5te/OP_SPUT_OBJECT.S */ 3024/* File: armv5te/OP_SPUT.S */ 3025 /* 3026 * General 32-bit SPUT handler. 3027 * 3028 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3029 */ 3030 /* op vAA, field@BBBB */ 3031 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3032 FETCH(r1, 1) @ r1<- field ref BBBB 3033 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3034 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3035 cmp r0, #0 @ is resolved entry null? 3036 beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve 3037.LOP_SPUT_OBJECT_finish: @ field ptr in r0 3038 mov r2, rINST, lsr #8 @ r2<- AA 3039 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3040 GET_VREG(r1, r2) @ r1<- fp[AA] 3041 GET_INST_OPCODE(ip) @ extract opcode from rINST 3042 @ no-op @ releasing store 3043 str r1, [r0, #offStaticField_value] @ field<- vAA 3044 GOTO_OPCODE(ip) @ jump to next instruction 3045 3046 3047/* ------------------------------ */ 3048 .balign 64 3049.L_OP_SPUT_BOOLEAN: /* 0x6a */ 3050/* File: armv5te/OP_SPUT_BOOLEAN.S */ 3051/* File: armv5te/OP_SPUT.S */ 3052 /* 3053 * General 32-bit SPUT handler. 3054 * 3055 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3056 */ 3057 /* op vAA, field@BBBB */ 3058 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3059 FETCH(r1, 1) @ r1<- field ref BBBB 3060 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3061 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3062 cmp r0, #0 @ is resolved entry null? 3063 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 3064.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 3065 mov r2, rINST, lsr #8 @ r2<- AA 3066 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3067 GET_VREG(r1, r2) @ r1<- fp[AA] 3068 GET_INST_OPCODE(ip) @ extract opcode from rINST 3069 @ no-op @ releasing store 3070 str r1, [r0, #offStaticField_value] @ field<- vAA 3071 GOTO_OPCODE(ip) @ jump to next instruction 3072 3073 3074/* ------------------------------ */ 3075 .balign 64 3076.L_OP_SPUT_BYTE: /* 0x6b */ 3077/* File: armv5te/OP_SPUT_BYTE.S */ 3078/* File: armv5te/OP_SPUT.S */ 3079 /* 3080 * General 32-bit SPUT handler. 3081 * 3082 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3083 */ 3084 /* op vAA, field@BBBB */ 3085 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3086 FETCH(r1, 1) @ r1<- field ref BBBB 3087 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3088 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3089 cmp r0, #0 @ is resolved entry null? 3090 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 3091.LOP_SPUT_BYTE_finish: @ field ptr in r0 3092 mov r2, rINST, lsr #8 @ r2<- AA 3093 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3094 GET_VREG(r1, r2) @ r1<- fp[AA] 3095 GET_INST_OPCODE(ip) @ extract opcode from rINST 3096 @ no-op @ releasing store 3097 str r1, [r0, #offStaticField_value] @ field<- vAA 3098 GOTO_OPCODE(ip) @ jump to next instruction 3099 3100 3101/* ------------------------------ */ 3102 .balign 64 3103.L_OP_SPUT_CHAR: /* 0x6c */ 3104/* File: armv5te/OP_SPUT_CHAR.S */ 3105/* File: armv5te/OP_SPUT.S */ 3106 /* 3107 * General 32-bit SPUT handler. 3108 * 3109 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3110 */ 3111 /* op vAA, field@BBBB */ 3112 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3113 FETCH(r1, 1) @ r1<- field ref BBBB 3114 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3115 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3116 cmp r0, #0 @ is resolved entry null? 3117 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 3118.LOP_SPUT_CHAR_finish: @ field ptr in r0 3119 mov r2, rINST, lsr #8 @ r2<- AA 3120 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3121 GET_VREG(r1, r2) @ r1<- fp[AA] 3122 GET_INST_OPCODE(ip) @ extract opcode from rINST 3123 @ no-op @ releasing store 3124 str r1, [r0, #offStaticField_value] @ field<- vAA 3125 GOTO_OPCODE(ip) @ jump to next instruction 3126 3127 3128/* ------------------------------ */ 3129 .balign 64 3130.L_OP_SPUT_SHORT: /* 0x6d */ 3131/* File: armv5te/OP_SPUT_SHORT.S */ 3132/* File: armv5te/OP_SPUT.S */ 3133 /* 3134 * General 32-bit SPUT handler. 3135 * 3136 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3137 */ 3138 /* op vAA, field@BBBB */ 3139 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3140 FETCH(r1, 1) @ r1<- field ref BBBB 3141 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3142 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3143 cmp r0, #0 @ is resolved entry null? 3144 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 3145.LOP_SPUT_SHORT_finish: @ field ptr in r0 3146 mov r2, rINST, lsr #8 @ r2<- AA 3147 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3148 GET_VREG(r1, r2) @ r1<- fp[AA] 3149 GET_INST_OPCODE(ip) @ extract opcode from rINST 3150 @ no-op @ releasing store 3151 str r1, [r0, #offStaticField_value] @ field<- vAA 3152 GOTO_OPCODE(ip) @ jump to next instruction 3153 3154 3155/* ------------------------------ */ 3156 .balign 64 3157.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3158/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3159 /* 3160 * Handle a virtual method call. 3161 * 3162 * for: invoke-virtual, invoke-virtual/range 3163 */ 3164 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3165 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3166 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3167 FETCH(r1, 1) @ r1<- BBBB 3168 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3169 FETCH(r10, 2) @ r10<- GFED or CCCC 3170 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3171 .if (!0) 3172 and r10, r10, #15 @ r10<- D (or stays CCCC) 3173 .endif 3174 cmp r0, #0 @ already resolved? 3175 EXPORT_PC() @ must export for invoke 3176 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3177 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3178 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3179 mov r2, #METHOD_VIRTUAL @ resolver method type 3180 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3181 cmp r0, #0 @ got null? 3182 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3183 b common_exceptionThrown @ yes, handle exception 3184 3185/* ------------------------------ */ 3186 .balign 64 3187.L_OP_INVOKE_SUPER: /* 0x6f */ 3188/* File: armv5te/OP_INVOKE_SUPER.S */ 3189 /* 3190 * Handle a "super" method call. 3191 * 3192 * for: invoke-super, invoke-super/range 3193 */ 3194 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3195 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3196 FETCH(r10, 2) @ r10<- GFED or CCCC 3197 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3198 .if (!0) 3199 and r10, r10, #15 @ r10<- D (or stays CCCC) 3200 .endif 3201 FETCH(r1, 1) @ r1<- BBBB 3202 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3203 GET_VREG(r2, r10) @ r2<- "this" ptr 3204 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3205 cmp r2, #0 @ null "this"? 3206 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3207 beq common_errNullObject @ null "this", throw exception 3208 cmp r0, #0 @ already resolved? 3209 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3210 EXPORT_PC() @ must export for invoke 3211 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3212 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3213 3214/* ------------------------------ */ 3215 .balign 64 3216.L_OP_INVOKE_DIRECT: /* 0x70 */ 3217/* File: armv5te/OP_INVOKE_DIRECT.S */ 3218 /* 3219 * Handle a direct method call. 3220 * 3221 * (We could defer the "is 'this' pointer null" test to the common 3222 * method invocation code, and use a flag to indicate that static 3223 * calls don't count. If we do this as part of copying the arguments 3224 * out we could avoiding loading the first arg twice.) 3225 * 3226 * for: invoke-direct, invoke-direct/range 3227 */ 3228 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3229 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3230 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3231 FETCH(r1, 1) @ r1<- BBBB 3232 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3233 FETCH(r10, 2) @ r10<- GFED or CCCC 3234 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3235 .if (!0) 3236 and r10, r10, #15 @ r10<- D (or stays CCCC) 3237 .endif 3238 cmp r0, #0 @ already resolved? 3239 EXPORT_PC() @ must export for invoke 3240 GET_VREG(r2, r10) @ r2<- "this" ptr 3241 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3242.LOP_INVOKE_DIRECT_finish: 3243 cmp r2, #0 @ null "this" ref? 3244 bne common_invokeMethodNoRange @ no, continue on 3245 b common_errNullObject @ yes, throw exception 3246 3247/* ------------------------------ */ 3248 .balign 64 3249.L_OP_INVOKE_STATIC: /* 0x71 */ 3250/* File: armv5te/OP_INVOKE_STATIC.S */ 3251 /* 3252 * Handle a static method call. 3253 * 3254 * for: invoke-static, invoke-static/range 3255 */ 3256 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3257 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3258 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3259 FETCH(r1, 1) @ r1<- BBBB 3260 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3261 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3262 cmp r0, #0 @ already resolved? 3263 EXPORT_PC() @ must export for invoke 3264 bne common_invokeMethodNoRange @ yes, continue on 32650: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3266 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3267 mov r2, #METHOD_STATIC @ resolver method type 3268 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3269 cmp r0, #0 @ got null? 3270 bne common_invokeMethodNoRange @ no, continue 3271 b common_exceptionThrown @ yes, handle exception 3272 3273/* ------------------------------ */ 3274 .balign 64 3275.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3276/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3277 /* 3278 * Handle an interface method call. 3279 * 3280 * for: invoke-interface, invoke-interface/range 3281 */ 3282 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3283 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3284 FETCH(r2, 2) @ r2<- FEDC or CCCC 3285 FETCH(r1, 1) @ r1<- BBBB 3286 .if (!0) 3287 and r2, r2, #15 @ r2<- C (or stays CCCC) 3288 .endif 3289 EXPORT_PC() @ must export for invoke 3290 GET_VREG(r0, r2) @ r0<- first arg ("this") 3291 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3292 cmp r0, #0 @ null obj? 3293 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3294 beq common_errNullObject @ yes, fail 3295 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3296 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3297 cmp r0, #0 @ failed? 3298 beq common_exceptionThrown @ yes, handle exception 3299 b common_invokeMethodNoRange @ jump to common handler 3300 3301/* ------------------------------ */ 3302 .balign 64 3303.L_OP_UNUSED_73: /* 0x73 */ 3304/* File: armv5te/OP_UNUSED_73.S */ 3305/* File: armv5te/unused.S */ 3306 bl common_abort 3307 3308 3309/* ------------------------------ */ 3310 .balign 64 3311.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3312/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3313/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3314 /* 3315 * Handle a virtual method call. 3316 * 3317 * for: invoke-virtual, invoke-virtual/range 3318 */ 3319 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3320 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3321 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3322 FETCH(r1, 1) @ r1<- BBBB 3323 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3324 FETCH(r10, 2) @ r10<- GFED or CCCC 3325 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3326 .if (!1) 3327 and r10, r10, #15 @ r10<- D (or stays CCCC) 3328 .endif 3329 cmp r0, #0 @ already resolved? 3330 EXPORT_PC() @ must export for invoke 3331 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3332 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3333 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3334 mov r2, #METHOD_VIRTUAL @ resolver method type 3335 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3336 cmp r0, #0 @ got null? 3337 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3338 b common_exceptionThrown @ yes, handle exception 3339 3340 3341/* ------------------------------ */ 3342 .balign 64 3343.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3344/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3345/* File: armv5te/OP_INVOKE_SUPER.S */ 3346 /* 3347 * Handle a "super" method call. 3348 * 3349 * for: invoke-super, invoke-super/range 3350 */ 3351 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3352 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3353 FETCH(r10, 2) @ r10<- GFED or CCCC 3354 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3355 .if (!1) 3356 and r10, r10, #15 @ r10<- D (or stays CCCC) 3357 .endif 3358 FETCH(r1, 1) @ r1<- BBBB 3359 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3360 GET_VREG(r2, r10) @ r2<- "this" ptr 3361 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3362 cmp r2, #0 @ null "this"? 3363 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3364 beq common_errNullObject @ null "this", throw exception 3365 cmp r0, #0 @ already resolved? 3366 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3367 EXPORT_PC() @ must export for invoke 3368 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3369 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3370 3371 3372/* ------------------------------ */ 3373 .balign 64 3374.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3375/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3376/* File: armv5te/OP_INVOKE_DIRECT.S */ 3377 /* 3378 * Handle a direct method call. 3379 * 3380 * (We could defer the "is 'this' pointer null" test to the common 3381 * method invocation code, and use a flag to indicate that static 3382 * calls don't count. If we do this as part of copying the arguments 3383 * out we could avoiding loading the first arg twice.) 3384 * 3385 * for: invoke-direct, invoke-direct/range 3386 */ 3387 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3388 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3389 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3390 FETCH(r1, 1) @ r1<- BBBB 3391 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3392 FETCH(r10, 2) @ r10<- GFED or CCCC 3393 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3394 .if (!1) 3395 and r10, r10, #15 @ r10<- D (or stays CCCC) 3396 .endif 3397 cmp r0, #0 @ already resolved? 3398 EXPORT_PC() @ must export for invoke 3399 GET_VREG(r2, r10) @ r2<- "this" ptr 3400 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3401.LOP_INVOKE_DIRECT_RANGE_finish: 3402 cmp r2, #0 @ null "this" ref? 3403 bne common_invokeMethodRange @ no, continue on 3404 b common_errNullObject @ yes, throw exception 3405 3406 3407/* ------------------------------ */ 3408 .balign 64 3409.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3410/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3411/* File: armv5te/OP_INVOKE_STATIC.S */ 3412 /* 3413 * Handle a static method call. 3414 * 3415 * for: invoke-static, invoke-static/range 3416 */ 3417 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3418 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3419 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3420 FETCH(r1, 1) @ r1<- BBBB 3421 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3422 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3423 cmp r0, #0 @ already resolved? 3424 EXPORT_PC() @ must export for invoke 3425 bne common_invokeMethodRange @ yes, continue on 34260: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3427 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3428 mov r2, #METHOD_STATIC @ resolver method type 3429 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3430 cmp r0, #0 @ got null? 3431 bne common_invokeMethodRange @ no, continue 3432 b common_exceptionThrown @ yes, handle exception 3433 3434 3435/* ------------------------------ */ 3436 .balign 64 3437.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3438/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3439/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3440 /* 3441 * Handle an interface method call. 3442 * 3443 * for: invoke-interface, invoke-interface/range 3444 */ 3445 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3446 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3447 FETCH(r2, 2) @ r2<- FEDC or CCCC 3448 FETCH(r1, 1) @ r1<- BBBB 3449 .if (!1) 3450 and r2, r2, #15 @ r2<- C (or stays CCCC) 3451 .endif 3452 EXPORT_PC() @ must export for invoke 3453 GET_VREG(r0, r2) @ r0<- first arg ("this") 3454 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3455 cmp r0, #0 @ null obj? 3456 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3457 beq common_errNullObject @ yes, fail 3458 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3459 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3460 cmp r0, #0 @ failed? 3461 beq common_exceptionThrown @ yes, handle exception 3462 b common_invokeMethodRange @ jump to common handler 3463 3464 3465/* ------------------------------ */ 3466 .balign 64 3467.L_OP_UNUSED_79: /* 0x79 */ 3468/* File: armv5te/OP_UNUSED_79.S */ 3469/* File: armv5te/unused.S */ 3470 bl common_abort 3471 3472 3473/* ------------------------------ */ 3474 .balign 64 3475.L_OP_UNUSED_7A: /* 0x7a */ 3476/* File: armv5te/OP_UNUSED_7A.S */ 3477/* File: armv5te/unused.S */ 3478 bl common_abort 3479 3480 3481/* ------------------------------ */ 3482 .balign 64 3483.L_OP_NEG_INT: /* 0x7b */ 3484/* File: armv6t2/OP_NEG_INT.S */ 3485/* File: armv6t2/unop.S */ 3486 /* 3487 * Generic 32-bit unary operation. Provide an "instr" line that 3488 * specifies an instruction that performs "result = op r0". 3489 * This could be an ARM instruction or a function call. 3490 * 3491 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3492 * int-to-byte, int-to-char, int-to-short 3493 */ 3494 /* unop vA, vB */ 3495 mov r3, rINST, lsr #12 @ r3<- B 3496 ubfx r9, rINST, #8, #4 @ r9<- A 3497 GET_VREG(r0, r3) @ r0<- vB 3498 @ optional op; may set condition codes 3499 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3500 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3501 GET_INST_OPCODE(ip) @ extract opcode from rINST 3502 SET_VREG(r0, r9) @ vAA<- r0 3503 GOTO_OPCODE(ip) @ jump to next instruction 3504 /* 8-9 instructions */ 3505 3506 3507/* ------------------------------ */ 3508 .balign 64 3509.L_OP_NOT_INT: /* 0x7c */ 3510/* File: armv6t2/OP_NOT_INT.S */ 3511/* File: armv6t2/unop.S */ 3512 /* 3513 * Generic 32-bit unary operation. Provide an "instr" line that 3514 * specifies an instruction that performs "result = op r0". 3515 * This could be an ARM instruction or a function call. 3516 * 3517 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3518 * int-to-byte, int-to-char, int-to-short 3519 */ 3520 /* unop vA, vB */ 3521 mov r3, rINST, lsr #12 @ r3<- B 3522 ubfx r9, rINST, #8, #4 @ r9<- A 3523 GET_VREG(r0, r3) @ r0<- vB 3524 @ optional op; may set condition codes 3525 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3526 mvn r0, r0 @ r0<- op, r0-r3 changed 3527 GET_INST_OPCODE(ip) @ extract opcode from rINST 3528 SET_VREG(r0, r9) @ vAA<- r0 3529 GOTO_OPCODE(ip) @ jump to next instruction 3530 /* 8-9 instructions */ 3531 3532 3533/* ------------------------------ */ 3534 .balign 64 3535.L_OP_NEG_LONG: /* 0x7d */ 3536/* File: armv6t2/OP_NEG_LONG.S */ 3537/* File: armv6t2/unopWide.S */ 3538 /* 3539 * Generic 64-bit unary operation. Provide an "instr" line that 3540 * specifies an instruction that performs "result = op r0/r1". 3541 * This could be an ARM instruction or a function call. 3542 * 3543 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3544 */ 3545 /* unop vA, vB */ 3546 mov r3, rINST, lsr #12 @ r3<- B 3547 ubfx r9, rINST, #8, #4 @ r9<- A 3548 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3549 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3550 ldmia r3, {r0-r1} @ r0/r1<- vAA 3551 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3552 rsbs r0, r0, #0 @ optional op; may set condition codes 3553 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3554 GET_INST_OPCODE(ip) @ extract opcode from rINST 3555 stmia r9, {r0-r1} @ vAA<- r0/r1 3556 GOTO_OPCODE(ip) @ jump to next instruction 3557 /* 10-11 instructions */ 3558 3559 3560/* ------------------------------ */ 3561 .balign 64 3562.L_OP_NOT_LONG: /* 0x7e */ 3563/* File: armv6t2/OP_NOT_LONG.S */ 3564/* File: armv6t2/unopWide.S */ 3565 /* 3566 * Generic 64-bit unary operation. Provide an "instr" line that 3567 * specifies an instruction that performs "result = op r0/r1". 3568 * This could be an ARM instruction or a function call. 3569 * 3570 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3571 */ 3572 /* unop vA, vB */ 3573 mov r3, rINST, lsr #12 @ r3<- B 3574 ubfx r9, rINST, #8, #4 @ r9<- A 3575 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3576 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3577 ldmia r3, {r0-r1} @ r0/r1<- vAA 3578 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3579 mvn r0, r0 @ optional op; may set condition codes 3580 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3581 GET_INST_OPCODE(ip) @ extract opcode from rINST 3582 stmia r9, {r0-r1} @ vAA<- r0/r1 3583 GOTO_OPCODE(ip) @ jump to next instruction 3584 /* 10-11 instructions */ 3585 3586 3587/* ------------------------------ */ 3588 .balign 64 3589.L_OP_NEG_FLOAT: /* 0x7f */ 3590/* File: armv6t2/OP_NEG_FLOAT.S */ 3591/* File: armv6t2/unop.S */ 3592 /* 3593 * Generic 32-bit unary operation. Provide an "instr" line that 3594 * specifies an instruction that performs "result = op r0". 3595 * This could be an ARM instruction or a function call. 3596 * 3597 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3598 * int-to-byte, int-to-char, int-to-short 3599 */ 3600 /* unop vA, vB */ 3601 mov r3, rINST, lsr #12 @ r3<- B 3602 ubfx r9, rINST, #8, #4 @ r9<- A 3603 GET_VREG(r0, r3) @ r0<- vB 3604 @ optional op; may set condition codes 3605 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3606 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3607 GET_INST_OPCODE(ip) @ extract opcode from rINST 3608 SET_VREG(r0, r9) @ vAA<- r0 3609 GOTO_OPCODE(ip) @ jump to next instruction 3610 /* 8-9 instructions */ 3611 3612 3613/* ------------------------------ */ 3614 .balign 64 3615.L_OP_NEG_DOUBLE: /* 0x80 */ 3616/* File: armv6t2/OP_NEG_DOUBLE.S */ 3617/* File: armv6t2/unopWide.S */ 3618 /* 3619 * Generic 64-bit unary operation. Provide an "instr" line that 3620 * specifies an instruction that performs "result = op r0/r1". 3621 * This could be an ARM instruction or a function call. 3622 * 3623 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3624 */ 3625 /* unop vA, vB */ 3626 mov r3, rINST, lsr #12 @ r3<- B 3627 ubfx r9, rINST, #8, #4 @ r9<- A 3628 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3629 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3630 ldmia r3, {r0-r1} @ r0/r1<- vAA 3631 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3632 @ optional op; may set condition codes 3633 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3634 GET_INST_OPCODE(ip) @ extract opcode from rINST 3635 stmia r9, {r0-r1} @ vAA<- r0/r1 3636 GOTO_OPCODE(ip) @ jump to next instruction 3637 /* 10-11 instructions */ 3638 3639 3640/* ------------------------------ */ 3641 .balign 64 3642.L_OP_INT_TO_LONG: /* 0x81 */ 3643/* File: armv6t2/OP_INT_TO_LONG.S */ 3644/* File: armv6t2/unopWider.S */ 3645 /* 3646 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3647 * that specifies an instruction that performs "result = op r0", where 3648 * "result" is a 64-bit quantity in r0/r1. 3649 * 3650 * For: int-to-long, int-to-double, float-to-long, float-to-double 3651 */ 3652 /* unop vA, vB */ 3653 mov r3, rINST, lsr #12 @ r3<- B 3654 ubfx r9, rINST, #8, #4 @ r9<- A 3655 GET_VREG(r0, r3) @ r0<- vB 3656 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3657 @ optional op; may set condition codes 3658 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3659 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3660 GET_INST_OPCODE(ip) @ extract opcode from rINST 3661 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3662 GOTO_OPCODE(ip) @ jump to next instruction 3663 /* 9-10 instructions */ 3664 3665 3666/* ------------------------------ */ 3667 .balign 64 3668.L_OP_INT_TO_FLOAT: /* 0x82 */ 3669/* File: arm-vfp/OP_INT_TO_FLOAT.S */ 3670/* File: arm-vfp/funop.S */ 3671 /* 3672 * Generic 32-bit unary floating-point operation. Provide an "instr" 3673 * line that specifies an instruction that performs "s1 = op s0". 3674 * 3675 * for: int-to-float, float-to-int 3676 */ 3677 /* unop vA, vB */ 3678 mov r3, rINST, lsr #12 @ r3<- B 3679 mov r9, rINST, lsr #8 @ r9<- A+ 3680 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3681 flds s0, [r3] @ s0<- vB 3682 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3683 and r9, r9, #15 @ r9<- A 3684 fsitos s1, s0 @ s1<- op 3685 GET_INST_OPCODE(ip) @ extract opcode from rINST 3686 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3687 fsts s1, [r9] @ vA<- s1 3688 GOTO_OPCODE(ip) @ jump to next instruction 3689 3690 3691/* ------------------------------ */ 3692 .balign 64 3693.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3694/* File: arm-vfp/OP_INT_TO_DOUBLE.S */ 3695/* File: arm-vfp/funopWider.S */ 3696 /* 3697 * Generic 32bit-to-64bit floating point unary operation. Provide an 3698 * "instr" line that specifies an instruction that performs "d0 = op s0". 3699 * 3700 * For: int-to-double, float-to-double 3701 */ 3702 /* unop vA, vB */ 3703 mov r3, rINST, lsr #12 @ r3<- B 3704 mov r9, rINST, lsr #8 @ r9<- A+ 3705 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3706 flds s0, [r3] @ s0<- vB 3707 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3708 and r9, r9, #15 @ r9<- A 3709 fsitod d0, s0 @ d0<- op 3710 GET_INST_OPCODE(ip) @ extract opcode from rINST 3711 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3712 fstd d0, [r9] @ vA<- d0 3713 GOTO_OPCODE(ip) @ jump to next instruction 3714 3715 3716/* ------------------------------ */ 3717 .balign 64 3718.L_OP_LONG_TO_INT: /* 0x84 */ 3719/* File: armv5te/OP_LONG_TO_INT.S */ 3720/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3721/* File: armv5te/OP_MOVE.S */ 3722 /* for move, move-object, long-to-int */ 3723 /* op vA, vB */ 3724 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3725 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3726 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3727 GET_VREG(r2, r1) @ r2<- fp[B] 3728 and r0, r0, #15 3729 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3730 SET_VREG(r2, r0) @ fp[A]<- r2 3731 GOTO_OPCODE(ip) @ execute next instruction 3732 3733 3734/* ------------------------------ */ 3735 .balign 64 3736.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3737/* File: armv6t2/OP_LONG_TO_FLOAT.S */ 3738/* File: armv6t2/unopNarrower.S */ 3739 /* 3740 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3741 * that specifies an instruction that performs "result = op r0/r1", where 3742 * "result" is a 32-bit quantity in r0. 3743 * 3744 * For: long-to-float, double-to-int, double-to-float 3745 * 3746 * (This would work for long-to-int, but that instruction is actually 3747 * an exact match for OP_MOVE.) 3748 */ 3749 /* unop vA, vB */ 3750 mov r3, rINST, lsr #12 @ r3<- B 3751 ubfx r9, rINST, #8, #4 @ r9<- A 3752 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3753 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3754 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3755 @ optional op; may set condition codes 3756 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3757 GET_INST_OPCODE(ip) @ extract opcode from rINST 3758 SET_VREG(r0, r9) @ vA<- r0 3759 GOTO_OPCODE(ip) @ jump to next instruction 3760 /* 9-10 instructions */ 3761 3762 3763/* ------------------------------ */ 3764 .balign 64 3765.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3766/* File: armv6t2/OP_LONG_TO_DOUBLE.S */ 3767/* File: armv6t2/unopWide.S */ 3768 /* 3769 * Generic 64-bit unary operation. Provide an "instr" line that 3770 * specifies an instruction that performs "result = op r0/r1". 3771 * This could be an ARM instruction or a function call. 3772 * 3773 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3774 */ 3775 /* unop vA, vB */ 3776 mov r3, rINST, lsr #12 @ r3<- B 3777 ubfx r9, rINST, #8, #4 @ r9<- A 3778 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3779 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3780 ldmia r3, {r0-r1} @ r0/r1<- vAA 3781 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3782 @ optional op; may set condition codes 3783 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3784 GET_INST_OPCODE(ip) @ extract opcode from rINST 3785 stmia r9, {r0-r1} @ vAA<- r0/r1 3786 GOTO_OPCODE(ip) @ jump to next instruction 3787 /* 10-11 instructions */ 3788 3789 3790/* ------------------------------ */ 3791 .balign 64 3792.L_OP_FLOAT_TO_INT: /* 0x87 */ 3793/* File: arm-vfp/OP_FLOAT_TO_INT.S */ 3794/* File: arm-vfp/funop.S */ 3795 /* 3796 * Generic 32-bit unary floating-point operation. Provide an "instr" 3797 * line that specifies an instruction that performs "s1 = op s0". 3798 * 3799 * for: int-to-float, float-to-int 3800 */ 3801 /* unop vA, vB */ 3802 mov r3, rINST, lsr #12 @ r3<- B 3803 mov r9, rINST, lsr #8 @ r9<- A+ 3804 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3805 flds s0, [r3] @ s0<- vB 3806 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3807 and r9, r9, #15 @ r9<- A 3808 ftosizs s1, s0 @ s1<- op 3809 GET_INST_OPCODE(ip) @ extract opcode from rINST 3810 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3811 fsts s1, [r9] @ vA<- s1 3812 GOTO_OPCODE(ip) @ jump to next instruction 3813 3814 3815/* ------------------------------ */ 3816 .balign 64 3817.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3818/* File: armv6t2/OP_FLOAT_TO_LONG.S */ 3819@include "armv6t2/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3820/* File: armv6t2/unopWider.S */ 3821 /* 3822 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3823 * that specifies an instruction that performs "result = op r0", where 3824 * "result" is a 64-bit quantity in r0/r1. 3825 * 3826 * For: int-to-long, int-to-double, float-to-long, float-to-double 3827 */ 3828 /* unop vA, vB */ 3829 mov r3, rINST, lsr #12 @ r3<- B 3830 ubfx r9, rINST, #8, #4 @ r9<- A 3831 GET_VREG(r0, r3) @ r0<- vB 3832 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3833 @ optional op; may set condition codes 3834 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3835 bl f2l_doconv @ r0<- op, r0-r3 changed 3836 GET_INST_OPCODE(ip) @ extract opcode from rINST 3837 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3838 GOTO_OPCODE(ip) @ jump to next instruction 3839 /* 9-10 instructions */ 3840 3841 3842 3843/* ------------------------------ */ 3844 .balign 64 3845.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3846/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */ 3847/* File: arm-vfp/funopWider.S */ 3848 /* 3849 * Generic 32bit-to-64bit floating point unary operation. Provide an 3850 * "instr" line that specifies an instruction that performs "d0 = op s0". 3851 * 3852 * For: int-to-double, float-to-double 3853 */ 3854 /* unop vA, vB */ 3855 mov r3, rINST, lsr #12 @ r3<- B 3856 mov r9, rINST, lsr #8 @ r9<- A+ 3857 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3858 flds s0, [r3] @ s0<- vB 3859 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3860 and r9, r9, #15 @ r9<- A 3861 fcvtds d0, s0 @ d0<- op 3862 GET_INST_OPCODE(ip) @ extract opcode from rINST 3863 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3864 fstd d0, [r9] @ vA<- d0 3865 GOTO_OPCODE(ip) @ jump to next instruction 3866 3867 3868/* ------------------------------ */ 3869 .balign 64 3870.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3871/* File: arm-vfp/OP_DOUBLE_TO_INT.S */ 3872/* File: arm-vfp/funopNarrower.S */ 3873 /* 3874 * Generic 64bit-to-32bit unary floating point operation. Provide an 3875 * "instr" line that specifies an instruction that performs "s0 = op d0". 3876 * 3877 * For: double-to-int, double-to-float 3878 */ 3879 /* unop vA, vB */ 3880 mov r3, rINST, lsr #12 @ r3<- B 3881 mov r9, rINST, lsr #8 @ r9<- A+ 3882 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3883 fldd d0, [r3] @ d0<- vB 3884 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3885 and r9, r9, #15 @ r9<- A 3886 ftosizd s0, d0 @ s0<- op 3887 GET_INST_OPCODE(ip) @ extract opcode from rINST 3888 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3889 fsts s0, [r9] @ vA<- s0 3890 GOTO_OPCODE(ip) @ jump to next instruction 3891 3892 3893/* ------------------------------ */ 3894 .balign 64 3895.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3896/* File: armv6t2/OP_DOUBLE_TO_LONG.S */ 3897@include "armv6t2/unopWide.S" {"instr":"bl __aeabi_d2lz"} 3898/* File: armv6t2/unopWide.S */ 3899 /* 3900 * Generic 64-bit unary operation. Provide an "instr" line that 3901 * specifies an instruction that performs "result = op r0/r1". 3902 * This could be an ARM instruction or a function call. 3903 * 3904 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3905 */ 3906 /* unop vA, vB */ 3907 mov r3, rINST, lsr #12 @ r3<- B 3908 ubfx r9, rINST, #8, #4 @ r9<- A 3909 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3910 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3911 ldmia r3, {r0-r1} @ r0/r1<- vAA 3912 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3913 @ optional op; may set condition codes 3914 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 3915 GET_INST_OPCODE(ip) @ extract opcode from rINST 3916 stmia r9, {r0-r1} @ vAA<- r0/r1 3917 GOTO_OPCODE(ip) @ jump to next instruction 3918 /* 10-11 instructions */ 3919 3920 3921 3922/* ------------------------------ */ 3923 .balign 64 3924.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3925/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */ 3926/* File: arm-vfp/funopNarrower.S */ 3927 /* 3928 * Generic 64bit-to-32bit unary floating point operation. Provide an 3929 * "instr" line that specifies an instruction that performs "s0 = op d0". 3930 * 3931 * For: double-to-int, double-to-float 3932 */ 3933 /* unop vA, vB */ 3934 mov r3, rINST, lsr #12 @ r3<- B 3935 mov r9, rINST, lsr #8 @ r9<- A+ 3936 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3937 fldd d0, [r3] @ d0<- vB 3938 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3939 and r9, r9, #15 @ r9<- A 3940 fcvtsd s0, d0 @ s0<- op 3941 GET_INST_OPCODE(ip) @ extract opcode from rINST 3942 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3943 fsts s0, [r9] @ vA<- s0 3944 GOTO_OPCODE(ip) @ jump to next instruction 3945 3946 3947/* ------------------------------ */ 3948 .balign 64 3949.L_OP_INT_TO_BYTE: /* 0x8d */ 3950/* File: armv6t2/OP_INT_TO_BYTE.S */ 3951/* File: armv6t2/unop.S */ 3952 /* 3953 * Generic 32-bit unary operation. Provide an "instr" line that 3954 * specifies an instruction that performs "result = op r0". 3955 * This could be an ARM instruction or a function call. 3956 * 3957 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3958 * int-to-byte, int-to-char, int-to-short 3959 */ 3960 /* unop vA, vB */ 3961 mov r3, rINST, lsr #12 @ r3<- B 3962 ubfx r9, rINST, #8, #4 @ r9<- A 3963 GET_VREG(r0, r3) @ r0<- vB 3964 @ optional op; may set condition codes 3965 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3966 sxtb r0, r0 @ r0<- op, r0-r3 changed 3967 GET_INST_OPCODE(ip) @ extract opcode from rINST 3968 SET_VREG(r0, r9) @ vAA<- r0 3969 GOTO_OPCODE(ip) @ jump to next instruction 3970 /* 8-9 instructions */ 3971 3972 3973/* ------------------------------ */ 3974 .balign 64 3975.L_OP_INT_TO_CHAR: /* 0x8e */ 3976/* File: armv6t2/OP_INT_TO_CHAR.S */ 3977/* File: armv6t2/unop.S */ 3978 /* 3979 * Generic 32-bit unary operation. Provide an "instr" line that 3980 * specifies an instruction that performs "result = op r0". 3981 * This could be an ARM instruction or a function call. 3982 * 3983 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3984 * int-to-byte, int-to-char, int-to-short 3985 */ 3986 /* unop vA, vB */ 3987 mov r3, rINST, lsr #12 @ r3<- B 3988 ubfx r9, rINST, #8, #4 @ r9<- A 3989 GET_VREG(r0, r3) @ r0<- vB 3990 @ optional op; may set condition codes 3991 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3992 uxth r0, r0 @ r0<- op, r0-r3 changed 3993 GET_INST_OPCODE(ip) @ extract opcode from rINST 3994 SET_VREG(r0, r9) @ vAA<- r0 3995 GOTO_OPCODE(ip) @ jump to next instruction 3996 /* 8-9 instructions */ 3997 3998 3999/* ------------------------------ */ 4000 .balign 64 4001.L_OP_INT_TO_SHORT: /* 0x8f */ 4002/* File: armv6t2/OP_INT_TO_SHORT.S */ 4003/* File: armv6t2/unop.S */ 4004 /* 4005 * Generic 32-bit unary operation. Provide an "instr" line that 4006 * specifies an instruction that performs "result = op r0". 4007 * This could be an ARM instruction or a function call. 4008 * 4009 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4010 * int-to-byte, int-to-char, int-to-short 4011 */ 4012 /* unop vA, vB */ 4013 mov r3, rINST, lsr #12 @ r3<- B 4014 ubfx r9, rINST, #8, #4 @ r9<- A 4015 GET_VREG(r0, r3) @ r0<- vB 4016 @ optional op; may set condition codes 4017 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4018 sxth r0, r0 @ r0<- op, r0-r3 changed 4019 GET_INST_OPCODE(ip) @ extract opcode from rINST 4020 SET_VREG(r0, r9) @ vAA<- r0 4021 GOTO_OPCODE(ip) @ jump to next instruction 4022 /* 8-9 instructions */ 4023 4024 4025/* ------------------------------ */ 4026 .balign 64 4027.L_OP_ADD_INT: /* 0x90 */ 4028/* File: armv5te/OP_ADD_INT.S */ 4029/* File: armv5te/binop.S */ 4030 /* 4031 * Generic 32-bit binary operation. Provide an "instr" line that 4032 * specifies an instruction that performs "result = r0 op r1". 4033 * This could be an ARM instruction or a function call. (If the result 4034 * comes back in a register other than r0, you can override "result".) 4035 * 4036 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4037 * vCC (r1). Useful for integer division and modulus. Note that we 4038 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4039 * handles it correctly. 4040 * 4041 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4042 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4043 * mul-float, div-float, rem-float 4044 */ 4045 /* binop vAA, vBB, vCC */ 4046 FETCH(r0, 1) @ r0<- CCBB 4047 mov r9, rINST, lsr #8 @ r9<- AA 4048 mov r3, r0, lsr #8 @ r3<- CC 4049 and r2, r0, #255 @ r2<- BB 4050 GET_VREG(r1, r3) @ r1<- vCC 4051 GET_VREG(r0, r2) @ r0<- vBB 4052 .if 0 4053 cmp r1, #0 @ is second operand zero? 4054 beq common_errDivideByZero 4055 .endif 4056 4057 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4058 @ optional op; may set condition codes 4059 add r0, r0, r1 @ r0<- op, r0-r3 changed 4060 GET_INST_OPCODE(ip) @ extract opcode from rINST 4061 SET_VREG(r0, r9) @ vAA<- r0 4062 GOTO_OPCODE(ip) @ jump to next instruction 4063 /* 11-14 instructions */ 4064 4065 4066/* ------------------------------ */ 4067 .balign 64 4068.L_OP_SUB_INT: /* 0x91 */ 4069/* File: armv5te/OP_SUB_INT.S */ 4070/* File: armv5te/binop.S */ 4071 /* 4072 * Generic 32-bit binary operation. Provide an "instr" line that 4073 * specifies an instruction that performs "result = r0 op r1". 4074 * This could be an ARM instruction or a function call. (If the result 4075 * comes back in a register other than r0, you can override "result".) 4076 * 4077 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4078 * vCC (r1). Useful for integer division and modulus. Note that we 4079 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4080 * handles it correctly. 4081 * 4082 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4083 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4084 * mul-float, div-float, rem-float 4085 */ 4086 /* binop vAA, vBB, vCC */ 4087 FETCH(r0, 1) @ r0<- CCBB 4088 mov r9, rINST, lsr #8 @ r9<- AA 4089 mov r3, r0, lsr #8 @ r3<- CC 4090 and r2, r0, #255 @ r2<- BB 4091 GET_VREG(r1, r3) @ r1<- vCC 4092 GET_VREG(r0, r2) @ r0<- vBB 4093 .if 0 4094 cmp r1, #0 @ is second operand zero? 4095 beq common_errDivideByZero 4096 .endif 4097 4098 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4099 @ optional op; may set condition codes 4100 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4101 GET_INST_OPCODE(ip) @ extract opcode from rINST 4102 SET_VREG(r0, r9) @ vAA<- r0 4103 GOTO_OPCODE(ip) @ jump to next instruction 4104 /* 11-14 instructions */ 4105 4106 4107/* ------------------------------ */ 4108 .balign 64 4109.L_OP_MUL_INT: /* 0x92 */ 4110/* File: armv5te/OP_MUL_INT.S */ 4111/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4112/* File: armv5te/binop.S */ 4113 /* 4114 * Generic 32-bit binary operation. Provide an "instr" line that 4115 * specifies an instruction that performs "result = r0 op r1". 4116 * This could be an ARM instruction or a function call. (If the result 4117 * comes back in a register other than r0, you can override "result".) 4118 * 4119 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4120 * vCC (r1). Useful for integer division and modulus. Note that we 4121 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4122 * handles it correctly. 4123 * 4124 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4125 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4126 * mul-float, div-float, rem-float 4127 */ 4128 /* binop vAA, vBB, vCC */ 4129 FETCH(r0, 1) @ r0<- CCBB 4130 mov r9, rINST, lsr #8 @ r9<- AA 4131 mov r3, r0, lsr #8 @ r3<- CC 4132 and r2, r0, #255 @ r2<- BB 4133 GET_VREG(r1, r3) @ r1<- vCC 4134 GET_VREG(r0, r2) @ r0<- vBB 4135 .if 0 4136 cmp r1, #0 @ is second operand zero? 4137 beq common_errDivideByZero 4138 .endif 4139 4140 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4141 @ optional op; may set condition codes 4142 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4143 GET_INST_OPCODE(ip) @ extract opcode from rINST 4144 SET_VREG(r0, r9) @ vAA<- r0 4145 GOTO_OPCODE(ip) @ jump to next instruction 4146 /* 11-14 instructions */ 4147 4148 4149/* ------------------------------ */ 4150 .balign 64 4151.L_OP_DIV_INT: /* 0x93 */ 4152/* File: armv5te/OP_DIV_INT.S */ 4153/* File: armv5te/binop.S */ 4154 /* 4155 * Generic 32-bit binary operation. Provide an "instr" line that 4156 * specifies an instruction that performs "result = r0 op r1". 4157 * This could be an ARM instruction or a function call. (If the result 4158 * comes back in a register other than r0, you can override "result".) 4159 * 4160 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4161 * vCC (r1). Useful for integer division and modulus. Note that we 4162 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4163 * handles it correctly. 4164 * 4165 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4166 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4167 * mul-float, div-float, rem-float 4168 */ 4169 /* binop vAA, vBB, vCC */ 4170 FETCH(r0, 1) @ r0<- CCBB 4171 mov r9, rINST, lsr #8 @ r9<- AA 4172 mov r3, r0, lsr #8 @ r3<- CC 4173 and r2, r0, #255 @ r2<- BB 4174 GET_VREG(r1, r3) @ r1<- vCC 4175 GET_VREG(r0, r2) @ r0<- vBB 4176 .if 1 4177 cmp r1, #0 @ is second operand zero? 4178 beq common_errDivideByZero 4179 .endif 4180 4181 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4182 @ optional op; may set condition codes 4183 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4184 GET_INST_OPCODE(ip) @ extract opcode from rINST 4185 SET_VREG(r0, r9) @ vAA<- r0 4186 GOTO_OPCODE(ip) @ jump to next instruction 4187 /* 11-14 instructions */ 4188 4189 4190/* ------------------------------ */ 4191 .balign 64 4192.L_OP_REM_INT: /* 0x94 */ 4193/* File: armv5te/OP_REM_INT.S */ 4194/* idivmod returns quotient in r0 and remainder in r1 */ 4195/* File: armv5te/binop.S */ 4196 /* 4197 * Generic 32-bit binary operation. Provide an "instr" line that 4198 * specifies an instruction that performs "result = r0 op r1". 4199 * This could be an ARM instruction or a function call. (If the result 4200 * comes back in a register other than r0, you can override "result".) 4201 * 4202 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4203 * vCC (r1). Useful for integer division and modulus. Note that we 4204 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4205 * handles it correctly. 4206 * 4207 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4208 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4209 * mul-float, div-float, rem-float 4210 */ 4211 /* binop vAA, vBB, vCC */ 4212 FETCH(r0, 1) @ r0<- CCBB 4213 mov r9, rINST, lsr #8 @ r9<- AA 4214 mov r3, r0, lsr #8 @ r3<- CC 4215 and r2, r0, #255 @ r2<- BB 4216 GET_VREG(r1, r3) @ r1<- vCC 4217 GET_VREG(r0, r2) @ r0<- vBB 4218 .if 1 4219 cmp r1, #0 @ is second operand zero? 4220 beq common_errDivideByZero 4221 .endif 4222 4223 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4224 @ optional op; may set condition codes 4225 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4226 GET_INST_OPCODE(ip) @ extract opcode from rINST 4227 SET_VREG(r1, r9) @ vAA<- r1 4228 GOTO_OPCODE(ip) @ jump to next instruction 4229 /* 11-14 instructions */ 4230 4231 4232/* ------------------------------ */ 4233 .balign 64 4234.L_OP_AND_INT: /* 0x95 */ 4235/* File: armv5te/OP_AND_INT.S */ 4236/* File: armv5te/binop.S */ 4237 /* 4238 * Generic 32-bit binary operation. Provide an "instr" line that 4239 * specifies an instruction that performs "result = r0 op r1". 4240 * This could be an ARM instruction or a function call. (If the result 4241 * comes back in a register other than r0, you can override "result".) 4242 * 4243 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4244 * vCC (r1). Useful for integer division and modulus. Note that we 4245 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4246 * handles it correctly. 4247 * 4248 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4249 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4250 * mul-float, div-float, rem-float 4251 */ 4252 /* binop vAA, vBB, vCC */ 4253 FETCH(r0, 1) @ r0<- CCBB 4254 mov r9, rINST, lsr #8 @ r9<- AA 4255 mov r3, r0, lsr #8 @ r3<- CC 4256 and r2, r0, #255 @ r2<- BB 4257 GET_VREG(r1, r3) @ r1<- vCC 4258 GET_VREG(r0, r2) @ r0<- vBB 4259 .if 0 4260 cmp r1, #0 @ is second operand zero? 4261 beq common_errDivideByZero 4262 .endif 4263 4264 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4265 @ optional op; may set condition codes 4266 and r0, r0, r1 @ r0<- op, r0-r3 changed 4267 GET_INST_OPCODE(ip) @ extract opcode from rINST 4268 SET_VREG(r0, r9) @ vAA<- r0 4269 GOTO_OPCODE(ip) @ jump to next instruction 4270 /* 11-14 instructions */ 4271 4272 4273/* ------------------------------ */ 4274 .balign 64 4275.L_OP_OR_INT: /* 0x96 */ 4276/* File: armv5te/OP_OR_INT.S */ 4277/* File: armv5te/binop.S */ 4278 /* 4279 * Generic 32-bit binary operation. Provide an "instr" line that 4280 * specifies an instruction that performs "result = r0 op r1". 4281 * This could be an ARM instruction or a function call. (If the result 4282 * comes back in a register other than r0, you can override "result".) 4283 * 4284 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4285 * vCC (r1). Useful for integer division and modulus. Note that we 4286 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4287 * handles it correctly. 4288 * 4289 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4290 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4291 * mul-float, div-float, rem-float 4292 */ 4293 /* binop vAA, vBB, vCC */ 4294 FETCH(r0, 1) @ r0<- CCBB 4295 mov r9, rINST, lsr #8 @ r9<- AA 4296 mov r3, r0, lsr #8 @ r3<- CC 4297 and r2, r0, #255 @ r2<- BB 4298 GET_VREG(r1, r3) @ r1<- vCC 4299 GET_VREG(r0, r2) @ r0<- vBB 4300 .if 0 4301 cmp r1, #0 @ is second operand zero? 4302 beq common_errDivideByZero 4303 .endif 4304 4305 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4306 @ optional op; may set condition codes 4307 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4308 GET_INST_OPCODE(ip) @ extract opcode from rINST 4309 SET_VREG(r0, r9) @ vAA<- r0 4310 GOTO_OPCODE(ip) @ jump to next instruction 4311 /* 11-14 instructions */ 4312 4313 4314/* ------------------------------ */ 4315 .balign 64 4316.L_OP_XOR_INT: /* 0x97 */ 4317/* File: armv5te/OP_XOR_INT.S */ 4318/* File: armv5te/binop.S */ 4319 /* 4320 * Generic 32-bit binary operation. Provide an "instr" line that 4321 * specifies an instruction that performs "result = r0 op r1". 4322 * This could be an ARM instruction or a function call. (If the result 4323 * comes back in a register other than r0, you can override "result".) 4324 * 4325 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4326 * vCC (r1). Useful for integer division and modulus. Note that we 4327 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4328 * handles it correctly. 4329 * 4330 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4331 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4332 * mul-float, div-float, rem-float 4333 */ 4334 /* binop vAA, vBB, vCC */ 4335 FETCH(r0, 1) @ r0<- CCBB 4336 mov r9, rINST, lsr #8 @ r9<- AA 4337 mov r3, r0, lsr #8 @ r3<- CC 4338 and r2, r0, #255 @ r2<- BB 4339 GET_VREG(r1, r3) @ r1<- vCC 4340 GET_VREG(r0, r2) @ r0<- vBB 4341 .if 0 4342 cmp r1, #0 @ is second operand zero? 4343 beq common_errDivideByZero 4344 .endif 4345 4346 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4347 @ optional op; may set condition codes 4348 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4349 GET_INST_OPCODE(ip) @ extract opcode from rINST 4350 SET_VREG(r0, r9) @ vAA<- r0 4351 GOTO_OPCODE(ip) @ jump to next instruction 4352 /* 11-14 instructions */ 4353 4354 4355/* ------------------------------ */ 4356 .balign 64 4357.L_OP_SHL_INT: /* 0x98 */ 4358/* File: armv5te/OP_SHL_INT.S */ 4359/* File: armv5te/binop.S */ 4360 /* 4361 * Generic 32-bit binary operation. Provide an "instr" line that 4362 * specifies an instruction that performs "result = r0 op r1". 4363 * This could be an ARM instruction or a function call. (If the result 4364 * comes back in a register other than r0, you can override "result".) 4365 * 4366 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4367 * vCC (r1). Useful for integer division and modulus. Note that we 4368 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4369 * handles it correctly. 4370 * 4371 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4372 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4373 * mul-float, div-float, rem-float 4374 */ 4375 /* binop vAA, vBB, vCC */ 4376 FETCH(r0, 1) @ r0<- CCBB 4377 mov r9, rINST, lsr #8 @ r9<- AA 4378 mov r3, r0, lsr #8 @ r3<- CC 4379 and r2, r0, #255 @ r2<- BB 4380 GET_VREG(r1, r3) @ r1<- vCC 4381 GET_VREG(r0, r2) @ r0<- vBB 4382 .if 0 4383 cmp r1, #0 @ is second operand zero? 4384 beq common_errDivideByZero 4385 .endif 4386 4387 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4388 and r1, r1, #31 @ optional op; may set condition codes 4389 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4390 GET_INST_OPCODE(ip) @ extract opcode from rINST 4391 SET_VREG(r0, r9) @ vAA<- r0 4392 GOTO_OPCODE(ip) @ jump to next instruction 4393 /* 11-14 instructions */ 4394 4395 4396/* ------------------------------ */ 4397 .balign 64 4398.L_OP_SHR_INT: /* 0x99 */ 4399/* File: armv5te/OP_SHR_INT.S */ 4400/* File: armv5te/binop.S */ 4401 /* 4402 * Generic 32-bit binary operation. Provide an "instr" line that 4403 * specifies an instruction that performs "result = r0 op r1". 4404 * This could be an ARM instruction or a function call. (If the result 4405 * comes back in a register other than r0, you can override "result".) 4406 * 4407 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4408 * vCC (r1). Useful for integer division and modulus. Note that we 4409 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4410 * handles it correctly. 4411 * 4412 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4413 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4414 * mul-float, div-float, rem-float 4415 */ 4416 /* binop vAA, vBB, vCC */ 4417 FETCH(r0, 1) @ r0<- CCBB 4418 mov r9, rINST, lsr #8 @ r9<- AA 4419 mov r3, r0, lsr #8 @ r3<- CC 4420 and r2, r0, #255 @ r2<- BB 4421 GET_VREG(r1, r3) @ r1<- vCC 4422 GET_VREG(r0, r2) @ r0<- vBB 4423 .if 0 4424 cmp r1, #0 @ is second operand zero? 4425 beq common_errDivideByZero 4426 .endif 4427 4428 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4429 and r1, r1, #31 @ optional op; may set condition codes 4430 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4431 GET_INST_OPCODE(ip) @ extract opcode from rINST 4432 SET_VREG(r0, r9) @ vAA<- r0 4433 GOTO_OPCODE(ip) @ jump to next instruction 4434 /* 11-14 instructions */ 4435 4436 4437/* ------------------------------ */ 4438 .balign 64 4439.L_OP_USHR_INT: /* 0x9a */ 4440/* File: armv5te/OP_USHR_INT.S */ 4441/* File: armv5te/binop.S */ 4442 /* 4443 * Generic 32-bit binary operation. Provide an "instr" line that 4444 * specifies an instruction that performs "result = r0 op r1". 4445 * This could be an ARM instruction or a function call. (If the result 4446 * comes back in a register other than r0, you can override "result".) 4447 * 4448 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4449 * vCC (r1). Useful for integer division and modulus. Note that we 4450 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4451 * handles it correctly. 4452 * 4453 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4454 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4455 * mul-float, div-float, rem-float 4456 */ 4457 /* binop vAA, vBB, vCC */ 4458 FETCH(r0, 1) @ r0<- CCBB 4459 mov r9, rINST, lsr #8 @ r9<- AA 4460 mov r3, r0, lsr #8 @ r3<- CC 4461 and r2, r0, #255 @ r2<- BB 4462 GET_VREG(r1, r3) @ r1<- vCC 4463 GET_VREG(r0, r2) @ r0<- vBB 4464 .if 0 4465 cmp r1, #0 @ is second operand zero? 4466 beq common_errDivideByZero 4467 .endif 4468 4469 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4470 and r1, r1, #31 @ optional op; may set condition codes 4471 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4472 GET_INST_OPCODE(ip) @ extract opcode from rINST 4473 SET_VREG(r0, r9) @ vAA<- r0 4474 GOTO_OPCODE(ip) @ jump to next instruction 4475 /* 11-14 instructions */ 4476 4477 4478/* ------------------------------ */ 4479 .balign 64 4480.L_OP_ADD_LONG: /* 0x9b */ 4481/* File: armv5te/OP_ADD_LONG.S */ 4482/* File: armv5te/binopWide.S */ 4483 /* 4484 * Generic 64-bit binary operation. Provide an "instr" line that 4485 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4486 * This could be an ARM instruction or a function call. (If the result 4487 * comes back in a register other than r0, you can override "result".) 4488 * 4489 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4490 * vCC (r1). Useful for integer division and modulus. 4491 * 4492 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4493 * xor-long, add-double, sub-double, mul-double, div-double, 4494 * rem-double 4495 * 4496 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4497 */ 4498 /* binop vAA, vBB, vCC */ 4499 FETCH(r0, 1) @ r0<- CCBB 4500 mov r9, rINST, lsr #8 @ r9<- AA 4501 and r2, r0, #255 @ r2<- BB 4502 mov r3, r0, lsr #8 @ r3<- CC 4503 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4504 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4505 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4506 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4507 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4508 .if 0 4509 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4510 beq common_errDivideByZero 4511 .endif 4512 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4513 4514 adds r0, r0, r2 @ optional op; may set condition codes 4515 adc r1, r1, r3 @ result<- op, r0-r3 changed 4516 GET_INST_OPCODE(ip) @ extract opcode from rINST 4517 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4518 GOTO_OPCODE(ip) @ jump to next instruction 4519 /* 14-17 instructions */ 4520 4521 4522/* ------------------------------ */ 4523 .balign 64 4524.L_OP_SUB_LONG: /* 0x9c */ 4525/* File: armv5te/OP_SUB_LONG.S */ 4526/* File: armv5te/binopWide.S */ 4527 /* 4528 * Generic 64-bit binary operation. Provide an "instr" line that 4529 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4530 * This could be an ARM instruction or a function call. (If the result 4531 * comes back in a register other than r0, you can override "result".) 4532 * 4533 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4534 * vCC (r1). Useful for integer division and modulus. 4535 * 4536 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4537 * xor-long, add-double, sub-double, mul-double, div-double, 4538 * rem-double 4539 * 4540 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4541 */ 4542 /* binop vAA, vBB, vCC */ 4543 FETCH(r0, 1) @ r0<- CCBB 4544 mov r9, rINST, lsr #8 @ r9<- AA 4545 and r2, r0, #255 @ r2<- BB 4546 mov r3, r0, lsr #8 @ r3<- CC 4547 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4548 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4549 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4550 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4551 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4552 .if 0 4553 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4554 beq common_errDivideByZero 4555 .endif 4556 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4557 4558 subs r0, r0, r2 @ optional op; may set condition codes 4559 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4560 GET_INST_OPCODE(ip) @ extract opcode from rINST 4561 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4562 GOTO_OPCODE(ip) @ jump to next instruction 4563 /* 14-17 instructions */ 4564 4565 4566/* ------------------------------ */ 4567 .balign 64 4568.L_OP_MUL_LONG: /* 0x9d */ 4569/* File: armv5te/OP_MUL_LONG.S */ 4570 /* 4571 * Signed 64-bit integer multiply. 4572 * 4573 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4574 * WX 4575 * x YZ 4576 * -------- 4577 * ZW ZX 4578 * YW YX 4579 * 4580 * The low word of the result holds ZX, the high word holds 4581 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4582 * it doesn't fit in the low 64 bits. 4583 * 4584 * Unlike most ARM math operations, multiply instructions have 4585 * restrictions on using the same register more than once (Rd and Rm 4586 * cannot be the same). 4587 */ 4588 /* mul-long vAA, vBB, vCC */ 4589 FETCH(r0, 1) @ r0<- CCBB 4590 and r2, r0, #255 @ r2<- BB 4591 mov r3, r0, lsr #8 @ r3<- CC 4592 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4593 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4594 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4595 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4596 mul ip, r2, r1 @ ip<- ZxW 4597 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4598 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4599 mov r0, rINST, lsr #8 @ r0<- AA 4600 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4601 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4602 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4603 b .LOP_MUL_LONG_finish 4604 4605/* ------------------------------ */ 4606 .balign 64 4607.L_OP_DIV_LONG: /* 0x9e */ 4608/* File: armv5te/OP_DIV_LONG.S */ 4609/* File: armv5te/binopWide.S */ 4610 /* 4611 * Generic 64-bit binary operation. Provide an "instr" line that 4612 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4613 * This could be an ARM instruction or a function call. (If the result 4614 * comes back in a register other than r0, you can override "result".) 4615 * 4616 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4617 * vCC (r1). Useful for integer division and modulus. 4618 * 4619 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4620 * xor-long, add-double, sub-double, mul-double, div-double, 4621 * rem-double 4622 * 4623 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4624 */ 4625 /* binop vAA, vBB, vCC */ 4626 FETCH(r0, 1) @ r0<- CCBB 4627 mov r9, rINST, lsr #8 @ r9<- AA 4628 and r2, r0, #255 @ r2<- BB 4629 mov r3, r0, lsr #8 @ r3<- CC 4630 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4631 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4632 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4633 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4634 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4635 .if 1 4636 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4637 beq common_errDivideByZero 4638 .endif 4639 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4640 4641 @ optional op; may set condition codes 4642 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4643 GET_INST_OPCODE(ip) @ extract opcode from rINST 4644 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4645 GOTO_OPCODE(ip) @ jump to next instruction 4646 /* 14-17 instructions */ 4647 4648 4649/* ------------------------------ */ 4650 .balign 64 4651.L_OP_REM_LONG: /* 0x9f */ 4652/* File: armv5te/OP_REM_LONG.S */ 4653/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4654/* File: armv5te/binopWide.S */ 4655 /* 4656 * Generic 64-bit binary operation. Provide an "instr" line that 4657 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4658 * This could be an ARM instruction or a function call. (If the result 4659 * comes back in a register other than r0, you can override "result".) 4660 * 4661 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4662 * vCC (r1). Useful for integer division and modulus. 4663 * 4664 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4665 * xor-long, add-double, sub-double, mul-double, div-double, 4666 * rem-double 4667 * 4668 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4669 */ 4670 /* binop vAA, vBB, vCC */ 4671 FETCH(r0, 1) @ r0<- CCBB 4672 mov r9, rINST, lsr #8 @ r9<- AA 4673 and r2, r0, #255 @ r2<- BB 4674 mov r3, r0, lsr #8 @ r3<- CC 4675 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4676 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4677 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4678 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4679 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4680 .if 1 4681 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4682 beq common_errDivideByZero 4683 .endif 4684 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4685 4686 @ optional op; may set condition codes 4687 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4688 GET_INST_OPCODE(ip) @ extract opcode from rINST 4689 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4690 GOTO_OPCODE(ip) @ jump to next instruction 4691 /* 14-17 instructions */ 4692 4693 4694/* ------------------------------ */ 4695 .balign 64 4696.L_OP_AND_LONG: /* 0xa0 */ 4697/* File: armv5te/OP_AND_LONG.S */ 4698/* File: armv5te/binopWide.S */ 4699 /* 4700 * Generic 64-bit binary operation. Provide an "instr" line that 4701 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4702 * This could be an ARM instruction or a function call. (If the result 4703 * comes back in a register other than r0, you can override "result".) 4704 * 4705 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4706 * vCC (r1). Useful for integer division and modulus. 4707 * 4708 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4709 * xor-long, add-double, sub-double, mul-double, div-double, 4710 * rem-double 4711 * 4712 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4713 */ 4714 /* binop vAA, vBB, vCC */ 4715 FETCH(r0, 1) @ r0<- CCBB 4716 mov r9, rINST, lsr #8 @ r9<- AA 4717 and r2, r0, #255 @ r2<- BB 4718 mov r3, r0, lsr #8 @ r3<- CC 4719 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4720 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4721 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4722 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4723 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4724 .if 0 4725 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4726 beq common_errDivideByZero 4727 .endif 4728 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4729 4730 and r0, r0, r2 @ optional op; may set condition codes 4731 and r1, r1, r3 @ result<- op, r0-r3 changed 4732 GET_INST_OPCODE(ip) @ extract opcode from rINST 4733 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4734 GOTO_OPCODE(ip) @ jump to next instruction 4735 /* 14-17 instructions */ 4736 4737 4738/* ------------------------------ */ 4739 .balign 64 4740.L_OP_OR_LONG: /* 0xa1 */ 4741/* File: armv5te/OP_OR_LONG.S */ 4742/* File: armv5te/binopWide.S */ 4743 /* 4744 * Generic 64-bit binary operation. Provide an "instr" line that 4745 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4746 * This could be an ARM instruction or a function call. (If the result 4747 * comes back in a register other than r0, you can override "result".) 4748 * 4749 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4750 * vCC (r1). Useful for integer division and modulus. 4751 * 4752 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4753 * xor-long, add-double, sub-double, mul-double, div-double, 4754 * rem-double 4755 * 4756 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4757 */ 4758 /* binop vAA, vBB, vCC */ 4759 FETCH(r0, 1) @ r0<- CCBB 4760 mov r9, rINST, lsr #8 @ r9<- AA 4761 and r2, r0, #255 @ r2<- BB 4762 mov r3, r0, lsr #8 @ r3<- CC 4763 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4764 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4765 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4766 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4767 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4768 .if 0 4769 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4770 beq common_errDivideByZero 4771 .endif 4772 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4773 4774 orr r0, r0, r2 @ optional op; may set condition codes 4775 orr r1, r1, r3 @ result<- op, r0-r3 changed 4776 GET_INST_OPCODE(ip) @ extract opcode from rINST 4777 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4778 GOTO_OPCODE(ip) @ jump to next instruction 4779 /* 14-17 instructions */ 4780 4781 4782/* ------------------------------ */ 4783 .balign 64 4784.L_OP_XOR_LONG: /* 0xa2 */ 4785/* File: armv5te/OP_XOR_LONG.S */ 4786/* File: armv5te/binopWide.S */ 4787 /* 4788 * Generic 64-bit binary operation. Provide an "instr" line that 4789 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4790 * This could be an ARM instruction or a function call. (If the result 4791 * comes back in a register other than r0, you can override "result".) 4792 * 4793 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4794 * vCC (r1). Useful for integer division and modulus. 4795 * 4796 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4797 * xor-long, add-double, sub-double, mul-double, div-double, 4798 * rem-double 4799 * 4800 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4801 */ 4802 /* binop vAA, vBB, vCC */ 4803 FETCH(r0, 1) @ r0<- CCBB 4804 mov r9, rINST, lsr #8 @ r9<- AA 4805 and r2, r0, #255 @ r2<- BB 4806 mov r3, r0, lsr #8 @ r3<- CC 4807 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4808 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4809 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4810 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4811 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4812 .if 0 4813 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4814 beq common_errDivideByZero 4815 .endif 4816 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4817 4818 eor r0, r0, r2 @ optional op; may set condition codes 4819 eor r1, r1, r3 @ result<- op, r0-r3 changed 4820 GET_INST_OPCODE(ip) @ extract opcode from rINST 4821 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4822 GOTO_OPCODE(ip) @ jump to next instruction 4823 /* 14-17 instructions */ 4824 4825 4826/* ------------------------------ */ 4827 .balign 64 4828.L_OP_SHL_LONG: /* 0xa3 */ 4829/* File: armv5te/OP_SHL_LONG.S */ 4830 /* 4831 * Long integer shift. This is different from the generic 32/64-bit 4832 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4833 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4834 * 6 bits of the shift distance. 4835 */ 4836 /* shl-long vAA, vBB, vCC */ 4837 FETCH(r0, 1) @ r0<- CCBB 4838 mov r9, rINST, lsr #8 @ r9<- AA 4839 and r3, r0, #255 @ r3<- BB 4840 mov r0, r0, lsr #8 @ r0<- CC 4841 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4842 GET_VREG(r2, r0) @ r2<- vCC 4843 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4844 and r2, r2, #63 @ r2<- r2 & 0x3f 4845 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4846 4847 mov r1, r1, asl r2 @ r1<- r1 << r2 4848 rsb r3, r2, #32 @ r3<- 32 - r2 4849 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 4850 subs ip, r2, #32 @ ip<- r2 - 32 4851 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 4852 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4853 b .LOP_SHL_LONG_finish 4854 4855/* ------------------------------ */ 4856 .balign 64 4857.L_OP_SHR_LONG: /* 0xa4 */ 4858/* File: armv5te/OP_SHR_LONG.S */ 4859 /* 4860 * Long integer shift. This is different from the generic 32/64-bit 4861 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4862 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4863 * 6 bits of the shift distance. 4864 */ 4865 /* shr-long vAA, vBB, vCC */ 4866 FETCH(r0, 1) @ r0<- CCBB 4867 mov r9, rINST, lsr #8 @ r9<- AA 4868 and r3, r0, #255 @ r3<- BB 4869 mov r0, r0, lsr #8 @ r0<- CC 4870 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4871 GET_VREG(r2, r0) @ r2<- vCC 4872 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4873 and r2, r2, #63 @ r0<- r0 & 0x3f 4874 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4875 4876 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4877 rsb r3, r2, #32 @ r3<- 32 - r2 4878 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4879 subs ip, r2, #32 @ ip<- r2 - 32 4880 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 4881 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4882 b .LOP_SHR_LONG_finish 4883 4884/* ------------------------------ */ 4885 .balign 64 4886.L_OP_USHR_LONG: /* 0xa5 */ 4887/* File: armv5te/OP_USHR_LONG.S */ 4888 /* 4889 * Long integer shift. This is different from the generic 32/64-bit 4890 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4891 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4892 * 6 bits of the shift distance. 4893 */ 4894 /* ushr-long vAA, vBB, vCC */ 4895 FETCH(r0, 1) @ r0<- CCBB 4896 mov r9, rINST, lsr #8 @ r9<- AA 4897 and r3, r0, #255 @ r3<- BB 4898 mov r0, r0, lsr #8 @ r0<- CC 4899 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4900 GET_VREG(r2, r0) @ r2<- vCC 4901 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4902 and r2, r2, #63 @ r0<- r0 & 0x3f 4903 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4904 4905 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4906 rsb r3, r2, #32 @ r3<- 32 - r2 4907 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4908 subs ip, r2, #32 @ ip<- r2 - 32 4909 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 4910 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4911 b .LOP_USHR_LONG_finish 4912 4913/* ------------------------------ */ 4914 .balign 64 4915.L_OP_ADD_FLOAT: /* 0xa6 */ 4916/* File: arm-vfp/OP_ADD_FLOAT.S */ 4917/* File: arm-vfp/fbinop.S */ 4918 /* 4919 * Generic 32-bit floating-point operation. Provide an "instr" line that 4920 * specifies an instruction that performs "s2 = s0 op s1". Because we 4921 * use the "softfp" ABI, this must be an instruction, not a function call. 4922 * 4923 * For: add-float, sub-float, mul-float, div-float 4924 */ 4925 /* floatop vAA, vBB, vCC */ 4926 FETCH(r0, 1) @ r0<- CCBB 4927 mov r9, rINST, lsr #8 @ r9<- AA 4928 mov r3, r0, lsr #8 @ r3<- CC 4929 and r2, r0, #255 @ r2<- BB 4930 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4931 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4932 flds s1, [r3] @ s1<- vCC 4933 flds s0, [r2] @ s0<- vBB 4934 4935 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4936 fadds s2, s0, s1 @ s2<- op 4937 GET_INST_OPCODE(ip) @ extract opcode from rINST 4938 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4939 fsts s2, [r9] @ vAA<- s2 4940 GOTO_OPCODE(ip) @ jump to next instruction 4941 4942 4943/* ------------------------------ */ 4944 .balign 64 4945.L_OP_SUB_FLOAT: /* 0xa7 */ 4946/* File: arm-vfp/OP_SUB_FLOAT.S */ 4947/* File: arm-vfp/fbinop.S */ 4948 /* 4949 * Generic 32-bit floating-point operation. Provide an "instr" line that 4950 * specifies an instruction that performs "s2 = s0 op s1". Because we 4951 * use the "softfp" ABI, this must be an instruction, not a function call. 4952 * 4953 * For: add-float, sub-float, mul-float, div-float 4954 */ 4955 /* floatop vAA, vBB, vCC */ 4956 FETCH(r0, 1) @ r0<- CCBB 4957 mov r9, rINST, lsr #8 @ r9<- AA 4958 mov r3, r0, lsr #8 @ r3<- CC 4959 and r2, r0, #255 @ r2<- BB 4960 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4961 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4962 flds s1, [r3] @ s1<- vCC 4963 flds s0, [r2] @ s0<- vBB 4964 4965 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4966 fsubs s2, s0, s1 @ s2<- op 4967 GET_INST_OPCODE(ip) @ extract opcode from rINST 4968 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4969 fsts s2, [r9] @ vAA<- s2 4970 GOTO_OPCODE(ip) @ jump to next instruction 4971 4972 4973/* ------------------------------ */ 4974 .balign 64 4975.L_OP_MUL_FLOAT: /* 0xa8 */ 4976/* File: arm-vfp/OP_MUL_FLOAT.S */ 4977/* File: arm-vfp/fbinop.S */ 4978 /* 4979 * Generic 32-bit floating-point operation. Provide an "instr" line that 4980 * specifies an instruction that performs "s2 = s0 op s1". Because we 4981 * use the "softfp" ABI, this must be an instruction, not a function call. 4982 * 4983 * For: add-float, sub-float, mul-float, div-float 4984 */ 4985 /* floatop vAA, vBB, vCC */ 4986 FETCH(r0, 1) @ r0<- CCBB 4987 mov r9, rINST, lsr #8 @ r9<- AA 4988 mov r3, r0, lsr #8 @ r3<- CC 4989 and r2, r0, #255 @ r2<- BB 4990 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4991 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4992 flds s1, [r3] @ s1<- vCC 4993 flds s0, [r2] @ s0<- vBB 4994 4995 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4996 fmuls s2, s0, s1 @ s2<- op 4997 GET_INST_OPCODE(ip) @ extract opcode from rINST 4998 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4999 fsts s2, [r9] @ vAA<- s2 5000 GOTO_OPCODE(ip) @ jump to next instruction 5001 5002 5003/* ------------------------------ */ 5004 .balign 64 5005.L_OP_DIV_FLOAT: /* 0xa9 */ 5006/* File: arm-vfp/OP_DIV_FLOAT.S */ 5007/* File: arm-vfp/fbinop.S */ 5008 /* 5009 * Generic 32-bit floating-point operation. Provide an "instr" line that 5010 * specifies an instruction that performs "s2 = s0 op s1". Because we 5011 * use the "softfp" ABI, this must be an instruction, not a function call. 5012 * 5013 * For: add-float, sub-float, mul-float, div-float 5014 */ 5015 /* floatop vAA, vBB, vCC */ 5016 FETCH(r0, 1) @ r0<- CCBB 5017 mov r9, rINST, lsr #8 @ r9<- AA 5018 mov r3, r0, lsr #8 @ r3<- CC 5019 and r2, r0, #255 @ r2<- BB 5020 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5021 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5022 flds s1, [r3] @ s1<- vCC 5023 flds s0, [r2] @ s0<- vBB 5024 5025 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5026 fdivs s2, s0, s1 @ s2<- op 5027 GET_INST_OPCODE(ip) @ extract opcode from rINST 5028 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5029 fsts s2, [r9] @ vAA<- s2 5030 GOTO_OPCODE(ip) @ jump to next instruction 5031 5032 5033/* ------------------------------ */ 5034 .balign 64 5035.L_OP_REM_FLOAT: /* 0xaa */ 5036/* File: armv5te/OP_REM_FLOAT.S */ 5037/* EABI doesn't define a float remainder function, but libm does */ 5038/* File: armv5te/binop.S */ 5039 /* 5040 * Generic 32-bit binary operation. Provide an "instr" line that 5041 * specifies an instruction that performs "result = r0 op r1". 5042 * This could be an ARM instruction or a function call. (If the result 5043 * comes back in a register other than r0, you can override "result".) 5044 * 5045 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5046 * vCC (r1). Useful for integer division and modulus. Note that we 5047 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5048 * handles it correctly. 5049 * 5050 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5051 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5052 * mul-float, div-float, rem-float 5053 */ 5054 /* binop vAA, vBB, vCC */ 5055 FETCH(r0, 1) @ r0<- CCBB 5056 mov r9, rINST, lsr #8 @ r9<- AA 5057 mov r3, r0, lsr #8 @ r3<- CC 5058 and r2, r0, #255 @ r2<- BB 5059 GET_VREG(r1, r3) @ r1<- vCC 5060 GET_VREG(r0, r2) @ r0<- vBB 5061 .if 0 5062 cmp r1, #0 @ is second operand zero? 5063 beq common_errDivideByZero 5064 .endif 5065 5066 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5067 @ optional op; may set condition codes 5068 bl fmodf @ r0<- op, r0-r3 changed 5069 GET_INST_OPCODE(ip) @ extract opcode from rINST 5070 SET_VREG(r0, r9) @ vAA<- r0 5071 GOTO_OPCODE(ip) @ jump to next instruction 5072 /* 11-14 instructions */ 5073 5074 5075/* ------------------------------ */ 5076 .balign 64 5077.L_OP_ADD_DOUBLE: /* 0xab */ 5078/* File: arm-vfp/OP_ADD_DOUBLE.S */ 5079/* File: arm-vfp/fbinopWide.S */ 5080 /* 5081 * Generic 64-bit double-precision floating point binary operation. 5082 * Provide an "instr" line that specifies an instruction that performs 5083 * "d2 = d0 op d1". 5084 * 5085 * for: add-double, sub-double, mul-double, div-double 5086 */ 5087 /* doubleop vAA, vBB, vCC */ 5088 FETCH(r0, 1) @ r0<- CCBB 5089 mov r9, rINST, lsr #8 @ r9<- AA 5090 mov r3, r0, lsr #8 @ r3<- CC 5091 and r2, r0, #255 @ r2<- BB 5092 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5093 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5094 fldd d1, [r3] @ d1<- vCC 5095 fldd d0, [r2] @ d0<- vBB 5096 5097 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5098 faddd d2, d0, d1 @ s2<- op 5099 GET_INST_OPCODE(ip) @ extract opcode from rINST 5100 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5101 fstd d2, [r9] @ vAA<- d2 5102 GOTO_OPCODE(ip) @ jump to next instruction 5103 5104 5105/* ------------------------------ */ 5106 .balign 64 5107.L_OP_SUB_DOUBLE: /* 0xac */ 5108/* File: arm-vfp/OP_SUB_DOUBLE.S */ 5109/* File: arm-vfp/fbinopWide.S */ 5110 /* 5111 * Generic 64-bit double-precision floating point binary operation. 5112 * Provide an "instr" line that specifies an instruction that performs 5113 * "d2 = d0 op d1". 5114 * 5115 * for: add-double, sub-double, mul-double, div-double 5116 */ 5117 /* doubleop vAA, vBB, vCC */ 5118 FETCH(r0, 1) @ r0<- CCBB 5119 mov r9, rINST, lsr #8 @ r9<- AA 5120 mov r3, r0, lsr #8 @ r3<- CC 5121 and r2, r0, #255 @ r2<- BB 5122 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5123 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5124 fldd d1, [r3] @ d1<- vCC 5125 fldd d0, [r2] @ d0<- vBB 5126 5127 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5128 fsubd d2, d0, d1 @ s2<- op 5129 GET_INST_OPCODE(ip) @ extract opcode from rINST 5130 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5131 fstd d2, [r9] @ vAA<- d2 5132 GOTO_OPCODE(ip) @ jump to next instruction 5133 5134 5135/* ------------------------------ */ 5136 .balign 64 5137.L_OP_MUL_DOUBLE: /* 0xad */ 5138/* File: arm-vfp/OP_MUL_DOUBLE.S */ 5139/* File: arm-vfp/fbinopWide.S */ 5140 /* 5141 * Generic 64-bit double-precision floating point binary operation. 5142 * Provide an "instr" line that specifies an instruction that performs 5143 * "d2 = d0 op d1". 5144 * 5145 * for: add-double, sub-double, mul-double, div-double 5146 */ 5147 /* doubleop vAA, vBB, vCC */ 5148 FETCH(r0, 1) @ r0<- CCBB 5149 mov r9, rINST, lsr #8 @ r9<- AA 5150 mov r3, r0, lsr #8 @ r3<- CC 5151 and r2, r0, #255 @ r2<- BB 5152 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5153 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5154 fldd d1, [r3] @ d1<- vCC 5155 fldd d0, [r2] @ d0<- vBB 5156 5157 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5158 fmuld d2, d0, d1 @ s2<- op 5159 GET_INST_OPCODE(ip) @ extract opcode from rINST 5160 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5161 fstd d2, [r9] @ vAA<- d2 5162 GOTO_OPCODE(ip) @ jump to next instruction 5163 5164 5165/* ------------------------------ */ 5166 .balign 64 5167.L_OP_DIV_DOUBLE: /* 0xae */ 5168/* File: arm-vfp/OP_DIV_DOUBLE.S */ 5169/* File: arm-vfp/fbinopWide.S */ 5170 /* 5171 * Generic 64-bit double-precision floating point binary operation. 5172 * Provide an "instr" line that specifies an instruction that performs 5173 * "d2 = d0 op d1". 5174 * 5175 * for: add-double, sub-double, mul-double, div-double 5176 */ 5177 /* doubleop vAA, vBB, vCC */ 5178 FETCH(r0, 1) @ r0<- CCBB 5179 mov r9, rINST, lsr #8 @ r9<- AA 5180 mov r3, r0, lsr #8 @ r3<- CC 5181 and r2, r0, #255 @ r2<- BB 5182 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5183 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5184 fldd d1, [r3] @ d1<- vCC 5185 fldd d0, [r2] @ d0<- vBB 5186 5187 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5188 fdivd d2, d0, d1 @ s2<- op 5189 GET_INST_OPCODE(ip) @ extract opcode from rINST 5190 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5191 fstd d2, [r9] @ vAA<- d2 5192 GOTO_OPCODE(ip) @ jump to next instruction 5193 5194 5195/* ------------------------------ */ 5196 .balign 64 5197.L_OP_REM_DOUBLE: /* 0xaf */ 5198/* File: armv5te/OP_REM_DOUBLE.S */ 5199/* EABI doesn't define a double remainder function, but libm does */ 5200/* File: armv5te/binopWide.S */ 5201 /* 5202 * Generic 64-bit binary operation. Provide an "instr" line that 5203 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5204 * This could be an ARM instruction or a function call. (If the result 5205 * comes back in a register other than r0, you can override "result".) 5206 * 5207 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5208 * vCC (r1). Useful for integer division and modulus. 5209 * 5210 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5211 * xor-long, add-double, sub-double, mul-double, div-double, 5212 * rem-double 5213 * 5214 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5215 */ 5216 /* binop vAA, vBB, vCC */ 5217 FETCH(r0, 1) @ r0<- CCBB 5218 mov r9, rINST, lsr #8 @ r9<- AA 5219 and r2, r0, #255 @ r2<- BB 5220 mov r3, r0, lsr #8 @ r3<- CC 5221 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5222 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5223 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5224 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5225 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5226 .if 0 5227 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5228 beq common_errDivideByZero 5229 .endif 5230 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5231 5232 @ optional op; may set condition codes 5233 bl fmod @ result<- op, r0-r3 changed 5234 GET_INST_OPCODE(ip) @ extract opcode from rINST 5235 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5236 GOTO_OPCODE(ip) @ jump to next instruction 5237 /* 14-17 instructions */ 5238 5239 5240/* ------------------------------ */ 5241 .balign 64 5242.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5243/* File: armv6t2/OP_ADD_INT_2ADDR.S */ 5244/* File: armv6t2/binop2addr.S */ 5245 /* 5246 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5247 * that specifies an instruction that performs "result = r0 op r1". 5248 * This could be an ARM instruction or a function call. (If the result 5249 * comes back in a register other than r0, you can override "result".) 5250 * 5251 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5252 * vCC (r1). Useful for integer division and modulus. 5253 * 5254 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5255 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5256 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5257 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5258 */ 5259 /* binop/2addr vA, vB */ 5260 mov r3, rINST, lsr #12 @ r3<- B 5261 ubfx r9, rINST, #8, #4 @ r9<- A 5262 GET_VREG(r1, r3) @ r1<- vB 5263 GET_VREG(r0, r9) @ r0<- vA 5264 .if 0 5265 cmp r1, #0 @ is second operand zero? 5266 beq common_errDivideByZero 5267 .endif 5268 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5269 5270 @ optional op; may set condition codes 5271 add r0, r0, r1 @ r0<- op, r0-r3 changed 5272 GET_INST_OPCODE(ip) @ extract opcode from rINST 5273 SET_VREG(r0, r9) @ vAA<- r0 5274 GOTO_OPCODE(ip) @ jump to next instruction 5275 /* 10-13 instructions */ 5276 5277 5278/* ------------------------------ */ 5279 .balign 64 5280.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5281/* File: armv6t2/OP_SUB_INT_2ADDR.S */ 5282/* File: armv6t2/binop2addr.S */ 5283 /* 5284 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5285 * that specifies an instruction that performs "result = r0 op r1". 5286 * This could be an ARM instruction or a function call. (If the result 5287 * comes back in a register other than r0, you can override "result".) 5288 * 5289 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5290 * vCC (r1). Useful for integer division and modulus. 5291 * 5292 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5293 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5294 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5295 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5296 */ 5297 /* binop/2addr vA, vB */ 5298 mov r3, rINST, lsr #12 @ r3<- B 5299 ubfx r9, rINST, #8, #4 @ r9<- A 5300 GET_VREG(r1, r3) @ r1<- vB 5301 GET_VREG(r0, r9) @ r0<- vA 5302 .if 0 5303 cmp r1, #0 @ is second operand zero? 5304 beq common_errDivideByZero 5305 .endif 5306 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5307 5308 @ optional op; may set condition codes 5309 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5310 GET_INST_OPCODE(ip) @ extract opcode from rINST 5311 SET_VREG(r0, r9) @ vAA<- r0 5312 GOTO_OPCODE(ip) @ jump to next instruction 5313 /* 10-13 instructions */ 5314 5315 5316/* ------------------------------ */ 5317 .balign 64 5318.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5319/* File: armv6t2/OP_MUL_INT_2ADDR.S */ 5320/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5321/* File: armv6t2/binop2addr.S */ 5322 /* 5323 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5324 * that specifies an instruction that performs "result = r0 op r1". 5325 * This could be an ARM instruction or a function call. (If the result 5326 * comes back in a register other than r0, you can override "result".) 5327 * 5328 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5329 * vCC (r1). Useful for integer division and modulus. 5330 * 5331 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5332 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5333 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5334 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5335 */ 5336 /* binop/2addr vA, vB */ 5337 mov r3, rINST, lsr #12 @ r3<- B 5338 ubfx r9, rINST, #8, #4 @ r9<- A 5339 GET_VREG(r1, r3) @ r1<- vB 5340 GET_VREG(r0, r9) @ r0<- vA 5341 .if 0 5342 cmp r1, #0 @ is second operand zero? 5343 beq common_errDivideByZero 5344 .endif 5345 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5346 5347 @ optional op; may set condition codes 5348 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5349 GET_INST_OPCODE(ip) @ extract opcode from rINST 5350 SET_VREG(r0, r9) @ vAA<- r0 5351 GOTO_OPCODE(ip) @ jump to next instruction 5352 /* 10-13 instructions */ 5353 5354 5355/* ------------------------------ */ 5356 .balign 64 5357.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5358/* File: armv6t2/OP_DIV_INT_2ADDR.S */ 5359/* File: armv6t2/binop2addr.S */ 5360 /* 5361 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5362 * that specifies an instruction that performs "result = r0 op r1". 5363 * This could be an ARM instruction or a function call. (If the result 5364 * comes back in a register other than r0, you can override "result".) 5365 * 5366 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5367 * vCC (r1). Useful for integer division and modulus. 5368 * 5369 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5370 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5371 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5372 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5373 */ 5374 /* binop/2addr vA, vB */ 5375 mov r3, rINST, lsr #12 @ r3<- B 5376 ubfx r9, rINST, #8, #4 @ r9<- A 5377 GET_VREG(r1, r3) @ r1<- vB 5378 GET_VREG(r0, r9) @ r0<- vA 5379 .if 1 5380 cmp r1, #0 @ is second operand zero? 5381 beq common_errDivideByZero 5382 .endif 5383 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5384 5385 @ optional op; may set condition codes 5386 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5387 GET_INST_OPCODE(ip) @ extract opcode from rINST 5388 SET_VREG(r0, r9) @ vAA<- r0 5389 GOTO_OPCODE(ip) @ jump to next instruction 5390 /* 10-13 instructions */ 5391 5392 5393/* ------------------------------ */ 5394 .balign 64 5395.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5396/* File: armv6t2/OP_REM_INT_2ADDR.S */ 5397/* idivmod returns quotient in r0 and remainder in r1 */ 5398/* File: armv6t2/binop2addr.S */ 5399 /* 5400 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5401 * that specifies an instruction that performs "result = r0 op r1". 5402 * This could be an ARM instruction or a function call. (If the result 5403 * comes back in a register other than r0, you can override "result".) 5404 * 5405 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5406 * vCC (r1). Useful for integer division and modulus. 5407 * 5408 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5409 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5410 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5411 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5412 */ 5413 /* binop/2addr vA, vB */ 5414 mov r3, rINST, lsr #12 @ r3<- B 5415 ubfx r9, rINST, #8, #4 @ r9<- A 5416 GET_VREG(r1, r3) @ r1<- vB 5417 GET_VREG(r0, r9) @ r0<- vA 5418 .if 1 5419 cmp r1, #0 @ is second operand zero? 5420 beq common_errDivideByZero 5421 .endif 5422 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5423 5424 @ optional op; may set condition codes 5425 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5426 GET_INST_OPCODE(ip) @ extract opcode from rINST 5427 SET_VREG(r1, r9) @ vAA<- r1 5428 GOTO_OPCODE(ip) @ jump to next instruction 5429 /* 10-13 instructions */ 5430 5431 5432/* ------------------------------ */ 5433 .balign 64 5434.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5435/* File: armv6t2/OP_AND_INT_2ADDR.S */ 5436/* File: armv6t2/binop2addr.S */ 5437 /* 5438 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5439 * that specifies an instruction that performs "result = r0 op r1". 5440 * This could be an ARM instruction or a function call. (If the result 5441 * comes back in a register other than r0, you can override "result".) 5442 * 5443 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5444 * vCC (r1). Useful for integer division and modulus. 5445 * 5446 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5447 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5448 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5449 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5450 */ 5451 /* binop/2addr vA, vB */ 5452 mov r3, rINST, lsr #12 @ r3<- B 5453 ubfx r9, rINST, #8, #4 @ r9<- A 5454 GET_VREG(r1, r3) @ r1<- vB 5455 GET_VREG(r0, r9) @ r0<- vA 5456 .if 0 5457 cmp r1, #0 @ is second operand zero? 5458 beq common_errDivideByZero 5459 .endif 5460 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5461 5462 @ optional op; may set condition codes 5463 and r0, r0, r1 @ r0<- op, r0-r3 changed 5464 GET_INST_OPCODE(ip) @ extract opcode from rINST 5465 SET_VREG(r0, r9) @ vAA<- r0 5466 GOTO_OPCODE(ip) @ jump to next instruction 5467 /* 10-13 instructions */ 5468 5469 5470/* ------------------------------ */ 5471 .balign 64 5472.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5473/* File: armv6t2/OP_OR_INT_2ADDR.S */ 5474/* File: armv6t2/binop2addr.S */ 5475 /* 5476 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5477 * that specifies an instruction that performs "result = r0 op r1". 5478 * This could be an ARM instruction or a function call. (If the result 5479 * comes back in a register other than r0, you can override "result".) 5480 * 5481 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5482 * vCC (r1). Useful for integer division and modulus. 5483 * 5484 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5485 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5486 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5487 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5488 */ 5489 /* binop/2addr vA, vB */ 5490 mov r3, rINST, lsr #12 @ r3<- B 5491 ubfx r9, rINST, #8, #4 @ r9<- A 5492 GET_VREG(r1, r3) @ r1<- vB 5493 GET_VREG(r0, r9) @ r0<- vA 5494 .if 0 5495 cmp r1, #0 @ is second operand zero? 5496 beq common_errDivideByZero 5497 .endif 5498 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5499 5500 @ optional op; may set condition codes 5501 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5502 GET_INST_OPCODE(ip) @ extract opcode from rINST 5503 SET_VREG(r0, r9) @ vAA<- r0 5504 GOTO_OPCODE(ip) @ jump to next instruction 5505 /* 10-13 instructions */ 5506 5507 5508/* ------------------------------ */ 5509 .balign 64 5510.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5511/* File: armv6t2/OP_XOR_INT_2ADDR.S */ 5512/* File: armv6t2/binop2addr.S */ 5513 /* 5514 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5515 * that specifies an instruction that performs "result = r0 op r1". 5516 * This could be an ARM instruction or a function call. (If the result 5517 * comes back in a register other than r0, you can override "result".) 5518 * 5519 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5520 * vCC (r1). Useful for integer division and modulus. 5521 * 5522 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5523 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5524 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5525 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5526 */ 5527 /* binop/2addr vA, vB */ 5528 mov r3, rINST, lsr #12 @ r3<- B 5529 ubfx r9, rINST, #8, #4 @ r9<- A 5530 GET_VREG(r1, r3) @ r1<- vB 5531 GET_VREG(r0, r9) @ r0<- vA 5532 .if 0 5533 cmp r1, #0 @ is second operand zero? 5534 beq common_errDivideByZero 5535 .endif 5536 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5537 5538 @ optional op; may set condition codes 5539 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5540 GET_INST_OPCODE(ip) @ extract opcode from rINST 5541 SET_VREG(r0, r9) @ vAA<- r0 5542 GOTO_OPCODE(ip) @ jump to next instruction 5543 /* 10-13 instructions */ 5544 5545 5546/* ------------------------------ */ 5547 .balign 64 5548.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5549/* File: armv6t2/OP_SHL_INT_2ADDR.S */ 5550/* File: armv6t2/binop2addr.S */ 5551 /* 5552 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5553 * that specifies an instruction that performs "result = r0 op r1". 5554 * This could be an ARM instruction or a function call. (If the result 5555 * comes back in a register other than r0, you can override "result".) 5556 * 5557 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5558 * vCC (r1). Useful for integer division and modulus. 5559 * 5560 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5561 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5562 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5563 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5564 */ 5565 /* binop/2addr vA, vB */ 5566 mov r3, rINST, lsr #12 @ r3<- B 5567 ubfx r9, rINST, #8, #4 @ r9<- A 5568 GET_VREG(r1, r3) @ r1<- vB 5569 GET_VREG(r0, r9) @ r0<- vA 5570 .if 0 5571 cmp r1, #0 @ is second operand zero? 5572 beq common_errDivideByZero 5573 .endif 5574 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5575 5576 and r1, r1, #31 @ optional op; may set condition codes 5577 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5578 GET_INST_OPCODE(ip) @ extract opcode from rINST 5579 SET_VREG(r0, r9) @ vAA<- r0 5580 GOTO_OPCODE(ip) @ jump to next instruction 5581 /* 10-13 instructions */ 5582 5583 5584/* ------------------------------ */ 5585 .balign 64 5586.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5587/* File: armv6t2/OP_SHR_INT_2ADDR.S */ 5588/* File: armv6t2/binop2addr.S */ 5589 /* 5590 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5591 * that specifies an instruction that performs "result = r0 op r1". 5592 * This could be an ARM instruction or a function call. (If the result 5593 * comes back in a register other than r0, you can override "result".) 5594 * 5595 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5596 * vCC (r1). Useful for integer division and modulus. 5597 * 5598 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5599 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5600 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5601 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5602 */ 5603 /* binop/2addr vA, vB */ 5604 mov r3, rINST, lsr #12 @ r3<- B 5605 ubfx r9, rINST, #8, #4 @ r9<- A 5606 GET_VREG(r1, r3) @ r1<- vB 5607 GET_VREG(r0, r9) @ r0<- vA 5608 .if 0 5609 cmp r1, #0 @ is second operand zero? 5610 beq common_errDivideByZero 5611 .endif 5612 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5613 5614 and r1, r1, #31 @ optional op; may set condition codes 5615 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5616 GET_INST_OPCODE(ip) @ extract opcode from rINST 5617 SET_VREG(r0, r9) @ vAA<- r0 5618 GOTO_OPCODE(ip) @ jump to next instruction 5619 /* 10-13 instructions */ 5620 5621 5622/* ------------------------------ */ 5623 .balign 64 5624.L_OP_USHR_INT_2ADDR: /* 0xba */ 5625/* File: armv6t2/OP_USHR_INT_2ADDR.S */ 5626/* File: armv6t2/binop2addr.S */ 5627 /* 5628 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5629 * that specifies an instruction that performs "result = r0 op r1". 5630 * This could be an ARM instruction or a function call. (If the result 5631 * comes back in a register other than r0, you can override "result".) 5632 * 5633 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5634 * vCC (r1). Useful for integer division and modulus. 5635 * 5636 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5637 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5638 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5639 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5640 */ 5641 /* binop/2addr vA, vB */ 5642 mov r3, rINST, lsr #12 @ r3<- B 5643 ubfx r9, rINST, #8, #4 @ r9<- A 5644 GET_VREG(r1, r3) @ r1<- vB 5645 GET_VREG(r0, r9) @ r0<- vA 5646 .if 0 5647 cmp r1, #0 @ is second operand zero? 5648 beq common_errDivideByZero 5649 .endif 5650 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5651 5652 and r1, r1, #31 @ optional op; may set condition codes 5653 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5654 GET_INST_OPCODE(ip) @ extract opcode from rINST 5655 SET_VREG(r0, r9) @ vAA<- r0 5656 GOTO_OPCODE(ip) @ jump to next instruction 5657 /* 10-13 instructions */ 5658 5659 5660/* ------------------------------ */ 5661 .balign 64 5662.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5663/* File: armv6t2/OP_ADD_LONG_2ADDR.S */ 5664/* File: armv6t2/binopWide2addr.S */ 5665 /* 5666 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5667 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 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-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5675 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5676 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5677 * rem-double/2addr 5678 */ 5679 /* binop/2addr vA, vB */ 5680 mov r1, rINST, lsr #12 @ r1<- B 5681 ubfx r9, rINST, #8, #4 @ r9<- A 5682 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5683 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5684 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5685 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5686 .if 0 5687 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5688 beq common_errDivideByZero 5689 .endif 5690 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5691 5692 adds r0, r0, r2 @ optional op; may set condition codes 5693 adc r1, r1, r3 @ result<- op, r0-r3 changed 5694 GET_INST_OPCODE(ip) @ extract opcode from rINST 5695 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5696 GOTO_OPCODE(ip) @ jump to next instruction 5697 /* 12-15 instructions */ 5698 5699 5700/* ------------------------------ */ 5701 .balign 64 5702.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5703/* File: armv6t2/OP_SUB_LONG_2ADDR.S */ 5704/* File: armv6t2/binopWide2addr.S */ 5705 /* 5706 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5707 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5708 * This could be an ARM instruction or a function call. (If the result 5709 * comes back in a register other than r0, you can override "result".) 5710 * 5711 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5712 * vCC (r1). Useful for integer division and modulus. 5713 * 5714 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5715 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5716 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5717 * rem-double/2addr 5718 */ 5719 /* binop/2addr vA, vB */ 5720 mov r1, rINST, lsr #12 @ r1<- B 5721 ubfx r9, rINST, #8, #4 @ r9<- A 5722 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5723 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5724 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5725 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5726 .if 0 5727 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5728 beq common_errDivideByZero 5729 .endif 5730 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5731 5732 subs r0, r0, r2 @ optional op; may set condition codes 5733 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5734 GET_INST_OPCODE(ip) @ extract opcode from rINST 5735 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5736 GOTO_OPCODE(ip) @ jump to next instruction 5737 /* 12-15 instructions */ 5738 5739 5740/* ------------------------------ */ 5741 .balign 64 5742.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 5743/* File: armv6t2/OP_MUL_LONG_2ADDR.S */ 5744 /* 5745 * Signed 64-bit integer multiply, "/2addr" version. 5746 * 5747 * See OP_MUL_LONG for an explanation. 5748 * 5749 * We get a little tight on registers, so to avoid looking up &fp[A] 5750 * again we stuff it into rINST. 5751 */ 5752 /* mul-long/2addr vA, vB */ 5753 mov r1, rINST, lsr #12 @ r1<- B 5754 ubfx r9, rINST, #8, #4 @ r9<- A 5755 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5756 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 5757 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5758 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 5759 mul ip, r2, r1 @ ip<- ZxW 5760 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 5761 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 5762 mov r0, rINST @ r0<- &fp[A] (free up rINST) 5763 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5764 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 5765 GET_INST_OPCODE(ip) @ extract opcode from rINST 5766 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 5767 GOTO_OPCODE(ip) @ jump to next instruction 5768 5769/* ------------------------------ */ 5770 .balign 64 5771.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 5772/* File: armv6t2/OP_DIV_LONG_2ADDR.S */ 5773/* File: armv6t2/binopWide2addr.S */ 5774 /* 5775 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5776 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5777 * This could be an ARM instruction or a function call. (If the result 5778 * comes back in a register other than r0, you can override "result".) 5779 * 5780 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5781 * vCC (r1). Useful for integer division and modulus. 5782 * 5783 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5784 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5785 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5786 * rem-double/2addr 5787 */ 5788 /* binop/2addr vA, vB */ 5789 mov r1, rINST, lsr #12 @ r1<- B 5790 ubfx r9, rINST, #8, #4 @ r9<- A 5791 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5792 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5793 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5794 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5795 .if 1 5796 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5797 beq common_errDivideByZero 5798 .endif 5799 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5800 5801 @ optional op; may set condition codes 5802 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5803 GET_INST_OPCODE(ip) @ extract opcode from rINST 5804 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5805 GOTO_OPCODE(ip) @ jump to next instruction 5806 /* 12-15 instructions */ 5807 5808 5809/* ------------------------------ */ 5810 .balign 64 5811.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5812/* File: armv6t2/OP_REM_LONG_2ADDR.S */ 5813/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 5814/* File: armv6t2/binopWide2addr.S */ 5815 /* 5816 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5817 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5818 * This could be an ARM instruction or a function call. (If the result 5819 * comes back in a register other than r0, you can override "result".) 5820 * 5821 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5822 * vCC (r1). Useful for integer division and modulus. 5823 * 5824 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5825 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5826 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5827 * rem-double/2addr 5828 */ 5829 /* binop/2addr vA, vB */ 5830 mov r1, rINST, lsr #12 @ r1<- B 5831 ubfx r9, rINST, #8, #4 @ r9<- A 5832 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5833 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5834 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5835 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5836 .if 1 5837 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5838 beq common_errDivideByZero 5839 .endif 5840 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5841 5842 @ optional op; may set condition codes 5843 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5844 GET_INST_OPCODE(ip) @ extract opcode from rINST 5845 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 5846 GOTO_OPCODE(ip) @ jump to next instruction 5847 /* 12-15 instructions */ 5848 5849 5850/* ------------------------------ */ 5851 .balign 64 5852.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 5853/* File: armv6t2/OP_AND_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 0 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 and r0, r0, r2 @ optional op; may set condition codes 5883 and r1, r1, r3 @ 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 .balign 64 5892.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 5893/* File: armv6t2/OP_OR_LONG_2ADDR.S */ 5894/* File: armv6t2/binopWide2addr.S */ 5895 /* 5896 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5897 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5898 * This could be an ARM instruction or a function call. (If the result 5899 * comes back in a register other than r0, you can override "result".) 5900 * 5901 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5902 * vCC (r1). Useful for integer division and modulus. 5903 * 5904 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5905 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5906 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5907 * rem-double/2addr 5908 */ 5909 /* binop/2addr vA, vB */ 5910 mov r1, rINST, lsr #12 @ r1<- B 5911 ubfx r9, rINST, #8, #4 @ r9<- A 5912 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5913 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5914 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5915 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5916 .if 0 5917 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5918 beq common_errDivideByZero 5919 .endif 5920 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5921 5922 orr r0, r0, r2 @ optional op; may set condition codes 5923 orr r1, r1, r3 @ result<- op, r0-r3 changed 5924 GET_INST_OPCODE(ip) @ extract opcode from rINST 5925 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5926 GOTO_OPCODE(ip) @ jump to next instruction 5927 /* 12-15 instructions */ 5928 5929 5930/* ------------------------------ */ 5931 .balign 64 5932.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 5933/* File: armv6t2/OP_XOR_LONG_2ADDR.S */ 5934/* File: armv6t2/binopWide2addr.S */ 5935 /* 5936 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5937 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5938 * This could be an ARM instruction or a function call. (If the result 5939 * comes back in a register other than r0, you can override "result".) 5940 * 5941 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5942 * vCC (r1). Useful for integer division and modulus. 5943 * 5944 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5945 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5946 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5947 * rem-double/2addr 5948 */ 5949 /* binop/2addr vA, vB */ 5950 mov r1, rINST, lsr #12 @ r1<- B 5951 ubfx r9, rINST, #8, #4 @ r9<- A 5952 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5953 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5954 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5955 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5956 .if 0 5957 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5958 beq common_errDivideByZero 5959 .endif 5960 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5961 5962 eor r0, r0, r2 @ optional op; may set condition codes 5963 eor r1, r1, r3 @ result<- op, r0-r3 changed 5964 GET_INST_OPCODE(ip) @ extract opcode from rINST 5965 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5966 GOTO_OPCODE(ip) @ jump to next instruction 5967 /* 12-15 instructions */ 5968 5969 5970/* ------------------------------ */ 5971 .balign 64 5972.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 5973/* File: armv6t2/OP_SHL_LONG_2ADDR.S */ 5974 /* 5975 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 5976 * 32-bit shift distance. 5977 */ 5978 /* shl-long/2addr vA, vB */ 5979 mov r3, rINST, lsr #12 @ r3<- B 5980 ubfx r9, rINST, #8, #4 @ r9<- A 5981 GET_VREG(r2, r3) @ r2<- vB 5982 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5983 and r2, r2, #63 @ r2<- r2 & 0x3f 5984 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5985 5986 mov r1, r1, asl r2 @ r1<- r1 << r2 5987 rsb r3, r2, #32 @ r3<- 32 - r2 5988 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 5989 subs ip, r2, #32 @ ip<- r2 - 32 5990 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5991 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 5992 mov r0, r0, asl r2 @ r0<- r0 << r2 5993 b .LOP_SHL_LONG_2ADDR_finish 5994 5995/* ------------------------------ */ 5996 .balign 64 5997.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 5998/* File: armv6t2/OP_SHR_LONG_2ADDR.S */ 5999 /* 6000 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6001 * 32-bit shift distance. 6002 */ 6003 /* shr-long/2addr vA, vB */ 6004 mov r3, rINST, lsr #12 @ r3<- B 6005 ubfx r9, rINST, #8, #4 @ r9<- A 6006 GET_VREG(r2, r3) @ r2<- vB 6007 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6008 and r2, r2, #63 @ r2<- r2 & 0x3f 6009 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6010 6011 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6012 rsb r3, r2, #32 @ r3<- 32 - r2 6013 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6014 subs ip, r2, #32 @ ip<- r2 - 32 6015 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6016 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6017 mov r1, r1, asr r2 @ r1<- r1 >> r2 6018 b .LOP_SHR_LONG_2ADDR_finish 6019 6020/* ------------------------------ */ 6021 .balign 64 6022.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6023/* File: armv6t2/OP_USHR_LONG_2ADDR.S */ 6024 /* 6025 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6026 * 32-bit shift distance. 6027 */ 6028 /* ushr-long/2addr vA, vB */ 6029 mov r3, rINST, lsr #12 @ r3<- B 6030 ubfx r9, rINST, #8, #4 @ r9<- A 6031 GET_VREG(r2, r3) @ r2<- vB 6032 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6033 and r2, r2, #63 @ r2<- r2 & 0x3f 6034 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6035 6036 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6037 rsb r3, r2, #32 @ r3<- 32 - r2 6038 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6039 subs ip, r2, #32 @ ip<- r2 - 32 6040 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6041 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6042 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6043 b .LOP_USHR_LONG_2ADDR_finish 6044 6045/* ------------------------------ */ 6046 .balign 64 6047.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6048/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */ 6049/* File: arm-vfp/fbinop2addr.S */ 6050 /* 6051 * Generic 32-bit floating point "/2addr" binary operation. Provide 6052 * an "instr" line that specifies an instruction that performs 6053 * "s2 = s0 op s1". 6054 * 6055 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6056 */ 6057 /* binop/2addr vA, vB */ 6058 mov r3, rINST, lsr #12 @ r3<- B 6059 mov r9, rINST, lsr #8 @ r9<- A+ 6060 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6061 and r9, r9, #15 @ r9<- A 6062 flds s1, [r3] @ s1<- vB 6063 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6064 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6065 flds s0, [r9] @ s0<- vA 6066 6067 fadds s2, s0, s1 @ s2<- op 6068 GET_INST_OPCODE(ip) @ extract opcode from rINST 6069 fsts s2, [r9] @ vAA<- s2 6070 GOTO_OPCODE(ip) @ jump to next instruction 6071 6072 6073/* ------------------------------ */ 6074 .balign 64 6075.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6076/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */ 6077/* File: arm-vfp/fbinop2addr.S */ 6078 /* 6079 * Generic 32-bit floating point "/2addr" binary operation. Provide 6080 * an "instr" line that specifies an instruction that performs 6081 * "s2 = s0 op s1". 6082 * 6083 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6084 */ 6085 /* binop/2addr vA, vB */ 6086 mov r3, rINST, lsr #12 @ r3<- B 6087 mov r9, rINST, lsr #8 @ r9<- A+ 6088 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6089 and r9, r9, #15 @ r9<- A 6090 flds s1, [r3] @ s1<- vB 6091 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6092 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6093 flds s0, [r9] @ s0<- vA 6094 6095 fsubs s2, s0, s1 @ s2<- op 6096 GET_INST_OPCODE(ip) @ extract opcode from rINST 6097 fsts s2, [r9] @ vAA<- s2 6098 GOTO_OPCODE(ip) @ jump to next instruction 6099 6100 6101/* ------------------------------ */ 6102 .balign 64 6103.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6104/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */ 6105/* File: arm-vfp/fbinop2addr.S */ 6106 /* 6107 * Generic 32-bit floating point "/2addr" binary operation. Provide 6108 * an "instr" line that specifies an instruction that performs 6109 * "s2 = s0 op s1". 6110 * 6111 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6112 */ 6113 /* binop/2addr vA, vB */ 6114 mov r3, rINST, lsr #12 @ r3<- B 6115 mov r9, rINST, lsr #8 @ r9<- A+ 6116 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6117 and r9, r9, #15 @ r9<- A 6118 flds s1, [r3] @ s1<- vB 6119 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6120 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6121 flds s0, [r9] @ s0<- vA 6122 6123 fmuls s2, s0, s1 @ s2<- op 6124 GET_INST_OPCODE(ip) @ extract opcode from rINST 6125 fsts s2, [r9] @ vAA<- s2 6126 GOTO_OPCODE(ip) @ jump to next instruction 6127 6128 6129/* ------------------------------ */ 6130 .balign 64 6131.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6132/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */ 6133/* File: arm-vfp/fbinop2addr.S */ 6134 /* 6135 * Generic 32-bit floating point "/2addr" binary operation. Provide 6136 * an "instr" line that specifies an instruction that performs 6137 * "s2 = s0 op s1". 6138 * 6139 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6140 */ 6141 /* binop/2addr vA, vB */ 6142 mov r3, rINST, lsr #12 @ r3<- B 6143 mov r9, rINST, lsr #8 @ r9<- A+ 6144 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6145 and r9, r9, #15 @ r9<- A 6146 flds s1, [r3] @ s1<- vB 6147 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6148 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6149 flds s0, [r9] @ s0<- vA 6150 6151 fdivs s2, s0, s1 @ s2<- op 6152 GET_INST_OPCODE(ip) @ extract opcode from rINST 6153 fsts s2, [r9] @ vAA<- s2 6154 GOTO_OPCODE(ip) @ jump to next instruction 6155 6156 6157/* ------------------------------ */ 6158 .balign 64 6159.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6160/* File: armv6t2/OP_REM_FLOAT_2ADDR.S */ 6161/* EABI doesn't define a float remainder function, but libm does */ 6162/* File: armv6t2/binop2addr.S */ 6163 /* 6164 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6165 * that specifies an instruction that performs "result = r0 op r1". 6166 * This could be an ARM instruction or a function call. (If the result 6167 * comes back in a register other than r0, you can override "result".) 6168 * 6169 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6170 * vCC (r1). Useful for integer division and modulus. 6171 * 6172 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6173 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6174 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6175 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6176 */ 6177 /* binop/2addr vA, vB */ 6178 mov r3, rINST, lsr #12 @ r3<- B 6179 ubfx r9, rINST, #8, #4 @ r9<- A 6180 GET_VREG(r1, r3) @ r1<- vB 6181 GET_VREG(r0, r9) @ r0<- vA 6182 .if 0 6183 cmp r1, #0 @ is second operand zero? 6184 beq common_errDivideByZero 6185 .endif 6186 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6187 6188 @ optional op; may set condition codes 6189 bl fmodf @ r0<- op, r0-r3 changed 6190 GET_INST_OPCODE(ip) @ extract opcode from rINST 6191 SET_VREG(r0, r9) @ vAA<- r0 6192 GOTO_OPCODE(ip) @ jump to next instruction 6193 /* 10-13 instructions */ 6194 6195 6196/* ------------------------------ */ 6197 .balign 64 6198.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6199/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */ 6200/* File: arm-vfp/fbinopWide2addr.S */ 6201 /* 6202 * Generic 64-bit floating point "/2addr" binary operation. Provide 6203 * an "instr" line that specifies an instruction that performs 6204 * "d2 = d0 op d1". 6205 * 6206 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6207 * div-double/2addr 6208 */ 6209 /* binop/2addr vA, vB */ 6210 mov r3, rINST, lsr #12 @ r3<- B 6211 mov r9, rINST, lsr #8 @ r9<- A+ 6212 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6213 and r9, r9, #15 @ r9<- A 6214 fldd d1, [r3] @ d1<- vB 6215 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6216 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6217 fldd d0, [r9] @ d0<- vA 6218 6219 faddd d2, d0, d1 @ d2<- op 6220 GET_INST_OPCODE(ip) @ extract opcode from rINST 6221 fstd d2, [r9] @ vAA<- d2 6222 GOTO_OPCODE(ip) @ jump to next instruction 6223 6224 6225/* ------------------------------ */ 6226 .balign 64 6227.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6228/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */ 6229/* File: arm-vfp/fbinopWide2addr.S */ 6230 /* 6231 * Generic 64-bit floating point "/2addr" binary operation. Provide 6232 * an "instr" line that specifies an instruction that performs 6233 * "d2 = d0 op d1". 6234 * 6235 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6236 * div-double/2addr 6237 */ 6238 /* binop/2addr vA, vB */ 6239 mov r3, rINST, lsr #12 @ r3<- B 6240 mov r9, rINST, lsr #8 @ r9<- A+ 6241 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6242 and r9, r9, #15 @ r9<- A 6243 fldd d1, [r3] @ d1<- vB 6244 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6245 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6246 fldd d0, [r9] @ d0<- vA 6247 6248 fsubd d2, d0, d1 @ d2<- op 6249 GET_INST_OPCODE(ip) @ extract opcode from rINST 6250 fstd d2, [r9] @ vAA<- d2 6251 GOTO_OPCODE(ip) @ jump to next instruction 6252 6253 6254/* ------------------------------ */ 6255 .balign 64 6256.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6257/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */ 6258/* File: arm-vfp/fbinopWide2addr.S */ 6259 /* 6260 * Generic 64-bit floating point "/2addr" binary operation. Provide 6261 * an "instr" line that specifies an instruction that performs 6262 * "d2 = d0 op d1". 6263 * 6264 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6265 * div-double/2addr 6266 */ 6267 /* binop/2addr vA, vB */ 6268 mov r3, rINST, lsr #12 @ r3<- B 6269 mov r9, rINST, lsr #8 @ r9<- A+ 6270 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6271 and r9, r9, #15 @ r9<- A 6272 fldd d1, [r3] @ d1<- vB 6273 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6274 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6275 fldd d0, [r9] @ d0<- vA 6276 6277 fmuld d2, d0, d1 @ d2<- op 6278 GET_INST_OPCODE(ip) @ extract opcode from rINST 6279 fstd d2, [r9] @ vAA<- d2 6280 GOTO_OPCODE(ip) @ jump to next instruction 6281 6282 6283/* ------------------------------ */ 6284 .balign 64 6285.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6286/* File: arm-vfp/OP_DIV_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 fdivd 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_REM_DOUBLE_2ADDR: /* 0xcf */ 6315/* File: armv6t2/OP_REM_DOUBLE_2ADDR.S */ 6316/* EABI doesn't define a double remainder function, but libm does */ 6317/* File: armv6t2/binopWide2addr.S */ 6318 /* 6319 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6320 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6321 * This could be an ARM instruction or a function call. (If the result 6322 * comes back in a register other than r0, you can override "result".) 6323 * 6324 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6325 * vCC (r1). Useful for integer division and modulus. 6326 * 6327 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6328 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6329 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6330 * rem-double/2addr 6331 */ 6332 /* binop/2addr vA, vB */ 6333 mov r1, rINST, lsr #12 @ r1<- B 6334 ubfx r9, rINST, #8, #4 @ r9<- A 6335 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6336 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6337 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6338 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6339 .if 0 6340 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6341 beq common_errDivideByZero 6342 .endif 6343 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6344 6345 @ optional op; may set condition codes 6346 bl fmod @ result<- op, r0-r3 changed 6347 GET_INST_OPCODE(ip) @ extract opcode from rINST 6348 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6349 GOTO_OPCODE(ip) @ jump to next instruction 6350 /* 12-15 instructions */ 6351 6352 6353/* ------------------------------ */ 6354 .balign 64 6355.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6356/* File: armv6t2/OP_ADD_INT_LIT16.S */ 6357/* File: armv6t2/binopLit16.S */ 6358 /* 6359 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6360 * that specifies an instruction that performs "result = r0 op r1". 6361 * This could be an ARM instruction or a function call. (If the result 6362 * comes back in a register other than r0, you can override "result".) 6363 * 6364 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6365 * vCC (r1). Useful for integer division and modulus. 6366 * 6367 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6368 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6369 */ 6370 /* binop/lit16 vA, vB, #+CCCC */ 6371 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6372 mov r2, rINST, lsr #12 @ r2<- B 6373 ubfx r9, rINST, #8, #4 @ r9<- A 6374 GET_VREG(r0, r2) @ r0<- vB 6375 .if 0 6376 cmp r1, #0 @ is second operand zero? 6377 beq common_errDivideByZero 6378 .endif 6379 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6380 6381 add r0, r0, r1 @ r0<- op, r0-r3 changed 6382 GET_INST_OPCODE(ip) @ extract opcode from rINST 6383 SET_VREG(r0, r9) @ vAA<- r0 6384 GOTO_OPCODE(ip) @ jump to next instruction 6385 /* 10-13 instructions */ 6386 6387 6388/* ------------------------------ */ 6389 .balign 64 6390.L_OP_RSUB_INT: /* 0xd1 */ 6391/* File: armv6t2/OP_RSUB_INT.S */ 6392/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6393/* File: armv6t2/binopLit16.S */ 6394 /* 6395 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6396 * that specifies an instruction that performs "result = r0 op r1". 6397 * This could be an ARM instruction or a function call. (If the result 6398 * comes back in a register other than r0, you can override "result".) 6399 * 6400 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6401 * vCC (r1). Useful for integer division and modulus. 6402 * 6403 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6404 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6405 */ 6406 /* binop/lit16 vA, vB, #+CCCC */ 6407 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6408 mov r2, rINST, lsr #12 @ r2<- B 6409 ubfx r9, rINST, #8, #4 @ r9<- A 6410 GET_VREG(r0, r2) @ r0<- vB 6411 .if 0 6412 cmp r1, #0 @ is second operand zero? 6413 beq common_errDivideByZero 6414 .endif 6415 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6416 6417 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6418 GET_INST_OPCODE(ip) @ extract opcode from rINST 6419 SET_VREG(r0, r9) @ vAA<- r0 6420 GOTO_OPCODE(ip) @ jump to next instruction 6421 /* 10-13 instructions */ 6422 6423 6424/* ------------------------------ */ 6425 .balign 64 6426.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6427/* File: armv6t2/OP_MUL_INT_LIT16.S */ 6428/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6429/* File: armv6t2/binopLit16.S */ 6430 /* 6431 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6432 * that specifies an instruction that performs "result = r0 op r1". 6433 * This could be an ARM instruction or a function call. (If the result 6434 * comes back in a register other than r0, you can override "result".) 6435 * 6436 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6437 * vCC (r1). Useful for integer division and modulus. 6438 * 6439 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6440 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6441 */ 6442 /* binop/lit16 vA, vB, #+CCCC */ 6443 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6444 mov r2, rINST, lsr #12 @ r2<- B 6445 ubfx r9, rINST, #8, #4 @ r9<- A 6446 GET_VREG(r0, r2) @ r0<- vB 6447 .if 0 6448 cmp r1, #0 @ is second operand zero? 6449 beq common_errDivideByZero 6450 .endif 6451 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6452 6453 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6454 GET_INST_OPCODE(ip) @ extract opcode from rINST 6455 SET_VREG(r0, r9) @ vAA<- r0 6456 GOTO_OPCODE(ip) @ jump to next instruction 6457 /* 10-13 instructions */ 6458 6459 6460/* ------------------------------ */ 6461 .balign 64 6462.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6463/* File: armv6t2/OP_DIV_INT_LIT16.S */ 6464/* File: armv6t2/binopLit16.S */ 6465 /* 6466 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6467 * that specifies an instruction that performs "result = r0 op r1". 6468 * This could be an ARM instruction or a function call. (If the result 6469 * comes back in a register other than r0, you can override "result".) 6470 * 6471 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6472 * vCC (r1). Useful for integer division and modulus. 6473 * 6474 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6475 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6476 */ 6477 /* binop/lit16 vA, vB, #+CCCC */ 6478 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6479 mov r2, rINST, lsr #12 @ r2<- B 6480 ubfx r9, rINST, #8, #4 @ r9<- A 6481 GET_VREG(r0, r2) @ r0<- vB 6482 .if 1 6483 cmp r1, #0 @ is second operand zero? 6484 beq common_errDivideByZero 6485 .endif 6486 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6487 6488 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6489 GET_INST_OPCODE(ip) @ extract opcode from rINST 6490 SET_VREG(r0, r9) @ vAA<- r0 6491 GOTO_OPCODE(ip) @ jump to next instruction 6492 /* 10-13 instructions */ 6493 6494 6495/* ------------------------------ */ 6496 .balign 64 6497.L_OP_REM_INT_LIT16: /* 0xd4 */ 6498/* File: armv6t2/OP_REM_INT_LIT16.S */ 6499/* idivmod returns quotient in r0 and remainder in r1 */ 6500/* File: armv6t2/binopLit16.S */ 6501 /* 6502 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6503 * that specifies an instruction that performs "result = r0 op r1". 6504 * This could be an ARM instruction or a function call. (If the result 6505 * comes back in a register other than r0, you can override "result".) 6506 * 6507 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6508 * vCC (r1). Useful for integer division and modulus. 6509 * 6510 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6511 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6512 */ 6513 /* binop/lit16 vA, vB, #+CCCC */ 6514 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6515 mov r2, rINST, lsr #12 @ r2<- B 6516 ubfx r9, rINST, #8, #4 @ r9<- A 6517 GET_VREG(r0, r2) @ r0<- vB 6518 .if 1 6519 cmp r1, #0 @ is second operand zero? 6520 beq common_errDivideByZero 6521 .endif 6522 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6523 6524 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6525 GET_INST_OPCODE(ip) @ extract opcode from rINST 6526 SET_VREG(r1, r9) @ vAA<- r1 6527 GOTO_OPCODE(ip) @ jump to next instruction 6528 /* 10-13 instructions */ 6529 6530 6531/* ------------------------------ */ 6532 .balign 64 6533.L_OP_AND_INT_LIT16: /* 0xd5 */ 6534/* File: armv6t2/OP_AND_INT_LIT16.S */ 6535/* File: armv6t2/binopLit16.S */ 6536 /* 6537 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6538 * that specifies an instruction that performs "result = r0 op r1". 6539 * This could be an ARM instruction or a function call. (If the result 6540 * comes back in a register other than r0, you can override "result".) 6541 * 6542 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6543 * vCC (r1). Useful for integer division and modulus. 6544 * 6545 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6546 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6547 */ 6548 /* binop/lit16 vA, vB, #+CCCC */ 6549 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6550 mov r2, rINST, lsr #12 @ r2<- B 6551 ubfx r9, rINST, #8, #4 @ r9<- A 6552 GET_VREG(r0, r2) @ r0<- vB 6553 .if 0 6554 cmp r1, #0 @ is second operand zero? 6555 beq common_errDivideByZero 6556 .endif 6557 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6558 6559 and r0, r0, r1 @ r0<- op, r0-r3 changed 6560 GET_INST_OPCODE(ip) @ extract opcode from rINST 6561 SET_VREG(r0, r9) @ vAA<- r0 6562 GOTO_OPCODE(ip) @ jump to next instruction 6563 /* 10-13 instructions */ 6564 6565 6566/* ------------------------------ */ 6567 .balign 64 6568.L_OP_OR_INT_LIT16: /* 0xd6 */ 6569/* File: armv6t2/OP_OR_INT_LIT16.S */ 6570/* File: armv6t2/binopLit16.S */ 6571 /* 6572 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6573 * that specifies an instruction that performs "result = r0 op r1". 6574 * This could be an ARM instruction or a function call. (If the result 6575 * comes back in a register other than r0, you can override "result".) 6576 * 6577 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6578 * vCC (r1). Useful for integer division and modulus. 6579 * 6580 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6581 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6582 */ 6583 /* binop/lit16 vA, vB, #+CCCC */ 6584 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6585 mov r2, rINST, lsr #12 @ r2<- B 6586 ubfx r9, rINST, #8, #4 @ r9<- A 6587 GET_VREG(r0, r2) @ r0<- vB 6588 .if 0 6589 cmp r1, #0 @ is second operand zero? 6590 beq common_errDivideByZero 6591 .endif 6592 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6593 6594 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6595 GET_INST_OPCODE(ip) @ extract opcode from rINST 6596 SET_VREG(r0, r9) @ vAA<- r0 6597 GOTO_OPCODE(ip) @ jump to next instruction 6598 /* 10-13 instructions */ 6599 6600 6601/* ------------------------------ */ 6602 .balign 64 6603.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6604/* File: armv6t2/OP_XOR_INT_LIT16.S */ 6605/* File: armv6t2/binopLit16.S */ 6606 /* 6607 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6608 * that specifies an instruction that performs "result = r0 op r1". 6609 * This could be an ARM instruction or a function call. (If the result 6610 * comes back in a register other than r0, you can override "result".) 6611 * 6612 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6613 * vCC (r1). Useful for integer division and modulus. 6614 * 6615 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6616 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6617 */ 6618 /* binop/lit16 vA, vB, #+CCCC */ 6619 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6620 mov r2, rINST, lsr #12 @ r2<- B 6621 ubfx r9, rINST, #8, #4 @ r9<- A 6622 GET_VREG(r0, r2) @ r0<- vB 6623 .if 0 6624 cmp r1, #0 @ is second operand zero? 6625 beq common_errDivideByZero 6626 .endif 6627 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6628 6629 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6630 GET_INST_OPCODE(ip) @ extract opcode from rINST 6631 SET_VREG(r0, r9) @ vAA<- r0 6632 GOTO_OPCODE(ip) @ jump to next instruction 6633 /* 10-13 instructions */ 6634 6635 6636/* ------------------------------ */ 6637 .balign 64 6638.L_OP_ADD_INT_LIT8: /* 0xd8 */ 6639/* File: armv5te/OP_ADD_INT_LIT8.S */ 6640/* File: armv5te/binopLit8.S */ 6641 /* 6642 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6643 * that specifies an instruction that performs "result = r0 op r1". 6644 * This could be an ARM instruction or a function call. (If the result 6645 * comes back in a register other than r0, you can override "result".) 6646 * 6647 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6648 * vCC (r1). Useful for integer division and modulus. 6649 * 6650 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6651 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6652 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6653 */ 6654 /* binop/lit8 vAA, vBB, #+CC */ 6655 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6656 mov r9, rINST, lsr #8 @ r9<- AA 6657 and r2, r3, #255 @ r2<- BB 6658 GET_VREG(r0, r2) @ r0<- vBB 6659 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6660 .if 0 6661 @cmp r1, #0 @ is second operand zero? 6662 beq common_errDivideByZero 6663 .endif 6664 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6665 6666 @ optional op; may set condition codes 6667 add r0, r0, r1 @ r0<- op, r0-r3 changed 6668 GET_INST_OPCODE(ip) @ extract opcode from rINST 6669 SET_VREG(r0, r9) @ vAA<- r0 6670 GOTO_OPCODE(ip) @ jump to next instruction 6671 /* 10-12 instructions */ 6672 6673 6674/* ------------------------------ */ 6675 .balign 64 6676.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 6677/* File: armv5te/OP_RSUB_INT_LIT8.S */ 6678/* File: armv5te/binopLit8.S */ 6679 /* 6680 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6681 * that specifies an instruction that performs "result = r0 op r1". 6682 * This could be an ARM instruction or a function call. (If the result 6683 * comes back in a register other than r0, you can override "result".) 6684 * 6685 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6686 * vCC (r1). Useful for integer division and modulus. 6687 * 6688 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6689 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6690 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6691 */ 6692 /* binop/lit8 vAA, vBB, #+CC */ 6693 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6694 mov r9, rINST, lsr #8 @ r9<- AA 6695 and r2, r3, #255 @ r2<- BB 6696 GET_VREG(r0, r2) @ r0<- vBB 6697 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6698 .if 0 6699 @cmp r1, #0 @ is second operand zero? 6700 beq common_errDivideByZero 6701 .endif 6702 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6703 6704 @ optional op; may set condition codes 6705 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6706 GET_INST_OPCODE(ip) @ extract opcode from rINST 6707 SET_VREG(r0, r9) @ vAA<- r0 6708 GOTO_OPCODE(ip) @ jump to next instruction 6709 /* 10-12 instructions */ 6710 6711 6712/* ------------------------------ */ 6713 .balign 64 6714.L_OP_MUL_INT_LIT8: /* 0xda */ 6715/* File: armv5te/OP_MUL_INT_LIT8.S */ 6716/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6717/* File: armv5te/binopLit8.S */ 6718 /* 6719 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6720 * that specifies an instruction that performs "result = r0 op r1". 6721 * This could be an ARM instruction or a function call. (If the result 6722 * comes back in a register other than r0, you can override "result".) 6723 * 6724 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6725 * vCC (r1). Useful for integer division and modulus. 6726 * 6727 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6728 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6729 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6730 */ 6731 /* binop/lit8 vAA, vBB, #+CC */ 6732 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6733 mov r9, rINST, lsr #8 @ r9<- AA 6734 and r2, r3, #255 @ r2<- BB 6735 GET_VREG(r0, r2) @ r0<- vBB 6736 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6737 .if 0 6738 @cmp r1, #0 @ is second operand zero? 6739 beq common_errDivideByZero 6740 .endif 6741 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6742 6743 @ optional op; may set condition codes 6744 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6745 GET_INST_OPCODE(ip) @ extract opcode from rINST 6746 SET_VREG(r0, r9) @ vAA<- r0 6747 GOTO_OPCODE(ip) @ jump to next instruction 6748 /* 10-12 instructions */ 6749 6750 6751/* ------------------------------ */ 6752 .balign 64 6753.L_OP_DIV_INT_LIT8: /* 0xdb */ 6754/* File: armv5te/OP_DIV_INT_LIT8.S */ 6755/* File: armv5te/binopLit8.S */ 6756 /* 6757 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6758 * that specifies an instruction that performs "result = r0 op r1". 6759 * This could be an ARM instruction or a function call. (If the result 6760 * comes back in a register other than r0, you can override "result".) 6761 * 6762 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6763 * vCC (r1). Useful for integer division and modulus. 6764 * 6765 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6766 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6767 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6768 */ 6769 /* binop/lit8 vAA, vBB, #+CC */ 6770 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6771 mov r9, rINST, lsr #8 @ r9<- AA 6772 and r2, r3, #255 @ r2<- BB 6773 GET_VREG(r0, r2) @ r0<- vBB 6774 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6775 .if 1 6776 @cmp r1, #0 @ is second operand zero? 6777 beq common_errDivideByZero 6778 .endif 6779 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6780 6781 @ optional op; may set condition codes 6782 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6783 GET_INST_OPCODE(ip) @ extract opcode from rINST 6784 SET_VREG(r0, r9) @ vAA<- r0 6785 GOTO_OPCODE(ip) @ jump to next instruction 6786 /* 10-12 instructions */ 6787 6788 6789/* ------------------------------ */ 6790 .balign 64 6791.L_OP_REM_INT_LIT8: /* 0xdc */ 6792/* File: armv5te/OP_REM_INT_LIT8.S */ 6793/* idivmod returns quotient in r0 and remainder in r1 */ 6794/* File: armv5te/binopLit8.S */ 6795 /* 6796 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6797 * that specifies an instruction that performs "result = r0 op r1". 6798 * This could be an ARM instruction or a function call. (If the result 6799 * comes back in a register other than r0, you can override "result".) 6800 * 6801 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6802 * vCC (r1). Useful for integer division and modulus. 6803 * 6804 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6805 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6806 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6807 */ 6808 /* binop/lit8 vAA, vBB, #+CC */ 6809 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6810 mov r9, rINST, lsr #8 @ r9<- AA 6811 and r2, r3, #255 @ r2<- BB 6812 GET_VREG(r0, r2) @ r0<- vBB 6813 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6814 .if 1 6815 @cmp r1, #0 @ is second operand zero? 6816 beq common_errDivideByZero 6817 .endif 6818 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6819 6820 @ optional op; may set condition codes 6821 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6822 GET_INST_OPCODE(ip) @ extract opcode from rINST 6823 SET_VREG(r1, r9) @ vAA<- r1 6824 GOTO_OPCODE(ip) @ jump to next instruction 6825 /* 10-12 instructions */ 6826 6827 6828/* ------------------------------ */ 6829 .balign 64 6830.L_OP_AND_INT_LIT8: /* 0xdd */ 6831/* File: armv5te/OP_AND_INT_LIT8.S */ 6832/* File: armv5te/binopLit8.S */ 6833 /* 6834 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6835 * that specifies an instruction that performs "result = r0 op r1". 6836 * This could be an ARM instruction or a function call. (If the result 6837 * comes back in a register other than r0, you can override "result".) 6838 * 6839 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6840 * vCC (r1). Useful for integer division and modulus. 6841 * 6842 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6843 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6844 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6845 */ 6846 /* binop/lit8 vAA, vBB, #+CC */ 6847 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6848 mov r9, rINST, lsr #8 @ r9<- AA 6849 and r2, r3, #255 @ r2<- BB 6850 GET_VREG(r0, r2) @ r0<- vBB 6851 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6852 .if 0 6853 @cmp r1, #0 @ is second operand zero? 6854 beq common_errDivideByZero 6855 .endif 6856 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6857 6858 @ optional op; may set condition codes 6859 and r0, r0, r1 @ r0<- op, r0-r3 changed 6860 GET_INST_OPCODE(ip) @ extract opcode from rINST 6861 SET_VREG(r0, r9) @ vAA<- r0 6862 GOTO_OPCODE(ip) @ jump to next instruction 6863 /* 10-12 instructions */ 6864 6865 6866/* ------------------------------ */ 6867 .balign 64 6868.L_OP_OR_INT_LIT8: /* 0xde */ 6869/* File: armv5te/OP_OR_INT_LIT8.S */ 6870/* File: armv5te/binopLit8.S */ 6871 /* 6872 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6873 * that specifies an instruction that performs "result = r0 op r1". 6874 * This could be an ARM instruction or a function call. (If the result 6875 * comes back in a register other than r0, you can override "result".) 6876 * 6877 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6878 * vCC (r1). Useful for integer division and modulus. 6879 * 6880 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6881 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6882 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6883 */ 6884 /* binop/lit8 vAA, vBB, #+CC */ 6885 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6886 mov r9, rINST, lsr #8 @ r9<- AA 6887 and r2, r3, #255 @ r2<- BB 6888 GET_VREG(r0, r2) @ r0<- vBB 6889 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6890 .if 0 6891 @cmp r1, #0 @ is second operand zero? 6892 beq common_errDivideByZero 6893 .endif 6894 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6895 6896 @ optional op; may set condition codes 6897 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6898 GET_INST_OPCODE(ip) @ extract opcode from rINST 6899 SET_VREG(r0, r9) @ vAA<- r0 6900 GOTO_OPCODE(ip) @ jump to next instruction 6901 /* 10-12 instructions */ 6902 6903 6904/* ------------------------------ */ 6905 .balign 64 6906.L_OP_XOR_INT_LIT8: /* 0xdf */ 6907/* File: armv5te/OP_XOR_INT_LIT8.S */ 6908/* File: armv5te/binopLit8.S */ 6909 /* 6910 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6911 * that specifies an instruction that performs "result = r0 op r1". 6912 * This could be an ARM instruction or a function call. (If the result 6913 * comes back in a register other than r0, you can override "result".) 6914 * 6915 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6916 * vCC (r1). Useful for integer division and modulus. 6917 * 6918 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6919 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6920 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6921 */ 6922 /* binop/lit8 vAA, vBB, #+CC */ 6923 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6924 mov r9, rINST, lsr #8 @ r9<- AA 6925 and r2, r3, #255 @ r2<- BB 6926 GET_VREG(r0, r2) @ r0<- vBB 6927 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6928 .if 0 6929 @cmp r1, #0 @ is second operand zero? 6930 beq common_errDivideByZero 6931 .endif 6932 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6933 6934 @ optional op; may set condition codes 6935 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6936 GET_INST_OPCODE(ip) @ extract opcode from rINST 6937 SET_VREG(r0, r9) @ vAA<- r0 6938 GOTO_OPCODE(ip) @ jump to next instruction 6939 /* 10-12 instructions */ 6940 6941 6942/* ------------------------------ */ 6943 .balign 64 6944.L_OP_SHL_INT_LIT8: /* 0xe0 */ 6945/* File: armv5te/OP_SHL_INT_LIT8.S */ 6946/* File: armv5te/binopLit8.S */ 6947 /* 6948 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6949 * that specifies an instruction that performs "result = r0 op r1". 6950 * This could be an ARM instruction or a function call. (If the result 6951 * comes back in a register other than r0, you can override "result".) 6952 * 6953 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6954 * vCC (r1). Useful for integer division and modulus. 6955 * 6956 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6957 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6958 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6959 */ 6960 /* binop/lit8 vAA, vBB, #+CC */ 6961 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6962 mov r9, rINST, lsr #8 @ r9<- AA 6963 and r2, r3, #255 @ r2<- BB 6964 GET_VREG(r0, r2) @ r0<- vBB 6965 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6966 .if 0 6967 @cmp r1, #0 @ is second operand zero? 6968 beq common_errDivideByZero 6969 .endif 6970 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6971 6972 and r1, r1, #31 @ optional op; may set condition codes 6973 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 6974 GET_INST_OPCODE(ip) @ extract opcode from rINST 6975 SET_VREG(r0, r9) @ vAA<- r0 6976 GOTO_OPCODE(ip) @ jump to next instruction 6977 /* 10-12 instructions */ 6978 6979 6980/* ------------------------------ */ 6981 .balign 64 6982.L_OP_SHR_INT_LIT8: /* 0xe1 */ 6983/* File: armv5te/OP_SHR_INT_LIT8.S */ 6984/* File: armv5te/binopLit8.S */ 6985 /* 6986 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6987 * that specifies an instruction that performs "result = r0 op r1". 6988 * This could be an ARM instruction or a function call. (If the result 6989 * comes back in a register other than r0, you can override "result".) 6990 * 6991 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6992 * vCC (r1). Useful for integer division and modulus. 6993 * 6994 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6995 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6996 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6997 */ 6998 /* binop/lit8 vAA, vBB, #+CC */ 6999 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7000 mov r9, rINST, lsr #8 @ r9<- AA 7001 and r2, r3, #255 @ r2<- BB 7002 GET_VREG(r0, r2) @ r0<- vBB 7003 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7004 .if 0 7005 @cmp r1, #0 @ is second operand zero? 7006 beq common_errDivideByZero 7007 .endif 7008 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7009 7010 and r1, r1, #31 @ optional op; may set condition codes 7011 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7012 GET_INST_OPCODE(ip) @ extract opcode from rINST 7013 SET_VREG(r0, r9) @ vAA<- r0 7014 GOTO_OPCODE(ip) @ jump to next instruction 7015 /* 10-12 instructions */ 7016 7017 7018/* ------------------------------ */ 7019 .balign 64 7020.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7021/* File: armv5te/OP_USHR_INT_LIT8.S */ 7022/* File: armv5te/binopLit8.S */ 7023 /* 7024 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7025 * that specifies an instruction that performs "result = r0 op r1". 7026 * This could be an ARM instruction or a function call. (If the result 7027 * comes back in a register other than r0, you can override "result".) 7028 * 7029 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7030 * vCC (r1). Useful for integer division and modulus. 7031 * 7032 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7033 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7034 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7035 */ 7036 /* binop/lit8 vAA, vBB, #+CC */ 7037 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7038 mov r9, rINST, lsr #8 @ r9<- AA 7039 and r2, r3, #255 @ r2<- BB 7040 GET_VREG(r0, r2) @ r0<- vBB 7041 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7042 .if 0 7043 @cmp r1, #0 @ is second operand zero? 7044 beq common_errDivideByZero 7045 .endif 7046 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7047 7048 and r1, r1, #31 @ optional op; may set condition codes 7049 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7050 GET_INST_OPCODE(ip) @ extract opcode from rINST 7051 SET_VREG(r0, r9) @ vAA<- r0 7052 GOTO_OPCODE(ip) @ jump to next instruction 7053 /* 10-12 instructions */ 7054 7055 7056/* ------------------------------ */ 7057 .balign 64 7058.L_OP_IGET_VOLATILE: /* 0xe3 */ 7059/* File: armv5te/OP_IGET_VOLATILE.S */ 7060/* File: armv5te/OP_IGET.S */ 7061 /* 7062 * General 32-bit instance field get. 7063 * 7064 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7065 */ 7066 /* op vA, vB, field@CCCC */ 7067 mov r0, rINST, lsr #12 @ r0<- B 7068 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7069 FETCH(r1, 1) @ r1<- field ref CCCC 7070 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7071 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7072 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7073 cmp r0, #0 @ is resolved entry null? 7074 bne .LOP_IGET_VOLATILE_finish @ no, already resolved 70758: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7076 EXPORT_PC() @ resolve() could throw 7077 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7078 bl dvmResolveInstField @ r0<- resolved InstField ptr 7079 cmp r0, #0 7080 bne .LOP_IGET_VOLATILE_finish 7081 b common_exceptionThrown 7082 7083 7084/* ------------------------------ */ 7085 .balign 64 7086.L_OP_IPUT_VOLATILE: /* 0xe4 */ 7087/* File: armv5te/OP_IPUT_VOLATILE.S */ 7088/* File: armv5te/OP_IPUT.S */ 7089 /* 7090 * General 32-bit instance field put. 7091 * 7092 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 7093 */ 7094 /* op vA, vB, field@CCCC */ 7095 mov r0, rINST, lsr #12 @ r0<- B 7096 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7097 FETCH(r1, 1) @ r1<- field ref CCCC 7098 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7099 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7100 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7101 cmp r0, #0 @ is resolved entry null? 7102 bne .LOP_IPUT_VOLATILE_finish @ no, already resolved 71038: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7104 EXPORT_PC() @ resolve() could throw 7105 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7106 bl dvmResolveInstField @ r0<- resolved InstField ptr 7107 cmp r0, #0 @ success? 7108 bne .LOP_IPUT_VOLATILE_finish @ yes, finish up 7109 b common_exceptionThrown 7110 7111 7112/* ------------------------------ */ 7113 .balign 64 7114.L_OP_SGET_VOLATILE: /* 0xe5 */ 7115/* File: armv5te/OP_SGET_VOLATILE.S */ 7116/* File: armv5te/OP_SGET.S */ 7117 /* 7118 * General 32-bit SGET handler. 7119 * 7120 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7121 */ 7122 /* op vAA, field@BBBB */ 7123 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7124 FETCH(r1, 1) @ r1<- field ref BBBB 7125 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7126 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7127 cmp r0, #0 @ is resolved entry null? 7128 beq .LOP_SGET_VOLATILE_resolve @ yes, do resolve 7129.LOP_SGET_VOLATILE_finish: @ field ptr in r0 7130 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7131 SMP_DMB @ acquiring load 7132 mov r2, rINST, lsr #8 @ r2<- AA 7133 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7134 SET_VREG(r1, r2) @ fp[AA]<- r1 7135 GET_INST_OPCODE(ip) @ extract opcode from rINST 7136 GOTO_OPCODE(ip) @ jump to next instruction 7137 7138 7139/* ------------------------------ */ 7140 .balign 64 7141.L_OP_SPUT_VOLATILE: /* 0xe6 */ 7142/* File: armv5te/OP_SPUT_VOLATILE.S */ 7143/* File: armv5te/OP_SPUT.S */ 7144 /* 7145 * General 32-bit SPUT handler. 7146 * 7147 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 7148 */ 7149 /* op vAA, field@BBBB */ 7150 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7151 FETCH(r1, 1) @ r1<- field ref BBBB 7152 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7153 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7154 cmp r0, #0 @ is resolved entry null? 7155 beq .LOP_SPUT_VOLATILE_resolve @ yes, do resolve 7156.LOP_SPUT_VOLATILE_finish: @ field ptr in r0 7157 mov r2, rINST, lsr #8 @ r2<- AA 7158 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7159 GET_VREG(r1, r2) @ r1<- fp[AA] 7160 GET_INST_OPCODE(ip) @ extract opcode from rINST 7161 SMP_DMB @ releasing store 7162 str r1, [r0, #offStaticField_value] @ field<- vAA 7163 GOTO_OPCODE(ip) @ jump to next instruction 7164 7165 7166/* ------------------------------ */ 7167 .balign 64 7168.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ 7169/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */ 7170/* File: armv5te/OP_IGET.S */ 7171 /* 7172 * General 32-bit instance field get. 7173 * 7174 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7175 */ 7176 /* op vA, vB, field@CCCC */ 7177 mov r0, rINST, lsr #12 @ r0<- B 7178 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7179 FETCH(r1, 1) @ r1<- field ref CCCC 7180 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7181 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7182 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7183 cmp r0, #0 @ is resolved entry null? 7184 bne .LOP_IGET_OBJECT_VOLATILE_finish @ no, already resolved 71858: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7186 EXPORT_PC() @ resolve() could throw 7187 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7188 bl dvmResolveInstField @ r0<- resolved InstField ptr 7189 cmp r0, #0 7190 bne .LOP_IGET_OBJECT_VOLATILE_finish 7191 b common_exceptionThrown 7192 7193 7194/* ------------------------------ */ 7195 .balign 64 7196.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */ 7197/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */ 7198/* File: armv5te/OP_IGET_WIDE.S */ 7199 /* 7200 * Wide 32-bit instance field get. 7201 */ 7202 /* iget-wide vA, vB, field@CCCC */ 7203 mov r0, rINST, lsr #12 @ r0<- B 7204 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7205 FETCH(r1, 1) @ r1<- field ref CCCC 7206 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7207 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7208 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7209 cmp r0, #0 @ is resolved entry null? 7210 bne .LOP_IGET_WIDE_VOLATILE_finish @ no, already resolved 72118: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7212 EXPORT_PC() @ resolve() could throw 7213 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7214 bl dvmResolveInstField @ r0<- resolved InstField ptr 7215 cmp r0, #0 7216 bne .LOP_IGET_WIDE_VOLATILE_finish 7217 b common_exceptionThrown 7218 7219 7220/* ------------------------------ */ 7221 .balign 64 7222.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */ 7223/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */ 7224/* File: armv5te/OP_IPUT_WIDE.S */ 7225 /* iput-wide vA, vB, field@CCCC */ 7226 mov r0, rINST, lsr #12 @ r0<- B 7227 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7228 FETCH(r1, 1) @ r1<- field ref CCCC 7229 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7230 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7231 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7232 cmp r0, #0 @ is resolved entry null? 7233 bne .LOP_IPUT_WIDE_VOLATILE_finish @ no, already resolved 72348: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7235 EXPORT_PC() @ resolve() could throw 7236 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7237 bl dvmResolveInstField @ r0<- resolved InstField ptr 7238 cmp r0, #0 @ success? 7239 bne .LOP_IPUT_WIDE_VOLATILE_finish @ yes, finish up 7240 b common_exceptionThrown 7241 7242 7243/* ------------------------------ */ 7244 .balign 64 7245.L_OP_SGET_WIDE_VOLATILE: /* 0xea */ 7246/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */ 7247/* File: armv5te/OP_SGET_WIDE.S */ 7248 /* 7249 * 64-bit SGET handler. 7250 */ 7251 /* sget-wide vAA, field@BBBB */ 7252 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7253 FETCH(r1, 1) @ r1<- field ref BBBB 7254 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7255 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7256 cmp r0, #0 @ is resolved entry null? 7257 beq .LOP_SGET_WIDE_VOLATILE_resolve @ yes, do resolve 7258.LOP_SGET_WIDE_VOLATILE_finish: 7259 mov r9, rINST, lsr #8 @ r9<- AA 7260 .if 1 7261 add r0, r0, #offStaticField_value @ r0<- pointer to data 7262 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 7263 .else 7264 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 7265 .endif 7266 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7267 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7268 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 7269 GET_INST_OPCODE(ip) @ extract opcode from rINST 7270 GOTO_OPCODE(ip) @ jump to next instruction 7271 7272 7273/* ------------------------------ */ 7274 .balign 64 7275.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */ 7276/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */ 7277/* File: armv5te/OP_SPUT_WIDE.S */ 7278 /* 7279 * 64-bit SPUT handler. 7280 */ 7281 /* sput-wide vAA, field@BBBB */ 7282 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 7283 FETCH(r1, 1) @ r1<- field ref BBBB 7284 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 7285 mov r9, rINST, lsr #8 @ r9<- AA 7286 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 7287 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7288 cmp r2, #0 @ is resolved entry null? 7289 beq .LOP_SPUT_WIDE_VOLATILE_resolve @ yes, do resolve 7290.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9 7291 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7292 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 7293 GET_INST_OPCODE(r10) @ extract opcode from rINST 7294 .if 1 7295 add r2, r2, #offStaticField_value @ r2<- pointer to data 7296 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 7297 .else 7298 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 7299 .endif 7300 GOTO_OPCODE(r10) @ jump to next instruction 7301 7302 7303/* ------------------------------ */ 7304 .balign 64 7305.L_OP_BREAKPOINT: /* 0xec */ 7306/* File: armv5te/OP_BREAKPOINT.S */ 7307/* File: armv5te/unused.S */ 7308 bl common_abort 7309 7310 7311/* ------------------------------ */ 7312 .balign 64 7313.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7314/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7315 /* 7316 * Handle a throw-verification-error instruction. This throws an 7317 * exception for an error discovered during verification. The 7318 * exception is indicated by AA, with some detail provided by BBBB. 7319 */ 7320 /* op AA, ref@BBBB */ 7321 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7322 FETCH(r2, 1) @ r2<- BBBB 7323 EXPORT_PC() @ export the PC 7324 mov r1, rINST, lsr #8 @ r1<- AA 7325 bl dvmThrowVerificationError @ always throws 7326 b common_exceptionThrown @ handle exception 7327 7328/* ------------------------------ */ 7329 .balign 64 7330.L_OP_EXECUTE_INLINE: /* 0xee */ 7331/* File: armv5te/OP_EXECUTE_INLINE.S */ 7332 /* 7333 * Execute a "native inline" instruction. 7334 * 7335 * We need to call an InlineOp4Func: 7336 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7337 * 7338 * The first four args are in r0-r3, pointer to return value storage 7339 * is on the stack. The function's return value is a flag that tells 7340 * us if an exception was thrown. 7341 */ 7342 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7343 FETCH(r10, 1) @ r10<- BBBB 7344 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7345 EXPORT_PC() @ can throw 7346 sub sp, sp, #8 @ make room for arg, +64 bit align 7347 mov r0, rINST, lsr #12 @ r0<- B 7348 str r1, [sp] @ push &glue->retval 7349 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7350 add sp, sp, #8 @ pop stack 7351 cmp r0, #0 @ test boolean result of inline 7352 beq common_exceptionThrown @ returned false, handle exception 7353 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7354 GET_INST_OPCODE(ip) @ extract opcode from rINST 7355 GOTO_OPCODE(ip) @ jump to next instruction 7356 7357/* ------------------------------ */ 7358 .balign 64 7359.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ 7360/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */ 7361 /* 7362 * Execute a "native inline" instruction, using "/range" semantics. 7363 * Same idea as execute-inline, but we get the args differently. 7364 * 7365 * We need to call an InlineOp4Func: 7366 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7367 * 7368 * The first four args are in r0-r3, pointer to return value storage 7369 * is on the stack. The function's return value is a flag that tells 7370 * us if an exception was thrown. 7371 */ 7372 /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */ 7373 FETCH(r10, 1) @ r10<- BBBB 7374 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7375 EXPORT_PC() @ can throw 7376 sub sp, sp, #8 @ make room for arg, +64 bit align 7377 mov r0, rINST, lsr #8 @ r0<- AA 7378 str r1, [sp] @ push &glue->retval 7379 bl .LOP_EXECUTE_INLINE_RANGE_continue @ make call; will return after 7380 add sp, sp, #8 @ pop stack 7381 cmp r0, #0 @ test boolean result of inline 7382 beq common_exceptionThrown @ returned false, handle exception 7383 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7384 GET_INST_OPCODE(ip) @ extract opcode from rINST 7385 GOTO_OPCODE(ip) @ jump to next instruction 7386 7387/* ------------------------------ */ 7388 .balign 64 7389.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7390/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7391 /* 7392 * invoke-direct-empty is a no-op in a "standard" interpreter. 7393 */ 7394 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7395 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7396 GOTO_OPCODE(ip) @ execute it 7397 7398/* ------------------------------ */ 7399 .balign 64 7400.L_OP_UNUSED_F1: /* 0xf1 */ 7401/* File: armv5te/OP_UNUSED_F1.S */ 7402/* File: armv5te/unused.S */ 7403 bl common_abort 7404 7405 7406/* ------------------------------ */ 7407 .balign 64 7408.L_OP_IGET_QUICK: /* 0xf2 */ 7409/* File: armv6t2/OP_IGET_QUICK.S */ 7410 /* For: iget-quick, iget-object-quick */ 7411 /* op vA, vB, offset@CCCC */ 7412 mov r2, rINST, lsr #12 @ r2<- B 7413 FETCH(r1, 1) @ r1<- field byte offset 7414 GET_VREG(r3, r2) @ r3<- object we're operating on 7415 ubfx r2, rINST, #8, #4 @ r2<- A 7416 cmp r3, #0 @ check object for null 7417 beq common_errNullObject @ object was null 7418 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7419 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7420 GET_INST_OPCODE(ip) @ extract opcode from rINST 7421 SET_VREG(r0, r2) @ fp[A]<- r0 7422 GOTO_OPCODE(ip) @ jump to next instruction 7423 7424/* ------------------------------ */ 7425 .balign 64 7426.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7427/* File: armv6t2/OP_IGET_WIDE_QUICK.S */ 7428 /* iget-wide-quick vA, vB, offset@CCCC */ 7429 mov r2, rINST, lsr #12 @ r2<- B 7430 FETCH(ip, 1) @ ip<- 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 ldrd r0, [r3, ip] @ r0<- obj.field (64 bits, aligned) 7436 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7437 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7438 GET_INST_OPCODE(ip) @ extract opcode from rINST 7439 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7440 GOTO_OPCODE(ip) @ jump to next instruction 7441 7442/* ------------------------------ */ 7443 .balign 64 7444.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7445/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7446/* File: armv5te/OP_IGET_QUICK.S */ 7447 /* For: iget-quick, iget-object-quick */ 7448 /* op vA, vB, offset@CCCC */ 7449 mov r2, rINST, lsr #12 @ r2<- B 7450 GET_VREG(r3, r2) @ r3<- object we're operating on 7451 FETCH(r1, 1) @ r1<- field byte offset 7452 cmp r3, #0 @ check object for null 7453 mov r2, rINST, lsr #8 @ r2<- A(+) 7454 beq common_errNullObject @ object was null 7455 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7456 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7457 and r2, r2, #15 7458 GET_INST_OPCODE(ip) @ extract opcode from rINST 7459 SET_VREG(r0, r2) @ fp[A]<- r0 7460 GOTO_OPCODE(ip) @ jump to next instruction 7461 7462 7463/* ------------------------------ */ 7464 .balign 64 7465.L_OP_IPUT_QUICK: /* 0xf5 */ 7466/* File: armv6t2/OP_IPUT_QUICK.S */ 7467 /* For: iput-quick, iput-object-quick */ 7468 /* op vA, vB, offset@CCCC */ 7469 mov r2, rINST, lsr #12 @ r2<- B 7470 FETCH(r1, 1) @ r1<- field byte offset 7471 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7472 ubfx r2, rINST, #8, #4 @ r2<- A 7473 cmp r3, #0 @ check object for null 7474 beq common_errNullObject @ object was null 7475 GET_VREG(r0, r2) @ r0<- fp[A] 7476 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7477 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7478 GET_INST_OPCODE(ip) @ extract opcode from rINST 7479 GOTO_OPCODE(ip) @ jump to next instruction 7480 7481/* ------------------------------ */ 7482 .balign 64 7483.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7484/* File: armv6t2/OP_IPUT_WIDE_QUICK.S */ 7485 /* iput-wide-quick vA, vB, offset@CCCC */ 7486 mov r1, rINST, lsr #12 @ r1<- B 7487 ubfx r0, rINST, #8, #4 @ r0<- A 7488 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7489 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7490 cmp r2, #0 @ check object for null 7491 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7492 beq common_errNullObject @ object was null 7493 FETCH(r3, 1) @ r3<- field byte offset 7494 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7495 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7496 GET_INST_OPCODE(ip) @ extract opcode from rINST 7497 GOTO_OPCODE(ip) @ jump to next instruction 7498 7499/* ------------------------------ */ 7500 .balign 64 7501.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7502/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7503/* File: armv5te/OP_IPUT_QUICK.S */ 7504 /* For: iput-quick, iput-object-quick */ 7505 /* op vA, vB, offset@CCCC */ 7506 mov r2, rINST, lsr #12 @ r2<- B 7507 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7508 FETCH(r1, 1) @ r1<- field byte offset 7509 cmp r3, #0 @ check object for null 7510 mov r2, rINST, lsr #8 @ r2<- A(+) 7511 beq common_errNullObject @ object was null 7512 and r2, r2, #15 7513 GET_VREG(r0, r2) @ r0<- fp[A] 7514 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7515 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7516 GET_INST_OPCODE(ip) @ extract opcode from rINST 7517 GOTO_OPCODE(ip) @ jump to next instruction 7518 7519 7520/* ------------------------------ */ 7521 .balign 64 7522.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7523/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7524 /* 7525 * Handle an optimized virtual method call. 7526 * 7527 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7528 */ 7529 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7530 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7531 FETCH(r3, 2) @ r3<- FEDC or CCCC 7532 FETCH(r1, 1) @ r1<- BBBB 7533 .if (!0) 7534 and r3, r3, #15 @ r3<- C (or stays CCCC) 7535 .endif 7536 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7537 cmp r2, #0 @ is "this" null? 7538 beq common_errNullObject @ null "this", throw exception 7539 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7540 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7541 EXPORT_PC() @ invoke must export 7542 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7543 bl common_invokeMethodNoRange @ continue on 7544 7545/* ------------------------------ */ 7546 .balign 64 7547.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7548/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7549/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7550 /* 7551 * Handle an optimized virtual method call. 7552 * 7553 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7554 */ 7555 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7556 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7557 FETCH(r3, 2) @ r3<- FEDC or CCCC 7558 FETCH(r1, 1) @ r1<- BBBB 7559 .if (!1) 7560 and r3, r3, #15 @ r3<- C (or stays CCCC) 7561 .endif 7562 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7563 cmp r2, #0 @ is "this" null? 7564 beq common_errNullObject @ null "this", throw exception 7565 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7566 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7567 EXPORT_PC() @ invoke must export 7568 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7569 bl common_invokeMethodRange @ continue on 7570 7571 7572/* ------------------------------ */ 7573 .balign 64 7574.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7575/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7576 /* 7577 * Handle an optimized "super" method call. 7578 * 7579 * for: [opt] invoke-super-quick, invoke-super-quick/range 7580 */ 7581 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7582 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7583 FETCH(r10, 2) @ r10<- GFED or CCCC 7584 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7585 .if (!0) 7586 and r10, r10, #15 @ r10<- D (or stays CCCC) 7587 .endif 7588 FETCH(r1, 1) @ r1<- BBBB 7589 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7590 EXPORT_PC() @ must export for invoke 7591 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7592 GET_VREG(r3, r10) @ r3<- "this" 7593 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7594 cmp r3, #0 @ null "this" ref? 7595 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7596 beq common_errNullObject @ "this" is null, throw exception 7597 bl common_invokeMethodNoRange @ continue on 7598 7599/* ------------------------------ */ 7600 .balign 64 7601.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7602/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7603/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7604 /* 7605 * Handle an optimized "super" method call. 7606 * 7607 * for: [opt] invoke-super-quick, invoke-super-quick/range 7608 */ 7609 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7610 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7611 FETCH(r10, 2) @ r10<- GFED or CCCC 7612 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7613 .if (!1) 7614 and r10, r10, #15 @ r10<- D (or stays CCCC) 7615 .endif 7616 FETCH(r1, 1) @ r1<- BBBB 7617 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7618 EXPORT_PC() @ must export for invoke 7619 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7620 GET_VREG(r3, r10) @ r3<- "this" 7621 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7622 cmp r3, #0 @ null "this" ref? 7623 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7624 beq common_errNullObject @ "this" is null, throw exception 7625 bl common_invokeMethodRange @ continue on 7626 7627 7628/* ------------------------------ */ 7629 .balign 64 7630.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ 7631/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */ 7632/* File: armv5te/OP_IPUT.S */ 7633 /* 7634 * General 32-bit instance field put. 7635 * 7636 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 7637 */ 7638 /* op vA, vB, field@CCCC */ 7639 mov r0, rINST, lsr #12 @ r0<- B 7640 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7641 FETCH(r1, 1) @ r1<- field ref CCCC 7642 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7643 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7644 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7645 cmp r0, #0 @ is resolved entry null? 7646 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ no, already resolved 76478: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7648 EXPORT_PC() @ resolve() could throw 7649 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7650 bl dvmResolveInstField @ r0<- resolved InstField ptr 7651 cmp r0, #0 @ success? 7652 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ yes, finish up 7653 b common_exceptionThrown 7654 7655 7656/* ------------------------------ */ 7657 .balign 64 7658.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ 7659/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */ 7660/* File: armv5te/OP_SGET.S */ 7661 /* 7662 * General 32-bit SGET handler. 7663 * 7664 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7665 */ 7666 /* op vAA, field@BBBB */ 7667 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7668 FETCH(r1, 1) @ r1<- field ref BBBB 7669 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7670 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7671 cmp r0, #0 @ is resolved entry null? 7672 beq .LOP_SGET_OBJECT_VOLATILE_resolve @ yes, do resolve 7673.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0 7674 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7675 SMP_DMB @ acquiring load 7676 mov r2, rINST, lsr #8 @ r2<- AA 7677 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7678 SET_VREG(r1, r2) @ fp[AA]<- r1 7679 GET_INST_OPCODE(ip) @ extract opcode from rINST 7680 GOTO_OPCODE(ip) @ jump to next instruction 7681 7682 7683/* ------------------------------ */ 7684 .balign 64 7685.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ 7686/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */ 7687/* File: armv5te/OP_SPUT.S */ 7688 /* 7689 * General 32-bit SPUT handler. 7690 * 7691 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 7692 */ 7693 /* op vAA, field@BBBB */ 7694 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7695 FETCH(r1, 1) @ r1<- field ref BBBB 7696 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7697 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7698 cmp r0, #0 @ is resolved entry null? 7699 beq .LOP_SPUT_OBJECT_VOLATILE_resolve @ yes, do resolve 7700.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0 7701 mov r2, rINST, lsr #8 @ r2<- AA 7702 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7703 GET_VREG(r1, r2) @ r1<- fp[AA] 7704 GET_INST_OPCODE(ip) @ extract opcode from rINST 7705 SMP_DMB @ releasing store 7706 str r1, [r0, #offStaticField_value] @ field<- vAA 7707 GOTO_OPCODE(ip) @ jump to next instruction 7708 7709 7710/* ------------------------------ */ 7711 .balign 64 7712.L_OP_UNUSED_FF: /* 0xff */ 7713/* File: armv5te/OP_UNUSED_FF.S */ 7714/* File: armv5te/unused.S */ 7715 bl common_abort 7716 7717 7718 7719 .balign 64 7720 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7721 .global dvmAsmInstructionEnd 7722dvmAsmInstructionEnd: 7723 7724/* 7725 * =========================================================================== 7726 * Sister implementations 7727 * =========================================================================== 7728 */ 7729 .global dvmAsmSisterStart 7730 .type dvmAsmSisterStart, %function 7731 .text 7732 .balign 4 7733dvmAsmSisterStart: 7734 7735/* continuation for OP_CONST_STRING */ 7736 7737 /* 7738 * Continuation if the String has not yet been resolved. 7739 * r1: BBBB (String ref) 7740 * r9: target register 7741 */ 7742.LOP_CONST_STRING_resolve: 7743 EXPORT_PC() 7744 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7745 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7746 bl dvmResolveString @ r0<- String reference 7747 cmp r0, #0 @ failed? 7748 beq common_exceptionThrown @ yup, handle the exception 7749 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7750 GET_INST_OPCODE(ip) @ extract opcode from rINST 7751 SET_VREG(r0, r9) @ vAA<- r0 7752 GOTO_OPCODE(ip) @ jump to next instruction 7753 7754/* continuation for OP_CONST_STRING_JUMBO */ 7755 7756 /* 7757 * Continuation if the String has not yet been resolved. 7758 * r1: BBBBBBBB (String ref) 7759 * r9: target register 7760 */ 7761.LOP_CONST_STRING_JUMBO_resolve: 7762 EXPORT_PC() 7763 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7764 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7765 bl dvmResolveString @ r0<- String reference 7766 cmp r0, #0 @ failed? 7767 beq common_exceptionThrown @ yup, handle the exception 7768 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7769 GET_INST_OPCODE(ip) @ extract opcode from rINST 7770 SET_VREG(r0, r9) @ vAA<- r0 7771 GOTO_OPCODE(ip) @ jump to next instruction 7772 7773/* continuation for OP_CONST_CLASS */ 7774 7775 /* 7776 * Continuation if the Class has not yet been resolved. 7777 * r1: BBBB (Class ref) 7778 * r9: target register 7779 */ 7780.LOP_CONST_CLASS_resolve: 7781 EXPORT_PC() 7782 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7783 mov r2, #1 @ r2<- true 7784 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7785 bl dvmResolveClass @ r0<- Class reference 7786 cmp r0, #0 @ failed? 7787 beq common_exceptionThrown @ yup, handle the exception 7788 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7789 GET_INST_OPCODE(ip) @ extract opcode from rINST 7790 SET_VREG(r0, r9) @ vAA<- r0 7791 GOTO_OPCODE(ip) @ jump to next instruction 7792 7793/* continuation for OP_CHECK_CAST */ 7794 7795 /* 7796 * Trivial test failed, need to perform full check. This is common. 7797 * r0 holds obj->clazz 7798 * r1 holds class resolved from BBBB 7799 * r9 holds object 7800 */ 7801.LOP_CHECK_CAST_fullcheck: 7802 bl dvmInstanceofNonTrivial @ r0<- boolean result 7803 cmp r0, #0 @ failed? 7804 bne .LOP_CHECK_CAST_okay @ no, success 7805 7806 @ A cast has failed. We need to throw a ClassCastException with the 7807 @ class of the object that failed to be cast. 7808 EXPORT_PC() @ about to throw 7809 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 7810 ldr r0, .LstrClassCastExceptionPtr 7811 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 7812 bl dvmThrowExceptionWithClassMessage 7813 b common_exceptionThrown 7814 7815 /* 7816 * Resolution required. This is the least-likely path. 7817 * 7818 * r2 holds BBBB 7819 * r9 holds object 7820 */ 7821.LOP_CHECK_CAST_resolve: 7822 EXPORT_PC() @ resolve() could throw 7823 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7824 mov r1, r2 @ r1<- BBBB 7825 mov r2, #0 @ r2<- false 7826 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7827 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7828 cmp r0, #0 @ got null? 7829 beq common_exceptionThrown @ yes, handle exception 7830 mov r1, r0 @ r1<- class resolved from BBB 7831 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7832 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7833 7834.LstrClassCastExceptionPtr: 7835 .word .LstrClassCastException 7836 7837/* continuation for OP_INSTANCE_OF */ 7838 7839 /* 7840 * Trivial test failed, need to perform full check. This is common. 7841 * r0 holds obj->clazz 7842 * r1 holds class resolved from BBBB 7843 * r9 holds A 7844 */ 7845.LOP_INSTANCE_OF_fullcheck: 7846 bl dvmInstanceofNonTrivial @ r0<- boolean result 7847 @ fall through to OP_INSTANCE_OF_store 7848 7849 /* 7850 * r0 holds boolean result 7851 * r9 holds A 7852 */ 7853.LOP_INSTANCE_OF_store: 7854 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7855 SET_VREG(r0, r9) @ vA<- r0 7856 GET_INST_OPCODE(ip) @ extract opcode from rINST 7857 GOTO_OPCODE(ip) @ jump to next instruction 7858 7859 /* 7860 * Trivial test succeeded, save and bail. 7861 * r9 holds A 7862 */ 7863.LOP_INSTANCE_OF_trivial: 7864 mov r0, #1 @ indicate success 7865 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7866 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7867 SET_VREG(r0, r9) @ vA<- r0 7868 GET_INST_OPCODE(ip) @ extract opcode from rINST 7869 GOTO_OPCODE(ip) @ jump to next instruction 7870 7871 /* 7872 * Resolution required. This is the least-likely path. 7873 * 7874 * r3 holds BBBB 7875 * r9 holds A 7876 */ 7877.LOP_INSTANCE_OF_resolve: 7878 EXPORT_PC() @ resolve() could throw 7879 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7880 mov r1, r3 @ r1<- BBBB 7881 mov r2, #1 @ r2<- true 7882 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7883 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7884 cmp r0, #0 @ got null? 7885 beq common_exceptionThrown @ yes, handle exception 7886 mov r1, r0 @ r1<- class resolved from BBB 7887 mov r3, rINST, lsr #12 @ r3<- B 7888 GET_VREG(r0, r3) @ r0<- vB (object) 7889 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7890 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7891 7892/* continuation for OP_NEW_INSTANCE */ 7893 7894 .balign 32 @ minimize cache lines 7895.LOP_NEW_INSTANCE_finish: @ r0=new object 7896 mov r3, rINST, lsr #8 @ r3<- AA 7897 cmp r0, #0 @ failed? 7898 beq common_exceptionThrown @ yes, handle the exception 7899 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7900 GET_INST_OPCODE(ip) @ extract opcode from rINST 7901 SET_VREG(r0, r3) @ vAA<- r0 7902 GOTO_OPCODE(ip) @ jump to next instruction 7903 7904 /* 7905 * Class initialization required. 7906 * 7907 * r0 holds class object 7908 */ 7909.LOP_NEW_INSTANCE_needinit: 7910 mov r9, r0 @ save r0 7911 bl dvmInitClass @ initialize class 7912 cmp r0, #0 @ check boolean result 7913 mov r0, r9 @ restore r0 7914 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7915 b common_exceptionThrown @ failed, deal with init exception 7916 7917 /* 7918 * Resolution required. This is the least-likely path. 7919 * 7920 * r1 holds BBBB 7921 */ 7922.LOP_NEW_INSTANCE_resolve: 7923 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7924 mov r2, #0 @ r2<- false 7925 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7926 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7927 cmp r0, #0 @ got null? 7928 bne .LOP_NEW_INSTANCE_resolved @ no, continue 7929 b common_exceptionThrown @ yes, handle exception 7930 7931.LstrInstantiationErrorPtr: 7932 .word .LstrInstantiationError 7933 7934/* continuation for OP_NEW_ARRAY */ 7935 7936 7937 /* 7938 * Resolve class. (This is an uncommon case.) 7939 * 7940 * r1 holds array length 7941 * r2 holds class ref CCCC 7942 */ 7943.LOP_NEW_ARRAY_resolve: 7944 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7945 mov r9, r1 @ r9<- length (save) 7946 mov r1, r2 @ r1<- CCCC 7947 mov r2, #0 @ r2<- false 7948 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7949 bl dvmResolveClass @ r0<- call(clazz, ref) 7950 cmp r0, #0 @ got null? 7951 mov r1, r9 @ r1<- length (restore) 7952 beq common_exceptionThrown @ yes, handle exception 7953 @ fall through to OP_NEW_ARRAY_finish 7954 7955 /* 7956 * Finish allocation. 7957 * 7958 * r0 holds class 7959 * r1 holds array length 7960 */ 7961.LOP_NEW_ARRAY_finish: 7962 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 7963 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 7964 cmp r0, #0 @ failed? 7965 mov r2, rINST, lsr #8 @ r2<- A+ 7966 beq common_exceptionThrown @ yes, handle the exception 7967 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7968 and r2, r2, #15 @ r2<- A 7969 GET_INST_OPCODE(ip) @ extract opcode from rINST 7970 SET_VREG(r0, r2) @ vA<- r0 7971 GOTO_OPCODE(ip) @ jump to next instruction 7972 7973/* continuation for OP_FILLED_NEW_ARRAY */ 7974 7975 /* 7976 * On entry: 7977 * r0 holds array class 7978 * r10 holds AA or BA 7979 */ 7980.LOP_FILLED_NEW_ARRAY_continue: 7981 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 7982 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 7983 ldrb r3, [r3, #1] @ r3<- descriptor[1] 7984 .if 0 7985 mov r1, r10 @ r1<- AA (length) 7986 .else 7987 mov r1, r10, lsr #4 @ r1<- B (length) 7988 .endif 7989 cmp r3, #'I' @ array of ints? 7990 cmpne r3, #'L' @ array of objects? 7991 cmpne r3, #'[' @ array of arrays? 7992 mov r9, r1 @ save length in r9 7993 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 7994 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 7995 cmp r0, #0 @ null return? 7996 beq common_exceptionThrown @ alloc failed, handle exception 7997 7998 FETCH(r1, 2) @ r1<- FEDC or CCCC 7999 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8000 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8001 subs r9, r9, #1 @ length--, check for neg 8002 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8003 bmi 2f @ was zero, bail 8004 8005 @ copy values from registers into the array 8006 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8007 .if 0 8008 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 80091: ldr r3, [r2], #4 @ r3<- *r2++ 8010 subs r9, r9, #1 @ count-- 8011 str r3, [r0], #4 @ *contents++ = vX 8012 bpl 1b 8013 @ continue at 2 8014 .else 8015 cmp r9, #4 @ length was initially 5? 8016 and r2, r10, #15 @ r2<- A 8017 bne 1f @ <= 4 args, branch 8018 GET_VREG(r3, r2) @ r3<- vA 8019 sub r9, r9, #1 @ count-- 8020 str r3, [r0, #16] @ contents[4] = vA 80211: and r2, r1, #15 @ r2<- F/E/D/C 8022 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8023 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8024 subs r9, r9, #1 @ count-- 8025 str r3, [r0], #4 @ *contents++ = vX 8026 bpl 1b 8027 @ continue at 2 8028 .endif 8029 80302: 8031 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8032 GOTO_OPCODE(ip) @ execute it 8033 8034 /* 8035 * Throw an exception indicating that we have not implemented this 8036 * mode of filled-new-array. 8037 */ 8038.LOP_FILLED_NEW_ARRAY_notimpl: 8039 ldr r0, .L_strInternalError 8040 ldr r1, .L_strFilledNewArrayNotImpl 8041 bl dvmThrowException 8042 b common_exceptionThrown 8043 8044 .if (!0) @ define in one or the other, not both 8045.L_strFilledNewArrayNotImpl: 8046 .word .LstrFilledNewArrayNotImpl 8047.L_strInternalError: 8048 .word .LstrInternalError 8049 .endif 8050 8051/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 8052 8053 /* 8054 * On entry: 8055 * r0 holds array class 8056 * r10 holds AA or BA 8057 */ 8058.LOP_FILLED_NEW_ARRAY_RANGE_continue: 8059 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8060 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8061 ldrb r3, [r3, #1] @ r3<- descriptor[1] 8062 .if 1 8063 mov r1, r10 @ r1<- AA (length) 8064 .else 8065 mov r1, r10, lsr #4 @ r1<- B (length) 8066 .endif 8067 cmp r3, #'I' @ array of ints? 8068 cmpne r3, #'L' @ array of objects? 8069 cmpne r3, #'[' @ array of arrays? 8070 mov r9, r1 @ save length in r9 8071 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 8072 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8073 cmp r0, #0 @ null return? 8074 beq common_exceptionThrown @ alloc failed, handle exception 8075 8076 FETCH(r1, 2) @ r1<- FEDC or CCCC 8077 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8078 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8079 subs r9, r9, #1 @ length--, check for neg 8080 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8081 bmi 2f @ was zero, bail 8082 8083 @ copy values from registers into the array 8084 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8085 .if 1 8086 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 80871: ldr r3, [r2], #4 @ r3<- *r2++ 8088 subs r9, r9, #1 @ count-- 8089 str r3, [r0], #4 @ *contents++ = vX 8090 bpl 1b 8091 @ continue at 2 8092 .else 8093 cmp r9, #4 @ length was initially 5? 8094 and r2, r10, #15 @ r2<- A 8095 bne 1f @ <= 4 args, branch 8096 GET_VREG(r3, r2) @ r3<- vA 8097 sub r9, r9, #1 @ count-- 8098 str r3, [r0, #16] @ contents[4] = vA 80991: and r2, r1, #15 @ r2<- F/E/D/C 8100 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8101 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8102 subs r9, r9, #1 @ count-- 8103 str r3, [r0], #4 @ *contents++ = vX 8104 bpl 1b 8105 @ continue at 2 8106 .endif 8107 81082: 8109 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8110 GOTO_OPCODE(ip) @ execute it 8111 8112 /* 8113 * Throw an exception indicating that we have not implemented this 8114 * mode of filled-new-array. 8115 */ 8116.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8117 ldr r0, .L_strInternalError 8118 ldr r1, .L_strFilledNewArrayNotImpl 8119 bl dvmThrowException 8120 b common_exceptionThrown 8121 8122 .if (!1) @ define in one or the other, not both 8123.L_strFilledNewArrayNotImpl: 8124 .word .LstrFilledNewArrayNotImpl 8125.L_strInternalError: 8126 .word .LstrInternalError 8127 .endif 8128 8129/* continuation for OP_CMPL_FLOAT */ 8130.LOP_CMPL_FLOAT_finish: 8131 SET_VREG(r0, r9) @ vAA<- r0 8132 GOTO_OPCODE(ip) @ jump to next instruction 8133 8134/* continuation for OP_CMPG_FLOAT */ 8135.LOP_CMPG_FLOAT_finish: 8136 SET_VREG(r0, r9) @ vAA<- r0 8137 GOTO_OPCODE(ip) @ jump to next instruction 8138 8139/* continuation for OP_CMPL_DOUBLE */ 8140.LOP_CMPL_DOUBLE_finish: 8141 SET_VREG(r0, r9) @ vAA<- r0 8142 GOTO_OPCODE(ip) @ jump to next instruction 8143 8144/* continuation for OP_CMPG_DOUBLE */ 8145.LOP_CMPG_DOUBLE_finish: 8146 SET_VREG(r0, r9) @ vAA<- r0 8147 GOTO_OPCODE(ip) @ jump to next instruction 8148 8149/* continuation for OP_CMP_LONG */ 8150 8151.LOP_CMP_LONG_less: 8152 mvn r1, #0 @ r1<- -1 8153 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8154 @ instead, we just replicate the tail end. 8155 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8156 SET_VREG(r1, r9) @ vAA<- r1 8157 GET_INST_OPCODE(ip) @ extract opcode from rINST 8158 GOTO_OPCODE(ip) @ jump to next instruction 8159 8160.LOP_CMP_LONG_greater: 8161 mov r1, #1 @ r1<- 1 8162 @ fall through to _finish 8163 8164.LOP_CMP_LONG_finish: 8165 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8166 SET_VREG(r1, r9) @ vAA<- r1 8167 GET_INST_OPCODE(ip) @ extract opcode from rINST 8168 GOTO_OPCODE(ip) @ jump to next instruction 8169 8170/* continuation for OP_AGET_WIDE */ 8171 8172.LOP_AGET_WIDE_finish: 8173 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8174 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8175 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8176 GET_INST_OPCODE(ip) @ extract opcode from rINST 8177 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8178 GOTO_OPCODE(ip) @ jump to next instruction 8179 8180/* continuation for OP_APUT_WIDE */ 8181 8182.LOP_APUT_WIDE_finish: 8183 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8184 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8185 GET_INST_OPCODE(ip) @ extract opcode from rINST 8186 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8187 GOTO_OPCODE(ip) @ jump to next instruction 8188 8189/* continuation for OP_APUT_OBJECT */ 8190 /* 8191 * On entry: 8192 * r1 = vBB (arrayObj) 8193 * r9 = vAA (obj) 8194 * r10 = offset into array (vBB + vCC * width) 8195 */ 8196.LOP_APUT_OBJECT_finish: 8197 cmp r9, #0 @ storing null reference? 8198 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8199 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8200 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz 8201 bl dvmCanPutArrayElement @ test object type vs. array type 8202 cmp r0, #0 @ okay? 8203 beq common_errArrayStore @ no 8204.LOP_APUT_OBJECT_skip_check: 8205 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8206 GET_INST_OPCODE(ip) @ extract opcode from rINST 8207 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8208 GOTO_OPCODE(ip) @ jump to next instruction 8209 8210/* continuation for OP_IGET */ 8211 8212 /* 8213 * Currently: 8214 * r0 holds resolved field 8215 * r9 holds object 8216 */ 8217.LOP_IGET_finish: 8218 @bl common_squeak0 8219 cmp r9, #0 @ check object for null 8220 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8221 beq common_errNullObject @ object was null 8222 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8223 ubfx r2, rINST, #8, #4 @ r2<- A 8224 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8225 GET_INST_OPCODE(ip) @ extract opcode from rINST 8226 SET_VREG(r0, r2) @ fp[A]<- r0 8227 GOTO_OPCODE(ip) @ jump to next instruction 8228 8229/* continuation for OP_IGET_WIDE */ 8230 8231 /* 8232 * Currently: 8233 * r0 holds resolved field 8234 * r9 holds object 8235 */ 8236.LOP_IGET_WIDE_finish: 8237 cmp r9, #0 @ check object for null 8238 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8239 beq common_errNullObject @ object was null 8240 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8241 ubfx r2, rINST, #8, #4 @ r2<- A 8242 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8243 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8244 GET_INST_OPCODE(ip) @ extract opcode from rINST 8245 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8246 GOTO_OPCODE(ip) @ jump to next instruction 8247 8248/* continuation for OP_IGET_OBJECT */ 8249 8250 /* 8251 * Currently: 8252 * r0 holds resolved field 8253 * r9 holds object 8254 */ 8255.LOP_IGET_OBJECT_finish: 8256 @bl common_squeak0 8257 cmp r9, #0 @ check object for null 8258 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8259 beq common_errNullObject @ object was null 8260 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8261 @ no-op @ acquiring load 8262 mov r2, rINST, lsr #8 @ r2<- A+ 8263 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8264 and r2, r2, #15 @ r2<- A 8265 GET_INST_OPCODE(ip) @ extract opcode from rINST 8266 SET_VREG(r0, r2) @ fp[A]<- r0 8267 GOTO_OPCODE(ip) @ jump to next instruction 8268 8269/* continuation for OP_IGET_BOOLEAN */ 8270 8271 /* 8272 * Currently: 8273 * r0 holds resolved field 8274 * r9 holds object 8275 */ 8276.LOP_IGET_BOOLEAN_finish: 8277 @bl common_squeak1 8278 cmp r9, #0 @ check object for null 8279 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8280 beq common_errNullObject @ object was null 8281 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8282 @ no-op @ acquiring load 8283 mov r2, rINST, lsr #8 @ r2<- A+ 8284 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8285 and r2, r2, #15 @ r2<- A 8286 GET_INST_OPCODE(ip) @ extract opcode from rINST 8287 SET_VREG(r0, r2) @ fp[A]<- r0 8288 GOTO_OPCODE(ip) @ jump to next instruction 8289 8290/* continuation for OP_IGET_BYTE */ 8291 8292 /* 8293 * Currently: 8294 * r0 holds resolved field 8295 * r9 holds object 8296 */ 8297.LOP_IGET_BYTE_finish: 8298 @bl common_squeak2 8299 cmp r9, #0 @ check object for null 8300 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8301 beq common_errNullObject @ object was null 8302 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8303 @ no-op @ acquiring load 8304 mov r2, rINST, lsr #8 @ r2<- A+ 8305 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8306 and r2, r2, #15 @ r2<- A 8307 GET_INST_OPCODE(ip) @ extract opcode from rINST 8308 SET_VREG(r0, r2) @ fp[A]<- r0 8309 GOTO_OPCODE(ip) @ jump to next instruction 8310 8311/* continuation for OP_IGET_CHAR */ 8312 8313 /* 8314 * Currently: 8315 * r0 holds resolved field 8316 * r9 holds object 8317 */ 8318.LOP_IGET_CHAR_finish: 8319 @bl common_squeak3 8320 cmp r9, #0 @ check object for null 8321 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8322 beq common_errNullObject @ object was null 8323 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8324 @ no-op @ acquiring load 8325 mov r2, rINST, lsr #8 @ r2<- A+ 8326 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8327 and r2, r2, #15 @ r2<- A 8328 GET_INST_OPCODE(ip) @ extract opcode from rINST 8329 SET_VREG(r0, r2) @ fp[A]<- r0 8330 GOTO_OPCODE(ip) @ jump to next instruction 8331 8332/* continuation for OP_IGET_SHORT */ 8333 8334 /* 8335 * Currently: 8336 * r0 holds resolved field 8337 * r9 holds object 8338 */ 8339.LOP_IGET_SHORT_finish: 8340 @bl common_squeak4 8341 cmp r9, #0 @ check object for null 8342 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8343 beq common_errNullObject @ object was null 8344 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8345 @ no-op @ acquiring load 8346 mov r2, rINST, lsr #8 @ r2<- A+ 8347 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8348 and r2, r2, #15 @ r2<- A 8349 GET_INST_OPCODE(ip) @ extract opcode from rINST 8350 SET_VREG(r0, r2) @ fp[A]<- r0 8351 GOTO_OPCODE(ip) @ jump to next instruction 8352 8353/* continuation for OP_IPUT */ 8354 8355 /* 8356 * Currently: 8357 * r0 holds resolved field 8358 * r9 holds object 8359 */ 8360.LOP_IPUT_finish: 8361 @bl common_squeak0 8362 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8363 ubfx r1, rINST, #8, #4 @ r1<- A 8364 cmp r9, #0 @ check object for null 8365 GET_VREG(r0, r1) @ r0<- fp[A] 8366 beq common_errNullObject @ object was null 8367 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8368 GET_INST_OPCODE(ip) @ extract opcode from rINST 8369 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8370 GOTO_OPCODE(ip) @ jump to next instruction 8371 8372/* continuation for OP_IPUT_WIDE */ 8373 8374 /* 8375 * Currently: 8376 * r0 holds resolved field 8377 * r9 holds object 8378 */ 8379.LOP_IPUT_WIDE_finish: 8380 ubfx r2, rINST, #8, #4 @ r2<- A 8381 cmp r9, #0 @ check object for null 8382 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8383 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8384 beq common_errNullObject @ object was null 8385 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8386 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8387 GET_INST_OPCODE(ip) @ extract opcode from rINST 8388 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0 8389 GOTO_OPCODE(ip) @ jump to next instruction 8390 8391/* continuation for OP_IPUT_OBJECT */ 8392 8393 /* 8394 * Currently: 8395 * r0 holds resolved field 8396 * r9 holds object 8397 */ 8398.LOP_IPUT_OBJECT_finish: 8399 @bl common_squeak0 8400 mov r1, rINST, lsr #8 @ r1<- A+ 8401 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8402 and r1, r1, #15 @ r1<- A 8403 cmp r9, #0 @ check object for null 8404 GET_VREG(r0, r1) @ r0<- fp[A] 8405 beq common_errNullObject @ object was null 8406 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8407 GET_INST_OPCODE(ip) @ extract opcode from rINST 8408 @ no-op @ releasing store 8409 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8410 GOTO_OPCODE(ip) @ jump to next instruction 8411 8412/* continuation for OP_IPUT_BOOLEAN */ 8413 8414 /* 8415 * Currently: 8416 * r0 holds resolved field 8417 * r9 holds object 8418 */ 8419.LOP_IPUT_BOOLEAN_finish: 8420 @bl common_squeak1 8421 mov r1, rINST, lsr #8 @ r1<- A+ 8422 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8423 and r1, r1, #15 @ r1<- A 8424 cmp r9, #0 @ check object for null 8425 GET_VREG(r0, r1) @ r0<- fp[A] 8426 beq common_errNullObject @ object was null 8427 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8428 GET_INST_OPCODE(ip) @ extract opcode from rINST 8429 @ no-op @ releasing store 8430 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8431 GOTO_OPCODE(ip) @ jump to next instruction 8432 8433/* continuation for OP_IPUT_BYTE */ 8434 8435 /* 8436 * Currently: 8437 * r0 holds resolved field 8438 * r9 holds object 8439 */ 8440.LOP_IPUT_BYTE_finish: 8441 @bl common_squeak2 8442 mov r1, rINST, lsr #8 @ r1<- A+ 8443 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8444 and r1, r1, #15 @ r1<- A 8445 cmp r9, #0 @ check object for null 8446 GET_VREG(r0, r1) @ r0<- fp[A] 8447 beq common_errNullObject @ object was null 8448 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8449 GET_INST_OPCODE(ip) @ extract opcode from rINST 8450 @ no-op @ releasing store 8451 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8452 GOTO_OPCODE(ip) @ jump to next instruction 8453 8454/* continuation for OP_IPUT_CHAR */ 8455 8456 /* 8457 * Currently: 8458 * r0 holds resolved field 8459 * r9 holds object 8460 */ 8461.LOP_IPUT_CHAR_finish: 8462 @bl common_squeak3 8463 mov r1, rINST, lsr #8 @ r1<- A+ 8464 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8465 and r1, r1, #15 @ r1<- A 8466 cmp r9, #0 @ check object for null 8467 GET_VREG(r0, r1) @ r0<- fp[A] 8468 beq common_errNullObject @ object was null 8469 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8470 GET_INST_OPCODE(ip) @ extract opcode from rINST 8471 @ no-op @ releasing store 8472 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8473 GOTO_OPCODE(ip) @ jump to next instruction 8474 8475/* continuation for OP_IPUT_SHORT */ 8476 8477 /* 8478 * Currently: 8479 * r0 holds resolved field 8480 * r9 holds object 8481 */ 8482.LOP_IPUT_SHORT_finish: 8483 @bl common_squeak4 8484 mov r1, rINST, lsr #8 @ r1<- A+ 8485 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8486 and r1, r1, #15 @ r1<- A 8487 cmp r9, #0 @ check object for null 8488 GET_VREG(r0, r1) @ r0<- fp[A] 8489 beq common_errNullObject @ object was null 8490 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8491 GET_INST_OPCODE(ip) @ extract opcode from rINST 8492 @ no-op @ releasing store 8493 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8494 GOTO_OPCODE(ip) @ jump to next instruction 8495 8496/* continuation for OP_SGET */ 8497 8498 /* 8499 * Continuation if the field has not yet been resolved. 8500 * r1: BBBB field ref 8501 */ 8502.LOP_SGET_resolve: 8503 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8504 EXPORT_PC() @ resolve() could throw, so export now 8505 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8506 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8507 cmp r0, #0 @ success? 8508 bne .LOP_SGET_finish @ yes, finish 8509 b common_exceptionThrown @ no, handle exception 8510 8511/* continuation for OP_SGET_WIDE */ 8512 8513 /* 8514 * Continuation if the field has not yet been resolved. 8515 * r1: BBBB field ref 8516 * 8517 * Returns StaticField pointer in r0. 8518 */ 8519.LOP_SGET_WIDE_resolve: 8520 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8521 EXPORT_PC() @ resolve() could throw, so export now 8522 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8523 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8524 cmp r0, #0 @ success? 8525 bne .LOP_SGET_WIDE_finish @ yes, finish 8526 b common_exceptionThrown @ no, handle exception 8527 8528/* continuation for OP_SGET_OBJECT */ 8529 8530 /* 8531 * Continuation if the field has not yet been resolved. 8532 * r1: BBBB field ref 8533 */ 8534.LOP_SGET_OBJECT_resolve: 8535 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8536 EXPORT_PC() @ resolve() could throw, so export now 8537 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8538 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8539 cmp r0, #0 @ success? 8540 bne .LOP_SGET_OBJECT_finish @ yes, finish 8541 b common_exceptionThrown @ no, handle exception 8542 8543/* continuation for OP_SGET_BOOLEAN */ 8544 8545 /* 8546 * Continuation if the field has not yet been resolved. 8547 * r1: BBBB field ref 8548 */ 8549.LOP_SGET_BOOLEAN_resolve: 8550 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8551 EXPORT_PC() @ resolve() could throw, so export now 8552 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8553 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8554 cmp r0, #0 @ success? 8555 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8556 b common_exceptionThrown @ no, handle exception 8557 8558/* continuation for OP_SGET_BYTE */ 8559 8560 /* 8561 * Continuation if the field has not yet been resolved. 8562 * r1: BBBB field ref 8563 */ 8564.LOP_SGET_BYTE_resolve: 8565 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8566 EXPORT_PC() @ resolve() could throw, so export now 8567 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8568 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8569 cmp r0, #0 @ success? 8570 bne .LOP_SGET_BYTE_finish @ yes, finish 8571 b common_exceptionThrown @ no, handle exception 8572 8573/* continuation for OP_SGET_CHAR */ 8574 8575 /* 8576 * Continuation if the field has not yet been resolved. 8577 * r1: BBBB field ref 8578 */ 8579.LOP_SGET_CHAR_resolve: 8580 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8581 EXPORT_PC() @ resolve() could throw, so export now 8582 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8583 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8584 cmp r0, #0 @ success? 8585 bne .LOP_SGET_CHAR_finish @ yes, finish 8586 b common_exceptionThrown @ no, handle exception 8587 8588/* continuation for OP_SGET_SHORT */ 8589 8590 /* 8591 * Continuation if the field has not yet been resolved. 8592 * r1: BBBB field ref 8593 */ 8594.LOP_SGET_SHORT_resolve: 8595 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8596 EXPORT_PC() @ resolve() could throw, so export now 8597 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8598 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8599 cmp r0, #0 @ success? 8600 bne .LOP_SGET_SHORT_finish @ yes, finish 8601 b common_exceptionThrown @ no, handle exception 8602 8603/* continuation for OP_SPUT */ 8604 8605 /* 8606 * Continuation if the field has not yet been resolved. 8607 * r1: BBBB field ref 8608 */ 8609.LOP_SPUT_resolve: 8610 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8611 EXPORT_PC() @ resolve() could throw, so export now 8612 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8613 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8614 cmp r0, #0 @ success? 8615 bne .LOP_SPUT_finish @ yes, finish 8616 b common_exceptionThrown @ no, handle exception 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/* continuation for OP_SPUT_OBJECT */ 8638 8639 /* 8640 * Continuation if the field has not yet been resolved. 8641 * r1: BBBB field ref 8642 */ 8643.LOP_SPUT_OBJECT_resolve: 8644 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8645 EXPORT_PC() @ resolve() could throw, so export now 8646 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8647 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8648 cmp r0, #0 @ success? 8649 bne .LOP_SPUT_OBJECT_finish @ yes, finish 8650 b common_exceptionThrown @ no, handle exception 8651 8652/* continuation for OP_SPUT_BOOLEAN */ 8653 8654 /* 8655 * Continuation if the field has not yet been resolved. 8656 * r1: BBBB field ref 8657 */ 8658.LOP_SPUT_BOOLEAN_resolve: 8659 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8660 EXPORT_PC() @ resolve() could throw, so export now 8661 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8662 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8663 cmp r0, #0 @ success? 8664 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 8665 b common_exceptionThrown @ no, handle exception 8666 8667/* continuation for OP_SPUT_BYTE */ 8668 8669 /* 8670 * Continuation if the field has not yet been resolved. 8671 * r1: BBBB field ref 8672 */ 8673.LOP_SPUT_BYTE_resolve: 8674 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8675 EXPORT_PC() @ resolve() could throw, so export now 8676 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8677 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8678 cmp r0, #0 @ success? 8679 bne .LOP_SPUT_BYTE_finish @ yes, finish 8680 b common_exceptionThrown @ no, handle exception 8681 8682/* continuation for OP_SPUT_CHAR */ 8683 8684 /* 8685 * Continuation if the field has not yet been resolved. 8686 * r1: BBBB field ref 8687 */ 8688.LOP_SPUT_CHAR_resolve: 8689 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8690 EXPORT_PC() @ resolve() could throw, so export now 8691 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8692 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8693 cmp r0, #0 @ success? 8694 bne .LOP_SPUT_CHAR_finish @ yes, finish 8695 b common_exceptionThrown @ no, handle exception 8696 8697/* continuation for OP_SPUT_SHORT */ 8698 8699 /* 8700 * Continuation if the field has not yet been resolved. 8701 * r1: BBBB field ref 8702 */ 8703.LOP_SPUT_SHORT_resolve: 8704 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8705 EXPORT_PC() @ resolve() could throw, so export now 8706 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8707 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8708 cmp r0, #0 @ success? 8709 bne .LOP_SPUT_SHORT_finish @ yes, finish 8710 b common_exceptionThrown @ no, handle exception 8711 8712/* continuation for OP_INVOKE_VIRTUAL */ 8713 8714 /* 8715 * At this point: 8716 * r0 = resolved base method 8717 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8718 */ 8719.LOP_INVOKE_VIRTUAL_continue: 8720 GET_VREG(r1, r10) @ r1<- "this" ptr 8721 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8722 cmp r1, #0 @ is "this" null? 8723 beq common_errNullObject @ null "this", throw exception 8724 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8725 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8726 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8727 bl common_invokeMethodNoRange @ continue on 8728 8729/* continuation for OP_INVOKE_SUPER */ 8730 8731 /* 8732 * At this point: 8733 * r0 = resolved base method 8734 * r9 = method->clazz 8735 */ 8736.LOP_INVOKE_SUPER_continue: 8737 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8738 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8739 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8740 EXPORT_PC() @ must export for invoke 8741 cmp r2, r3 @ compare (methodIndex, vtableCount) 8742 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 8743 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8744 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8745 bl common_invokeMethodNoRange @ continue on 8746 8747.LOP_INVOKE_SUPER_resolve: 8748 mov r0, r9 @ r0<- method->clazz 8749 mov r2, #METHOD_VIRTUAL @ resolver method type 8750 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8751 cmp r0, #0 @ got null? 8752 bne .LOP_INVOKE_SUPER_continue @ no, continue 8753 b common_exceptionThrown @ yes, handle exception 8754 8755 /* 8756 * Throw a NoSuchMethodError with the method name as the message. 8757 * r0 = resolved base method 8758 */ 8759.LOP_INVOKE_SUPER_nsm: 8760 ldr r1, [r0, #offMethod_name] @ r1<- method name 8761 b common_errNoSuchMethod 8762 8763/* continuation for OP_INVOKE_DIRECT */ 8764 8765 /* 8766 * On entry: 8767 * r1 = reference (BBBB or CCCC) 8768 * r10 = "this" register 8769 */ 8770.LOP_INVOKE_DIRECT_resolve: 8771 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8772 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8773 mov r2, #METHOD_DIRECT @ resolver method type 8774 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8775 cmp r0, #0 @ got null? 8776 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8777 bne .LOP_INVOKE_DIRECT_finish @ no, continue 8778 b common_exceptionThrown @ yes, handle exception 8779 8780/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 8781 8782 /* 8783 * At this point: 8784 * r0 = resolved base method 8785 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8786 */ 8787.LOP_INVOKE_VIRTUAL_RANGE_continue: 8788 GET_VREG(r1, r10) @ r1<- "this" ptr 8789 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8790 cmp r1, #0 @ is "this" null? 8791 beq common_errNullObject @ null "this", throw exception 8792 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8793 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8794 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8795 bl common_invokeMethodRange @ continue on 8796 8797/* continuation for OP_INVOKE_SUPER_RANGE */ 8798 8799 /* 8800 * At this point: 8801 * r0 = resolved base method 8802 * r9 = method->clazz 8803 */ 8804.LOP_INVOKE_SUPER_RANGE_continue: 8805 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8806 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8807 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8808 EXPORT_PC() @ must export for invoke 8809 cmp r2, r3 @ compare (methodIndex, vtableCount) 8810 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 8811 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8812 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8813 bl common_invokeMethodRange @ continue on 8814 8815.LOP_INVOKE_SUPER_RANGE_resolve: 8816 mov r0, r9 @ r0<- method->clazz 8817 mov r2, #METHOD_VIRTUAL @ resolver method type 8818 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8819 cmp r0, #0 @ got null? 8820 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 8821 b common_exceptionThrown @ yes, handle exception 8822 8823 /* 8824 * Throw a NoSuchMethodError with the method name as the message. 8825 * r0 = resolved base method 8826 */ 8827.LOP_INVOKE_SUPER_RANGE_nsm: 8828 ldr r1, [r0, #offMethod_name] @ r1<- method name 8829 b common_errNoSuchMethod 8830 8831/* continuation for OP_INVOKE_DIRECT_RANGE */ 8832 8833 /* 8834 * On entry: 8835 * r1 = reference (BBBB or CCCC) 8836 * r10 = "this" register 8837 */ 8838.LOP_INVOKE_DIRECT_RANGE_resolve: 8839 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8840 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8841 mov r2, #METHOD_DIRECT @ resolver method type 8842 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8843 cmp r0, #0 @ got null? 8844 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8845 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 8846 b common_exceptionThrown @ yes, handle exception 8847 8848/* continuation for OP_FLOAT_TO_LONG */ 8849/* 8850 * Convert the float in r0 to a long in r0/r1. 8851 * 8852 * We have to clip values to long min/max per the specification. The 8853 * expected common case is a "reasonable" value that converts directly 8854 * to modest integer. The EABI convert function isn't doing this for us. 8855 */ 8856f2l_doconv: 8857 stmfd sp!, {r4, lr} 8858 mov r1, #0x5f000000 @ (float)maxlong 8859 mov r4, r0 8860 bl __aeabi_fcmpge @ is arg >= maxlong? 8861 cmp r0, #0 @ nonzero == yes 8862 mvnne r0, #0 @ return maxlong (7fffffff) 8863 mvnne r1, #0x80000000 8864 ldmnefd sp!, {r4, pc} 8865 8866 mov r0, r4 @ recover arg 8867 mov r1, #0xdf000000 @ (float)minlong 8868 bl __aeabi_fcmple @ is arg <= minlong? 8869 cmp r0, #0 @ nonzero == yes 8870 movne r0, #0 @ return minlong (80000000) 8871 movne r1, #0x80000000 8872 ldmnefd sp!, {r4, pc} 8873 8874 mov r0, r4 @ recover arg 8875 mov r1, r4 8876 bl __aeabi_fcmpeq @ is arg == self? 8877 cmp r0, #0 @ zero == no 8878 moveq r1, #0 @ return zero for NaN 8879 ldmeqfd sp!, {r4, pc} 8880 8881 mov r0, r4 @ recover arg 8882 bl __aeabi_f2lz @ convert float to long 8883 ldmfd sp!, {r4, pc} 8884 8885/* continuation for OP_DOUBLE_TO_LONG */ 8886/* 8887 * Convert the double in r0/r1 to a long in r0/r1. 8888 * 8889 * We have to clip values to long min/max per the specification. The 8890 * expected common case is a "reasonable" value that converts directly 8891 * to modest integer. The EABI convert function isn't doing this for us. 8892 */ 8893d2l_doconv: 8894 stmfd sp!, {r4, r5, lr} @ save regs 8895 mov r3, #0x43000000 @ maxlong, as a double (high word) 8896 add r3, #0x00e00000 @ 0x43e00000 8897 mov r2, #0 @ maxlong, as a double (low word) 8898 sub sp, sp, #4 @ align for EABI 8899 mov r4, r0 @ save a copy of r0 8900 mov r5, r1 @ and r1 8901 bl __aeabi_dcmpge @ is arg >= maxlong? 8902 cmp r0, #0 @ nonzero == yes 8903 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 8904 mvnne r1, #0x80000000 8905 bne 1f 8906 8907 mov r0, r4 @ recover arg 8908 mov r1, r5 8909 mov r3, #0xc3000000 @ minlong, as a double (high word) 8910 add r3, #0x00e00000 @ 0xc3e00000 8911 mov r2, #0 @ minlong, as a double (low word) 8912 bl __aeabi_dcmple @ is arg <= minlong? 8913 cmp r0, #0 @ nonzero == yes 8914 movne r0, #0 @ return minlong (8000000000000000) 8915 movne r1, #0x80000000 8916 bne 1f 8917 8918 mov r0, r4 @ recover arg 8919 mov r1, r5 8920 mov r2, r4 @ compare against self 8921 mov r3, r5 8922 bl __aeabi_dcmpeq @ is arg == self? 8923 cmp r0, #0 @ zero == no 8924 moveq r1, #0 @ return zero for NaN 8925 beq 1f 8926 8927 mov r0, r4 @ recover arg 8928 mov r1, r5 8929 bl __aeabi_d2lz @ convert double to long 8930 89311: 8932 add sp, sp, #4 8933 ldmfd sp!, {r4, r5, pc} 8934 8935/* continuation for OP_MUL_LONG */ 8936 8937.LOP_MUL_LONG_finish: 8938 GET_INST_OPCODE(ip) @ extract opcode from rINST 8939 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 8940 GOTO_OPCODE(ip) @ jump to next instruction 8941 8942/* continuation for OP_SHL_LONG */ 8943 8944.LOP_SHL_LONG_finish: 8945 mov r0, r0, asl r2 @ r0<- r0 << r2 8946 GET_INST_OPCODE(ip) @ extract opcode from rINST 8947 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8948 GOTO_OPCODE(ip) @ jump to next instruction 8949 8950/* continuation for OP_SHR_LONG */ 8951 8952.LOP_SHR_LONG_finish: 8953 mov r1, r1, asr r2 @ r1<- r1 >> r2 8954 GET_INST_OPCODE(ip) @ extract opcode from rINST 8955 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8956 GOTO_OPCODE(ip) @ jump to next instruction 8957 8958/* continuation for OP_USHR_LONG */ 8959 8960.LOP_USHR_LONG_finish: 8961 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 8962 GET_INST_OPCODE(ip) @ extract opcode from rINST 8963 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8964 GOTO_OPCODE(ip) @ jump to next instruction 8965 8966/* continuation for OP_SHL_LONG_2ADDR */ 8967 8968.LOP_SHL_LONG_2ADDR_finish: 8969 GET_INST_OPCODE(ip) @ extract opcode from rINST 8970 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8971 GOTO_OPCODE(ip) @ jump to next instruction 8972 8973/* continuation for OP_SHR_LONG_2ADDR */ 8974 8975.LOP_SHR_LONG_2ADDR_finish: 8976 GET_INST_OPCODE(ip) @ extract opcode from rINST 8977 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8978 GOTO_OPCODE(ip) @ jump to next instruction 8979 8980/* continuation for OP_USHR_LONG_2ADDR */ 8981 8982.LOP_USHR_LONG_2ADDR_finish: 8983 GET_INST_OPCODE(ip) @ extract opcode from rINST 8984 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 8985 GOTO_OPCODE(ip) @ jump to next instruction 8986 8987/* continuation for OP_IGET_VOLATILE */ 8988 8989 /* 8990 * Currently: 8991 * r0 holds resolved field 8992 * r9 holds object 8993 */ 8994.LOP_IGET_VOLATILE_finish: 8995 @bl common_squeak0 8996 cmp r9, #0 @ check object for null 8997 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8998 beq common_errNullObject @ object was null 8999 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9000 SMP_DMB @ acquiring load 9001 mov r2, rINST, lsr #8 @ r2<- A+ 9002 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9003 and r2, r2, #15 @ r2<- A 9004 GET_INST_OPCODE(ip) @ extract opcode from rINST 9005 SET_VREG(r0, r2) @ fp[A]<- r0 9006 GOTO_OPCODE(ip) @ jump to next instruction 9007 9008/* continuation for OP_IPUT_VOLATILE */ 9009 9010 /* 9011 * Currently: 9012 * r0 holds resolved field 9013 * r9 holds object 9014 */ 9015.LOP_IPUT_VOLATILE_finish: 9016 @bl common_squeak0 9017 mov r1, rINST, lsr #8 @ r1<- A+ 9018 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9019 and r1, r1, #15 @ r1<- A 9020 cmp r9, #0 @ check object for null 9021 GET_VREG(r0, r1) @ r0<- fp[A] 9022 beq common_errNullObject @ object was null 9023 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9024 GET_INST_OPCODE(ip) @ extract opcode from rINST 9025 SMP_DMB @ releasing store 9026 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 9027 GOTO_OPCODE(ip) @ jump to next instruction 9028 9029/* continuation for OP_SGET_VOLATILE */ 9030 9031 /* 9032 * Continuation if the field has not yet been resolved. 9033 * r1: BBBB field ref 9034 */ 9035.LOP_SGET_VOLATILE_resolve: 9036 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9037 EXPORT_PC() @ resolve() could throw, so export now 9038 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9039 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9040 cmp r0, #0 @ success? 9041 bne .LOP_SGET_VOLATILE_finish @ yes, finish 9042 b common_exceptionThrown @ no, handle exception 9043 9044/* continuation for OP_SPUT_VOLATILE */ 9045 9046 /* 9047 * Continuation if the field has not yet been resolved. 9048 * r1: BBBB field ref 9049 */ 9050.LOP_SPUT_VOLATILE_resolve: 9051 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9052 EXPORT_PC() @ resolve() could throw, so export now 9053 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9054 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9055 cmp r0, #0 @ success? 9056 bne .LOP_SPUT_VOLATILE_finish @ yes, finish 9057 b common_exceptionThrown @ no, handle exception 9058 9059/* continuation for OP_IGET_OBJECT_VOLATILE */ 9060 9061 /* 9062 * Currently: 9063 * r0 holds resolved field 9064 * r9 holds object 9065 */ 9066.LOP_IGET_OBJECT_VOLATILE_finish: 9067 @bl common_squeak0 9068 cmp r9, #0 @ check object for null 9069 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9070 beq common_errNullObject @ object was null 9071 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9072 SMP_DMB @ acquiring load 9073 mov r2, rINST, lsr #8 @ r2<- A+ 9074 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9075 and r2, r2, #15 @ r2<- A 9076 GET_INST_OPCODE(ip) @ extract opcode from rINST 9077 SET_VREG(r0, r2) @ fp[A]<- r0 9078 GOTO_OPCODE(ip) @ jump to next instruction 9079 9080/* continuation for OP_IGET_WIDE_VOLATILE */ 9081 9082 /* 9083 * Currently: 9084 * r0 holds resolved field 9085 * r9 holds object 9086 */ 9087.LOP_IGET_WIDE_VOLATILE_finish: 9088 cmp r9, #0 @ check object for null 9089 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9090 beq common_errNullObject @ object was null 9091 .if 1 9092 add r0, r9, r3 @ r0<- address of field 9093 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 9094 .else 9095 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 9096 .endif 9097 mov r2, rINST, lsr #8 @ r2<- A+ 9098 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9099 and r2, r2, #15 @ r2<- A 9100 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 9101 GET_INST_OPCODE(ip) @ extract opcode from rINST 9102 stmia r3, {r0-r1} @ fp[A]<- r0/r1 9103 GOTO_OPCODE(ip) @ jump to next instruction 9104 9105/* continuation for OP_IPUT_WIDE_VOLATILE */ 9106 9107 /* 9108 * Currently: 9109 * r0 holds resolved field 9110 * r9 holds object 9111 */ 9112.LOP_IPUT_WIDE_VOLATILE_finish: 9113 mov r2, rINST, lsr #8 @ r2<- A+ 9114 cmp r9, #0 @ check object for null 9115 and r2, r2, #15 @ r2<- A 9116 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9117 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 9118 beq common_errNullObject @ object was null 9119 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9120 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 9121 GET_INST_OPCODE(r10) @ extract opcode from rINST 9122 .if 1 9123 add r2, r9, r3 @ r2<- target address 9124 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 9125 .else 9126 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 9127 .endif 9128 GOTO_OPCODE(r10) @ jump to next instruction 9129 9130/* continuation for OP_SGET_WIDE_VOLATILE */ 9131 9132 /* 9133 * Continuation if the field has not yet been resolved. 9134 * r1: BBBB field ref 9135 * 9136 * Returns StaticField pointer in r0. 9137 */ 9138.LOP_SGET_WIDE_VOLATILE_resolve: 9139 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9140 EXPORT_PC() @ resolve() could throw, so export now 9141 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9142 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9143 cmp r0, #0 @ success? 9144 bne .LOP_SGET_WIDE_VOLATILE_finish @ yes, finish 9145 b common_exceptionThrown @ no, handle exception 9146 9147/* continuation for OP_SPUT_WIDE_VOLATILE */ 9148 9149 /* 9150 * Continuation if the field has not yet been resolved. 9151 * r1: BBBB field ref 9152 * r9: &fp[AA] 9153 * 9154 * Returns StaticField pointer in r2. 9155 */ 9156.LOP_SPUT_WIDE_VOLATILE_resolve: 9157 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9158 EXPORT_PC() @ resolve() could throw, so export now 9159 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9160 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9161 cmp r0, #0 @ success? 9162 mov r2, r0 @ copy to r2 9163 bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish 9164 b common_exceptionThrown @ no, handle exception 9165 9166/* continuation for OP_EXECUTE_INLINE */ 9167 9168 /* 9169 * Extract args, call function. 9170 * r0 = #of args (0-4) 9171 * r10 = call index 9172 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9173 * 9174 * Other ideas: 9175 * - Use a jump table from the main piece to jump directly into the 9176 * AND/LDR pairs. Costs a data load, saves a branch. 9177 * - Have five separate pieces that do the loading, so we can work the 9178 * interleave a little better. Increases code size. 9179 */ 9180.LOP_EXECUTE_INLINE_continue: 9181 rsb r0, r0, #4 @ r0<- 4-r0 9182 FETCH(r9, 2) @ r9<- FEDC 9183 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9184 bl common_abort @ (skipped due to ARM prefetch) 91854: and ip, r9, #0xf000 @ isolate F 9186 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 91873: and ip, r9, #0x0f00 @ isolate E 9188 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 91892: and ip, r9, #0x00f0 @ isolate D 9190 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 91911: and ip, r9, #0x000f @ isolate C 9192 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 91930: 9194 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 9195 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9196 @ (not reached) 9197 9198.LOP_EXECUTE_INLINE_table: 9199 .word gDvmInlineOpsTable 9200 9201/* continuation for OP_EXECUTE_INLINE_RANGE */ 9202 9203 /* 9204 * Extract args, call function. 9205 * r0 = #of args (0-4) 9206 * r10 = call index 9207 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9208 */ 9209.LOP_EXECUTE_INLINE_RANGE_continue: 9210 rsb r0, r0, #4 @ r0<- 4-r0 9211 FETCH(r9, 2) @ r9<- CCCC 9212 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9213 bl common_abort @ (skipped due to ARM prefetch) 92144: add ip, r9, #3 @ base+3 9215 GET_VREG(r3, ip) @ r3<- vBase[3] 92163: add ip, r9, #2 @ base+2 9217 GET_VREG(r2, ip) @ r2<- vBase[2] 92182: add ip, r9, #1 @ base+1 9219 GET_VREG(r1, ip) @ r1<- vBase[1] 92201: add ip, r9, #0 @ (nop) 9221 GET_VREG(r0, ip) @ r0<- vBase[0] 92220: 9223 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation 9224 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9225 @ (not reached) 9226 9227.LOP_EXECUTE_INLINE_RANGE_table: 9228 .word gDvmInlineOpsTable 9229 9230/* continuation for OP_IPUT_OBJECT_VOLATILE */ 9231 9232 /* 9233 * Currently: 9234 * r0 holds resolved field 9235 * r9 holds object 9236 */ 9237.LOP_IPUT_OBJECT_VOLATILE_finish: 9238 @bl common_squeak0 9239 mov r1, rINST, lsr #8 @ r1<- A+ 9240 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9241 and r1, r1, #15 @ r1<- A 9242 cmp r9, #0 @ check object for null 9243 GET_VREG(r0, r1) @ r0<- fp[A] 9244 beq common_errNullObject @ object was null 9245 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9246 GET_INST_OPCODE(ip) @ extract opcode from rINST 9247 SMP_DMB @ releasing store 9248 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 9249 GOTO_OPCODE(ip) @ jump to next instruction 9250 9251/* continuation for OP_SGET_OBJECT_VOLATILE */ 9252 9253 /* 9254 * Continuation if the field has not yet been resolved. 9255 * r1: BBBB field ref 9256 */ 9257.LOP_SGET_OBJECT_VOLATILE_resolve: 9258 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9259 EXPORT_PC() @ resolve() could throw, so export now 9260 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9261 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9262 cmp r0, #0 @ success? 9263 bne .LOP_SGET_OBJECT_VOLATILE_finish @ yes, finish 9264 b common_exceptionThrown @ no, handle exception 9265 9266/* continuation for OP_SPUT_OBJECT_VOLATILE */ 9267 9268 /* 9269 * Continuation if the field has not yet been resolved. 9270 * r1: BBBB field ref 9271 */ 9272.LOP_SPUT_OBJECT_VOLATILE_resolve: 9273 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9274 EXPORT_PC() @ resolve() could throw, so export now 9275 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9276 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9277 cmp r0, #0 @ success? 9278 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish 9279 b common_exceptionThrown @ no, handle exception 9280 9281 .size dvmAsmSisterStart, .-dvmAsmSisterStart 9282 .global dvmAsmSisterEnd 9283dvmAsmSisterEnd: 9284 9285/* File: armv5te/footer.S */ 9286 9287/* 9288 * =========================================================================== 9289 * Common subroutines and data 9290 * =========================================================================== 9291 */ 9292 9293 9294 9295 .text 9296 .align 2 9297 9298#if defined(WITH_JIT) 9299#if defined(WITH_SELF_VERIFICATION) 9300 .global dvmJitToInterpPunt 9301dvmJitToInterpPunt: 9302 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9303 mov r2,#kSVSPunt @ r2<- interpreter entry point 9304 mov r3, #0 9305 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9306 b jitSVShadowRunEnd @ doesn't return 9307 9308 .global dvmJitToInterpSingleStep 9309dvmJitToInterpSingleStep: 9310 str lr,[rGLUE,#offGlue_jitResumeNPC] 9311 str r1,[rGLUE,#offGlue_jitResumeDPC] 9312 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 9313 b jitSVShadowRunEnd @ doesn't return 9314 9315 .global dvmJitToInterpTraceSelectNoChain 9316dvmJitToInterpTraceSelectNoChain: 9317 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9318 mov r0,rPC @ pass our target PC 9319 mov r2,#kSVSTraceSelectNoChain @ r2<- interpreter entry point 9320 mov r3, #0 9321 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9322 b jitSVShadowRunEnd @ doesn't return 9323 9324 .global dvmJitToInterpTraceSelect 9325dvmJitToInterpTraceSelect: 9326 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9327 ldr r0,[lr, #-1] @ pass our target PC 9328 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9329 mov r3, #0 9330 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9331 b jitSVShadowRunEnd @ doesn't return 9332 9333 .global dvmJitToInterpBackwardBranch 9334dvmJitToInterpBackwardBranch: 9335 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9336 ldr r0,[lr, #-1] @ pass our target PC 9337 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 9338 mov r3, #0 9339 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9340 b jitSVShadowRunEnd @ doesn't return 9341 9342 .global dvmJitToInterpNormal 9343dvmJitToInterpNormal: 9344 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9345 ldr r0,[lr, #-1] @ pass our target PC 9346 mov r2,#kSVSNormal @ r2<- interpreter entry point 9347 mov r3, #0 9348 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9349 b jitSVShadowRunEnd @ doesn't return 9350 9351 .global dvmJitToInterpNoChain 9352dvmJitToInterpNoChain: 9353 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9354 mov r0,rPC @ pass our target PC 9355 mov r2,#kSVSNoChain @ r2<- interpreter entry point 9356 mov r3, #0 9357 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9358 b jitSVShadowRunEnd @ doesn't return 9359#else 9360/* 9361 * Return from the translation cache to the interpreter when the compiler is 9362 * having issues translating/executing a Dalvik instruction. We have to skip 9363 * the code cache lookup otherwise it is possible to indefinitely bouce 9364 * between the interpreter and the code cache if the instruction that fails 9365 * to be compiled happens to be at a trace start. 9366 */ 9367 .global dvmJitToInterpPunt 9368dvmJitToInterpPunt: 9369 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9370 mov rPC, r0 9371#if defined(WITH_JIT_TUNING) 9372 mov r0,lr 9373 bl dvmBumpPunt; 9374#endif 9375 EXPORT_PC() 9376 mov r0, #0 9377 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9378 adrl rIBASE, dvmAsmInstructionStart 9379 FETCH_INST() 9380 GET_INST_OPCODE(ip) 9381 GOTO_OPCODE(ip) 9382 9383/* 9384 * Return to the interpreter to handle a single instruction. 9385 * On entry: 9386 * r0 <= PC 9387 * r1 <= PC of resume instruction 9388 * lr <= resume point in translation 9389 */ 9390 .global dvmJitToInterpSingleStep 9391dvmJitToInterpSingleStep: 9392 str lr,[rGLUE,#offGlue_jitResumeNPC] 9393 str r1,[rGLUE,#offGlue_jitResumeDPC] 9394 mov r1,#kInterpEntryInstr 9395 @ enum is 4 byte in aapcs-EABI 9396 str r1, [rGLUE, #offGlue_entryPoint] 9397 mov rPC,r0 9398 EXPORT_PC() 9399 9400 adrl rIBASE, dvmAsmInstructionStart 9401 mov r2,#kJitSingleStep @ Ask for single step and then revert 9402 str r2,[rGLUE,#offGlue_jitState] 9403 mov r1,#1 @ set changeInterp to bail to debug interp 9404 b common_gotoBail 9405 9406/* 9407 * Return from the translation cache and immediately request 9408 * a translation for the exit target. Commonly used for callees. 9409 */ 9410 .global dvmJitToInterpTraceSelectNoChain 9411dvmJitToInterpTraceSelectNoChain: 9412#if defined(WITH_JIT_TUNING) 9413 bl dvmBumpNoChain 9414#endif 9415 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9416 mov r0,rPC 9417 bl dvmJitGetCodeAddr @ Is there a translation? 9418 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9419 mov r1, rPC @ arg1 of translation may need this 9420 mov lr, #0 @ in case target is HANDLER_INTERPRET 9421 cmp r0,#0 9422 bxne r0 @ continue native execution if so 9423 b 2f 9424 9425/* 9426 * Return from the translation cache and immediately request 9427 * a translation for the exit target. Commonly used following 9428 * invokes. 9429 */ 9430 .global dvmJitToInterpTraceSelect 9431dvmJitToInterpTraceSelect: 9432 ldr rPC,[lr, #-1] @ get our target PC 9433 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9434 add rINST,lr,#-5 @ save start of chain branch 9435 add rINST, #-4 @ .. which is 9 bytes back 9436 mov r0,rPC 9437 bl dvmJitGetCodeAddr @ Is there a translation? 9438 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9439 cmp r0,#0 9440 beq 2f 9441 mov r1,rINST 9442 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9443 mov r1, rPC @ arg1 of translation may need this 9444 mov lr, #0 @ in case target is HANDLER_INTERPRET 9445 cmp r0,#0 @ successful chain? 9446 bxne r0 @ continue native execution 9447 b toInterpreter @ didn't chain - resume with interpreter 9448 9449/* No translation, so request one if profiling isn't disabled*/ 94502: 9451 adrl rIBASE, dvmAsmInstructionStart 9452 GET_JIT_PROF_TABLE(r0) 9453 FETCH_INST() 9454 cmp r0, #0 9455 movne r2,#kJitTSelectRequestHot @ ask for trace selection 9456 bne common_selectTrace 9457 GET_INST_OPCODE(ip) 9458 GOTO_OPCODE(ip) 9459 9460/* 9461 * Return from the translation cache to the interpreter. 9462 * The return was done with a BLX from thumb mode, and 9463 * the following 32-bit word contains the target rPC value. 9464 * Note that lr (r14) will have its low-order bit set to denote 9465 * its thumb-mode origin. 9466 * 9467 * We'll need to stash our lr origin away, recover the new 9468 * target and then check to see if there is a translation available 9469 * for our new target. If so, we do a translation chain and 9470 * go back to native execution. Otherwise, it's back to the 9471 * interpreter (after treating this entry as a potential 9472 * trace start). 9473 */ 9474 .global dvmJitToInterpNormal 9475dvmJitToInterpNormal: 9476 ldr rPC,[lr, #-1] @ get our target PC 9477 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9478 add rINST,lr,#-5 @ save start of chain branch 9479 add rINST,#-4 @ .. which is 9 bytes back 9480#if defined(WITH_JIT_TUNING) 9481 bl dvmBumpNormal 9482#endif 9483 mov r0,rPC 9484 bl dvmJitGetCodeAddr @ Is there a translation? 9485 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9486 cmp r0,#0 9487 beq toInterpreter @ go if not, otherwise do chain 9488 mov r1,rINST 9489 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9490 mov r1, rPC @ arg1 of translation may need this 9491 mov lr, #0 @ in case target is HANDLER_INTERPRET 9492 cmp r0,#0 @ successful chain? 9493 bxne r0 @ continue native execution 9494 b toInterpreter @ didn't chain - resume with interpreter 9495 9496/* 9497 * Return from the translation cache to the interpreter to do method invocation. 9498 * Check if translation exists for the callee, but don't chain to it. 9499 */ 9500 .global dvmJitToInterpNoChain 9501dvmJitToInterpNoChain: 9502#if defined(WITH_JIT_TUNING) 9503 bl dvmBumpNoChain 9504#endif 9505 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9506 mov r0,rPC 9507 bl dvmJitGetCodeAddr @ Is there a translation? 9508 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9509 mov r1, rPC @ arg1 of translation may need this 9510 mov lr, #0 @ in case target is HANDLER_INTERPRET 9511 cmp r0,#0 9512 bxne r0 @ continue native execution if so 9513#endif 9514 9515/* 9516 * No translation, restore interpreter regs and start interpreting. 9517 * rGLUE & rFP were preserved in the translated code, and rPC has 9518 * already been restored by the time we get here. We'll need to set 9519 * up rIBASE & rINST, and load the address of the JitTable into r0. 9520 */ 9521toInterpreter: 9522 EXPORT_PC() 9523 adrl rIBASE, dvmAsmInstructionStart 9524 FETCH_INST() 9525 GET_JIT_PROF_TABLE(r0) 9526 @ NOTE: intended fallthrough 9527/* 9528 * Common code to update potential trace start counter, and initiate 9529 * a trace-build if appropriate. On entry, rPC should point to the 9530 * next instruction to execute, and rINST should be already loaded with 9531 * the next opcode word, and r0 holds a pointer to the jit profile 9532 * table (pJitProfTable). 9533 */ 9534common_testUpdateProfile: 9535 cmp r0,#0 9536 GET_INST_OPCODE(ip) 9537 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 9538 9539common_updateProfile: 9540 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 9541 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits 9542 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter 9543 GET_INST_OPCODE(ip) 9544 subs r1,r1,#1 @ decrement counter 9545 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it 9546 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 9547 9548/* 9549 * Here, we switch to the debug interpreter to request 9550 * trace selection. First, though, check to see if there 9551 * is already a native translation in place (and, if so, 9552 * jump to it now). 9553 */ 9554 GET_JIT_THRESHOLD(r1) 9555 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9556 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter 9557 EXPORT_PC() 9558 mov r0,rPC 9559 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC) 9560 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9561 mov r1, rPC @ arg1 of translation may need this 9562 mov lr, #0 @ in case target is HANDLER_INTERPRET 9563 cmp r0,#0 9564#if !defined(WITH_SELF_VERIFICATION) 9565 bxne r0 @ jump to the translation 9566 mov r2,#kJitTSelectRequest @ ask for trace selection 9567 @ fall-through to common_selectTrace 9568#else 9569 moveq r2,#kJitTSelectRequest @ ask for trace selection 9570 beq common_selectTrace 9571 /* 9572 * At this point, we have a target translation. However, if 9573 * that translation is actually the interpret-only pseudo-translation 9574 * we want to treat it the same as no translation. 9575 */ 9576 mov r10, r0 @ save target 9577 bl dvmCompilerGetInterpretTemplate 9578 cmp r0, r10 @ special case? 9579 bne jitSVShadowRunStart @ set up self verification shadow space 9580 GET_INST_OPCODE(ip) 9581 GOTO_OPCODE(ip) 9582 /* no return */ 9583#endif 9584 9585/* 9586 * On entry: 9587 * r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot 9588 */ 9589common_selectTrace: 9590 str r2,[rGLUE,#offGlue_jitState] 9591 mov r2,#kInterpEntryInstr @ normal entry reason 9592 str r2,[rGLUE,#offGlue_entryPoint] 9593 mov r1,#1 @ set changeInterp 9594 b common_gotoBail 9595 9596#if defined(WITH_SELF_VERIFICATION) 9597/* 9598 * Save PC and registers to shadow memory for self verification mode 9599 * before jumping to native translation. 9600 * On entry: 9601 * rPC, rFP, rGLUE: the values that they should contain 9602 * r10: the address of the target translation. 9603 */ 9604jitSVShadowRunStart: 9605 mov r0,rPC @ r0<- program counter 9606 mov r1,rFP @ r1<- frame pointer 9607 mov r2,rGLUE @ r2<- InterpState pointer 9608 mov r3,r10 @ r3<- target translation 9609 bl dvmSelfVerificationSaveState @ save registers to shadow space 9610 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 9611 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 9612 bx r10 @ jump to the translation 9613 9614/* 9615 * Restore PC, registers, and interpState to original values 9616 * before jumping back to the interpreter. 9617 */ 9618jitSVShadowRunEnd: 9619 mov r1,rFP @ pass ending fp 9620 bl dvmSelfVerificationRestoreState @ restore pc and fp values 9621 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 9622 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 9623 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 9624 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 9625 cmp r1,#0 @ check for punt condition 9626 beq 1f 9627 mov r2,#kJitSelfVerification @ ask for self verification 9628 str r2,[rGLUE,#offGlue_jitState] 9629 mov r2,#kInterpEntryInstr @ normal entry reason 9630 str r2,[rGLUE,#offGlue_entryPoint] 9631 mov r1,#1 @ set changeInterp 9632 b common_gotoBail 9633 96341: @ exit to interpreter without check 9635 EXPORT_PC() 9636 adrl rIBASE, dvmAsmInstructionStart 9637 FETCH_INST() 9638 GET_INST_OPCODE(ip) 9639 GOTO_OPCODE(ip) 9640#endif 9641 9642#endif 9643 9644/* 9645 * Common code when a backward branch is taken. 9646 * 9647 * TODO: we could avoid a branch by just setting r0 and falling through 9648 * into the common_periodicChecks code, and having a test on r0 at the 9649 * end determine if we should return to the caller or update & branch to 9650 * the next instr. 9651 * 9652 * On entry: 9653 * r9 is PC adjustment *in bytes* 9654 */ 9655common_backwardBranch: 9656 mov r0, #kInterpEntryInstr 9657 bl common_periodicChecks 9658#if defined(WITH_JIT) 9659 GET_JIT_PROF_TABLE(r0) 9660 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9661 cmp r0,#0 9662 bne common_updateProfile 9663 GET_INST_OPCODE(ip) 9664 GOTO_OPCODE(ip) 9665#else 9666 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9667 GET_INST_OPCODE(ip) @ extract opcode from rINST 9668 GOTO_OPCODE(ip) @ jump to next instruction 9669#endif 9670 9671 9672/* 9673 * Need to see if the thread needs to be suspended or debugger/profiler 9674 * activity has begun. If so, we suspend the thread or side-exit to 9675 * the debug interpreter as appropriate. 9676 * 9677 * The common case is no activity on any of these, so we want to figure 9678 * that out quickly. If something is up, we can then sort out what. 9679 * 9680 * We want to be fast if the VM was built without debugger or profiler 9681 * support, but we also need to recognize that the system is usually 9682 * shipped with both of these enabled. 9683 * 9684 * TODO: reduce this so we're just checking a single location. 9685 * 9686 * On entry: 9687 * r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling) 9688 * r9 is trampoline PC adjustment *in bytes* 9689 */ 9690common_periodicChecks: 9691 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9692 9693#if defined(WITH_DEBUGGER) 9694 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9695#endif 9696#if defined(WITH_PROFILER) 9697 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9698#endif 9699 9700 ldr ip, [r3] @ ip<- suspendCount (int) 9701 9702#if defined(WITH_DEBUGGER) && defined(WITH_PROFILER) 9703 cmp r1, #0 @ debugger enabled? 9704 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9705 ldr r2, [r2] @ r2<- activeProfilers (int) 9706 orrne ip, ip, r1 @ ip<- suspendCount | debuggerActive 9707 orrs ip, ip, r2 @ ip<- suspend|debugger|profiler; set Z 9708#elif defined(WITH_DEBUGGER) 9709 cmp r1, #0 @ debugger enabled? 9710 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9711 orrsne ip, ip, r1 @ yes, ip<- suspend | debugger; set Z 9712 @ (if not enabled, Z was set by test for r1==0, which is what we want) 9713#elif defined (WITH_PROFILER) 9714 ldr r2, [r2] @ r2<- activeProfilers (int) 9715 orrs ip, ip, r2 @ ip<- suspendCount | activeProfilers 9716#else 9717 cmp ip, #0 @ not ORing anything in; set Z 9718#endif 9719 9720 bxeq lr @ all zero, return 9721 9722 /* 9723 * One or more interesting events have happened. Figure out what. 9724 * 9725 * If debugging or profiling are compiled in, we need to disambiguate. 9726 * 9727 * r0 still holds the reentry type. 9728 */ 9729#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 9730 ldr ip, [r3] @ ip<- suspendCount (int) 9731 cmp ip, #0 @ want suspend? 9732 beq 1f @ no, must be debugger/profiler 9733#endif 9734 9735 stmfd sp!, {r0, lr} @ preserve r0 and lr 9736#if defined(WITH_JIT) 9737 /* 9738 * Refresh the Jit's cached copy of profile table pointer. This pointer 9739 * doubles as the Jit's on/off switch. 9740 */ 9741 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable 9742 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9743 ldr r3, [r3] @ r3 <- pJitProfTable 9744 EXPORT_PC() @ need for precise GC 9745 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch 9746#else 9747 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9748 EXPORT_PC() @ need for precise GC 9749#endif 9750 bl dvmCheckSuspendPending @ do full check, suspend if necessary 9751 ldmfd sp!, {r0, lr} @ restore r0 and lr 9752 9753#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 9754 9755 /* 9756 * Reload the debugger/profiler enable flags. We're checking to see 9757 * if either of these got set while we were suspended. 9758 * 9759 * We can't really avoid the #ifdefs here, because the fields don't 9760 * exist when the feature is disabled. 9761 */ 9762#if defined(WITH_DEBUGGER) 9763 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9764 cmp r1, #0 @ debugger enabled? 9765 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9766#else 9767 mov r1, #0 9768#endif 9769#if defined(WITH_PROFILER) 9770 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9771 ldr r2, [r2] @ r2<- activeProfilers (int) 9772#else 9773 mov r2, #0 9774#endif 9775 9776 orrs r1, r1, r2 9777 beq 2f 9778 97791: @ debugger/profiler enabled, bail out; glue->entryPoint was set above 9780 str r0, [rGLUE, #offGlue_entryPoint] @ store r0, need for debug/prof 9781 add rPC, rPC, r9 @ update rPC 9782 mov r1, #1 @ "want switch" = true 9783 b common_gotoBail @ side exit 9784 9785#endif /*WITH_DEBUGGER || WITH_PROFILER*/ 9786 97872: 9788 bx lr @ nothing to do, return 9789 9790 9791/* 9792 * The equivalent of "goto bail", this calls through the "bail handler". 9793 * 9794 * State registers will be saved to the "glue" area before bailing. 9795 * 9796 * On entry: 9797 * r1 is "bool changeInterp", indicating if we want to switch to the 9798 * other interpreter or just bail all the way out 9799 */ 9800common_gotoBail: 9801 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9802 mov r0, rGLUE @ r0<- glue ptr 9803 b dvmMterpStdBail @ call(glue, changeInterp) 9804 9805 @add r1, r1, #1 @ using (boolean+1) 9806 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9807 @bl _longjmp @ does not return 9808 @bl common_abort 9809 9810 9811/* 9812 * Common code for method invocation with range. 9813 * 9814 * On entry: 9815 * r0 is "Method* methodToCall", the method we're trying to call 9816 */ 9817common_invokeMethodRange: 9818.LinvokeNewRange: 9819 @ prepare to copy args to "outs" area of current frame 9820 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9821 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9822 beq .LinvokeArgsDone @ if no args, skip the rest 9823 FETCH(r1, 2) @ r1<- CCCC 9824 9825 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9826 @ (very few methods have > 10 args; could unroll for common cases) 9827 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9828 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9829 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 98301: ldr r1, [r3], #4 @ val = *fp++ 9831 subs r2, r2, #1 @ count-- 9832 str r1, [r10], #4 @ *outs++ = val 9833 bne 1b @ ...while count != 0 9834 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9835 b .LinvokeArgsDone 9836 9837/* 9838 * Common code for method invocation without range. 9839 * 9840 * On entry: 9841 * r0 is "Method* methodToCall", the method we're trying to call 9842 */ 9843common_invokeMethodNoRange: 9844.LinvokeNewNoRange: 9845 @ prepare to copy args to "outs" area of current frame 9846 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9847 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9848 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9849 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9850 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9851 beq .LinvokeArgsDone 9852 9853 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9854.LinvokeNonRange: 9855 rsb r2, r2, #5 @ r2<- 5-r2 9856 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9857 bl common_abort @ (skipped due to ARM prefetch) 98585: and ip, rINST, #0x0f00 @ isolate A 9859 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 9860 mov r0, r0 @ nop 9861 str r2, [r10, #-4]! @ *--outs = vA 98624: and ip, r1, #0xf000 @ isolate G 9863 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 9864 mov r0, r0 @ nop 9865 str r2, [r10, #-4]! @ *--outs = vG 98663: and ip, r1, #0x0f00 @ isolate F 9867 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 9868 mov r0, r0 @ nop 9869 str r2, [r10, #-4]! @ *--outs = vF 98702: and ip, r1, #0x00f0 @ isolate E 9871 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 9872 mov r0, r0 @ nop 9873 str r2, [r10, #-4]! @ *--outs = vE 98741: and ip, r1, #0x000f @ isolate D 9875 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 9876 mov r0, r0 @ nop 9877 str r2, [r10, #-4]! @ *--outs = vD 98780: @ fall through to .LinvokeArgsDone 9879 9880.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 9881 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 9882 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 9883 @ find space for the new stack frame, check for overflow 9884 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 9885 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 9886 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 9887@ bl common_dumpRegs 9888 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 9889 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 9890 cmp r3, r9 @ bottom < interpStackEnd? 9891 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 9892 blo .LstackOverflow @ yes, this frame will overflow stack 9893 9894 @ set up newSaveArea 9895#ifdef EASY_GDB 9896 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 9897 str ip, [r10, #offStackSaveArea_prevSave] 9898#endif 9899 str rFP, [r10, #offStackSaveArea_prevFrame] 9900 str rPC, [r10, #offStackSaveArea_savedPc] 9901#if defined(WITH_JIT) 9902 mov r9, #0 9903 str r9, [r10, #offStackSaveArea_returnAddr] 9904#endif 9905 str r0, [r10, #offStackSaveArea_method] 9906 tst r3, #ACC_NATIVE 9907 bne .LinvokeNative 9908 9909 /* 9910 stmfd sp!, {r0-r3} 9911 bl common_printNewline 9912 mov r0, rFP 9913 mov r1, #0 9914 bl dvmDumpFp 9915 ldmfd sp!, {r0-r3} 9916 stmfd sp!, {r0-r3} 9917 mov r0, r1 9918 mov r1, r10 9919 bl dvmDumpFp 9920 bl common_printNewline 9921 ldmfd sp!, {r0-r3} 9922 */ 9923 9924 ldrh r9, [r2] @ r9 <- load INST from new PC 9925 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 9926 mov rPC, r2 @ publish new rPC 9927 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 9928 9929 @ Update "glue" values for the new method 9930 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 9931 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 9932 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 9933#if defined(WITH_JIT) 9934 GET_JIT_PROF_TABLE(r0) 9935 mov rFP, r1 @ fp = newFp 9936 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9937 mov rINST, r9 @ publish new rINST 9938 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9939 cmp r0,#0 9940 bne common_updateProfile 9941 GOTO_OPCODE(ip) @ jump to next instruction 9942#else 9943 mov rFP, r1 @ fp = newFp 9944 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9945 mov rINST, r9 @ publish new rINST 9946 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9947 GOTO_OPCODE(ip) @ jump to next instruction 9948#endif 9949 9950.LinvokeNative: 9951 @ Prep for the native call 9952 @ r0=methodToCall, r1=newFp, r10=newSaveArea 9953 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9954 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 9955 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 9956 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 9957 mov r9, r3 @ r9<- glue->self (preserve) 9958 9959 mov r2, r0 @ r2<- methodToCall 9960 mov r0, r1 @ r0<- newFp (points to args) 9961 add r1, rGLUE, #offGlue_retval @ r1<- &retval 9962 9963#ifdef ASSIST_DEBUGGER 9964 /* insert fake function header to help gdb find the stack frame */ 9965 b .Lskip 9966 .type dalvik_mterp, %function 9967dalvik_mterp: 9968 .fnstart 9969 MTERP_ENTRY1 9970 MTERP_ENTRY2 9971.Lskip: 9972#endif 9973 9974 @mov lr, pc @ set return addr 9975 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 9976 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 9977 9978#if defined(WITH_JIT) 9979 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status 9980#endif 9981 9982 @ native return; r9=self, r10=newSaveArea 9983 @ equivalent to dvmPopJniLocals 9984 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 9985 ldr r1, [r9, #offThread_exception] @ check for exception 9986#if defined(WITH_JIT) 9987 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable 9988#endif 9989 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 9990 cmp r1, #0 @ null? 9991 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 9992#if defined(WITH_JIT) 9993 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch 9994#endif 9995 bne common_exceptionThrown @ no, handle exception 9996 9997 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 9998 GET_INST_OPCODE(ip) @ extract opcode from rINST 9999 GOTO_OPCODE(ip) @ jump to next instruction 10000 10001.LstackOverflow: @ r0=methodToCall 10002 mov r1, r0 @ r1<- methodToCall 10003 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 10004 bl dvmHandleStackOverflow 10005 b common_exceptionThrown 10006#ifdef ASSIST_DEBUGGER 10007 .fnend 10008#endif 10009 10010 10011 /* 10012 * Common code for method invocation, calling through "glue code". 10013 * 10014 * TODO: now that we have range and non-range invoke handlers, this 10015 * needs to be split into two. Maybe just create entry points 10016 * that set r9 and jump here? 10017 * 10018 * On entry: 10019 * r0 is "Method* methodToCall", the method we're trying to call 10020 * r9 is "bool methodCallRange", indicating if this is a /range variant 10021 */ 10022 .if 0 10023.LinvokeOld: 10024 sub sp, sp, #8 @ space for args + pad 10025 FETCH(ip, 2) @ ip<- FEDC or CCCC 10026 mov r2, r0 @ A2<- methodToCall 10027 mov r0, rGLUE @ A0<- glue 10028 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 10029 mov r1, r9 @ A1<- methodCallRange 10030 mov r3, rINST, lsr #8 @ A3<- AA 10031 str ip, [sp, #0] @ A4<- ip 10032 bl dvmMterp_invokeMethod @ call the C invokeMethod 10033 add sp, sp, #8 @ remove arg area 10034 b common_resumeAfterGlueCall @ continue to next instruction 10035 .endif 10036 10037 10038 10039/* 10040 * Common code for handling a return instruction. 10041 * 10042 * This does not return. 10043 */ 10044common_returnFromMethod: 10045.LreturnNew: 10046 mov r0, #kInterpEntryReturn 10047 mov r9, #0 10048 bl common_periodicChecks 10049 10050 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 10051 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 10052 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 10053 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 10054 @ r2<- method we're returning to 10055 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10056 cmp r2, #0 @ is this a break frame? 10057 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 10058 mov r1, #0 @ "want switch" = false 10059 beq common_gotoBail @ break frame, bail out completely 10060 10061 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 10062 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 10063 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 10064 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 10065#if defined(WITH_JIT) 10066 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr 10067 GET_JIT_PROF_TABLE(r0) 10068 mov rPC, r9 @ publish new rPC 10069 str r1, [rGLUE, #offGlue_methodClassDex] 10070 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land 10071 cmp r10, #0 @ caller is compiled code 10072 blxne r10 10073 GET_INST_OPCODE(ip) @ extract opcode from rINST 10074 cmp r0,#0 10075 bne common_updateProfile 10076 GOTO_OPCODE(ip) @ jump to next instruction 10077#else 10078 GET_INST_OPCODE(ip) @ extract opcode from rINST 10079 mov rPC, r9 @ publish new rPC 10080 str r1, [rGLUE, #offGlue_methodClassDex] 10081 GOTO_OPCODE(ip) @ jump to next instruction 10082#endif 10083 10084 /* 10085 * Return handling, calls through "glue code". 10086 */ 10087 .if 0 10088.LreturnOld: 10089 SAVE_PC_FP_TO_GLUE() @ export state 10090 mov r0, rGLUE @ arg to function 10091 bl dvmMterp_returnFromMethod 10092 b common_resumeAfterGlueCall 10093 .endif 10094 10095 10096/* 10097 * Somebody has thrown an exception. Handle it. 10098 * 10099 * If the exception processing code returns to us (instead of falling 10100 * out of the interpreter), continue with whatever the next instruction 10101 * now happens to be. 10102 * 10103 * This does not return. 10104 */ 10105 .global dvmMterpCommonExceptionThrown 10106dvmMterpCommonExceptionThrown: 10107common_exceptionThrown: 10108.LexceptionNew: 10109 mov r0, #kInterpEntryThrow 10110 mov r9, #0 10111 bl common_periodicChecks 10112 10113 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 10114 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 10115 mov r1, r10 @ r1<- self 10116 mov r0, r9 @ r0<- exception 10117 bl dvmAddTrackedAlloc @ don't let the exception be GCed 10118 mov r3, #0 @ r3<- NULL 10119 str r3, [r10, #offThread_exception] @ self->exception = NULL 10120 10121 /* set up args and a local for "&fp" */ 10122 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 10123 str rFP, [sp, #-4]! @ *--sp = fp 10124 mov ip, sp @ ip<- &fp 10125 mov r3, #0 @ r3<- false 10126 str ip, [sp, #-4]! @ *--sp = &fp 10127 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 10128 mov r0, r10 @ r0<- self 10129 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 10130 mov r2, r9 @ r2<- exception 10131 sub r1, rPC, r1 @ r1<- pc - method->insns 10132 mov r1, r1, asr #1 @ r1<- offset in code units 10133 10134 /* call, r0 gets catchRelPc (a code-unit offset) */ 10135 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 10136 10137 /* fix earlier stack overflow if necessary; may trash rFP */ 10138 ldrb r1, [r10, #offThread_stackOverflowed] 10139 cmp r1, #0 @ did we overflow earlier? 10140 beq 1f @ no, skip ahead 10141 mov rFP, r0 @ save relPc result in rFP 10142 mov r0, r10 @ r0<- self 10143 mov r1, r9 @ r1<- exception 10144 bl dvmCleanupStackOverflow @ call(self) 10145 mov r0, rFP @ restore result 101461: 10147 10148 /* update frame pointer and check result from dvmFindCatchBlock */ 10149 ldr rFP, [sp, #4] @ retrieve the updated rFP 10150 cmp r0, #0 @ is catchRelPc < 0? 10151 add sp, sp, #8 @ restore stack 10152 bmi .LnotCaughtLocally 10153 10154 /* adjust locals to match self->curFrame and updated PC */ 10155 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 10156 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 10157 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 10158 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 10159 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 10160 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 10161 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 10162 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 10163 10164 /* release the tracked alloc on the exception */ 10165 mov r0, r9 @ r0<- exception 10166 mov r1, r10 @ r1<- self 10167 bl dvmReleaseTrackedAlloc @ release the exception 10168 10169 /* restore the exception if the handler wants it */ 10170 FETCH_INST() @ load rINST from rPC 10171 GET_INST_OPCODE(ip) @ extract opcode from rINST 10172 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 10173 streq r9, [r10, #offThread_exception] @ yes, restore the exception 10174 GOTO_OPCODE(ip) @ jump to next instruction 10175 10176.LnotCaughtLocally: @ r9=exception, r10=self 10177 /* fix stack overflow if necessary */ 10178 ldrb r1, [r10, #offThread_stackOverflowed] 10179 cmp r1, #0 @ did we overflow earlier? 10180 movne r0, r10 @ if yes: r0<- self 10181 movne r1, r9 @ if yes: r1<- exception 10182 blne dvmCleanupStackOverflow @ if yes: call(self) 10183 10184 @ may want to show "not caught locally" debug messages here 10185#if DVM_SHOW_EXCEPTION >= 2 10186 /* call __android_log_print(prio, tag, format, ...) */ 10187 /* "Exception %s from %s:%d not caught locally" */ 10188 @ dvmLineNumFromPC(method, pc - method->insns) 10189 ldr r0, [rGLUE, #offGlue_method] 10190 ldr r1, [r0, #offMethod_insns] 10191 sub r1, rPC, r1 10192 asr r1, r1, #1 10193 bl dvmLineNumFromPC 10194 str r0, [sp, #-4]! 10195 @ dvmGetMethodSourceFile(method) 10196 ldr r0, [rGLUE, #offGlue_method] 10197 bl dvmGetMethodSourceFile 10198 str r0, [sp, #-4]! 10199 @ exception->clazz->descriptor 10200 ldr r3, [r9, #offObject_clazz] 10201 ldr r3, [r3, #offClassObject_descriptor] 10202 @ 10203 ldr r2, strExceptionNotCaughtLocally 10204 ldr r1, strLogTag 10205 mov r0, #3 @ LOG_DEBUG 10206 bl __android_log_print 10207#endif 10208 str r9, [r10, #offThread_exception] @ restore exception 10209 mov r0, r9 @ r0<- exception 10210 mov r1, r10 @ r1<- self 10211 bl dvmReleaseTrackedAlloc @ release the exception 10212 mov r1, #0 @ "want switch" = false 10213 b common_gotoBail @ bail out 10214 10215 10216 /* 10217 * Exception handling, calls through "glue code". 10218 */ 10219 .if 0 10220.LexceptionOld: 10221 SAVE_PC_FP_TO_GLUE() @ export state 10222 mov r0, rGLUE @ arg to function 10223 bl dvmMterp_exceptionThrown 10224 b common_resumeAfterGlueCall 10225 .endif 10226 10227 10228/* 10229 * After returning from a "glued" function, pull out the updated 10230 * values and start executing at the next instruction. 10231 */ 10232common_resumeAfterGlueCall: 10233 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 10234 FETCH_INST() @ load rINST from rPC 10235 GET_INST_OPCODE(ip) @ extract opcode from rINST 10236 GOTO_OPCODE(ip) @ jump to next instruction 10237 10238/* 10239 * Invalid array index. 10240 */ 10241common_errArrayIndex: 10242 EXPORT_PC() 10243 ldr r0, strArrayIndexException 10244 mov r1, #0 10245 bl dvmThrowException 10246 b common_exceptionThrown 10247 10248/* 10249 * Invalid array value. 10250 */ 10251common_errArrayStore: 10252 EXPORT_PC() 10253 ldr r0, strArrayStoreException 10254 mov r1, #0 10255 bl dvmThrowException 10256 b common_exceptionThrown 10257 10258/* 10259 * Integer divide or mod by zero. 10260 */ 10261common_errDivideByZero: 10262 EXPORT_PC() 10263 ldr r0, strArithmeticException 10264 ldr r1, strDivideByZero 10265 bl dvmThrowException 10266 b common_exceptionThrown 10267 10268/* 10269 * Attempt to allocate an array with a negative size. 10270 */ 10271common_errNegativeArraySize: 10272 EXPORT_PC() 10273 ldr r0, strNegativeArraySizeException 10274 mov r1, #0 10275 bl dvmThrowException 10276 b common_exceptionThrown 10277 10278/* 10279 * Invocation of a non-existent method. 10280 */ 10281common_errNoSuchMethod: 10282 EXPORT_PC() 10283 ldr r0, strNoSuchMethodError 10284 mov r1, #0 10285 bl dvmThrowException 10286 b common_exceptionThrown 10287 10288/* 10289 * We encountered a null object when we weren't expecting one. We 10290 * export the PC, throw a NullPointerException, and goto the exception 10291 * processing code. 10292 */ 10293common_errNullObject: 10294 EXPORT_PC() 10295 ldr r0, strNullPointerException 10296 mov r1, #0 10297 bl dvmThrowException 10298 b common_exceptionThrown 10299 10300/* 10301 * For debugging, cause an immediate fault. The source address will 10302 * be in lr (use a bl instruction to jump here). 10303 */ 10304common_abort: 10305 ldr pc, .LdeadFood 10306.LdeadFood: 10307 .word 0xdeadf00d 10308 10309/* 10310 * Spit out a "we were here", preserving all registers. (The attempt 10311 * to save ip won't work, but we need to save an even number of 10312 * registers for EABI 64-bit stack alignment.) 10313 */ 10314 .macro SQUEAK num 10315common_squeak\num: 10316 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10317 ldr r0, strSqueak 10318 mov r1, #\num 10319 bl printf 10320 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10321 bx lr 10322 .endm 10323 10324 SQUEAK 0 10325 SQUEAK 1 10326 SQUEAK 2 10327 SQUEAK 3 10328 SQUEAK 4 10329 SQUEAK 5 10330 10331/* 10332 * Spit out the number in r0, preserving registers. 10333 */ 10334common_printNum: 10335 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10336 mov r1, r0 10337 ldr r0, strSqueak 10338 bl printf 10339 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10340 bx lr 10341 10342/* 10343 * Print a newline, preserving registers. 10344 */ 10345common_printNewline: 10346 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10347 ldr r0, strNewline 10348 bl printf 10349 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10350 bx lr 10351 10352 /* 10353 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 10354 */ 10355common_printHex: 10356 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10357 mov r1, r0 10358 ldr r0, strPrintHex 10359 bl printf 10360 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10361 bx lr 10362 10363/* 10364 * Print the 64-bit quantity in r0-r1, preserving registers. 10365 */ 10366common_printLong: 10367 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10368 mov r3, r1 10369 mov r2, r0 10370 ldr r0, strPrintLong 10371 bl printf 10372 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10373 bx lr 10374 10375/* 10376 * Print full method info. Pass the Method* in r0. Preserves regs. 10377 */ 10378common_printMethod: 10379 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10380 bl dvmMterpPrintMethod 10381 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10382 bx lr 10383 10384/* 10385 * Call a C helper function that dumps regs and possibly some 10386 * additional info. Requires the C function to be compiled in. 10387 */ 10388 .if 0 10389common_dumpRegs: 10390 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10391 bl dvmMterpDumpArmRegs 10392 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10393 bx lr 10394 .endif 10395 10396#if 0 10397/* 10398 * Experiment on VFP mode. 10399 * 10400 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 10401 * 10402 * Updates the bits specified by "mask", setting them to the values in "val". 10403 */ 10404setFPSCR: 10405 and r0, r0, r1 @ make sure no stray bits are set 10406 fmrx r2, fpscr @ get VFP reg 10407 mvn r1, r1 @ bit-invert mask 10408 and r2, r2, r1 @ clear masked bits 10409 orr r2, r2, r0 @ set specified bits 10410 fmxr fpscr, r2 @ set VFP reg 10411 mov r0, r2 @ return new value 10412 bx lr 10413 10414 .align 2 10415 .global dvmConfigureFP 10416 .type dvmConfigureFP, %function 10417dvmConfigureFP: 10418 stmfd sp!, {ip, lr} 10419 /* 0x03000000 sets DN/FZ */ 10420 /* 0x00009f00 clears the six exception enable flags */ 10421 bl common_squeak0 10422 mov r0, #0x03000000 @ r0<- 0x03000000 10423 add r1, r0, #0x9f00 @ r1<- 0x03009f00 10424 bl setFPSCR 10425 ldmfd sp!, {ip, pc} 10426#endif 10427 10428 10429/* 10430 * String references, must be close to the code that uses them. 10431 */ 10432 .align 2 10433strArithmeticException: 10434 .word .LstrArithmeticException 10435strArrayIndexException: 10436 .word .LstrArrayIndexException 10437strArrayStoreException: 10438 .word .LstrArrayStoreException 10439strDivideByZero: 10440 .word .LstrDivideByZero 10441strNegativeArraySizeException: 10442 .word .LstrNegativeArraySizeException 10443strNoSuchMethodError: 10444 .word .LstrNoSuchMethodError 10445strNullPointerException: 10446 .word .LstrNullPointerException 10447 10448strLogTag: 10449 .word .LstrLogTag 10450strExceptionNotCaughtLocally: 10451 .word .LstrExceptionNotCaughtLocally 10452 10453strNewline: 10454 .word .LstrNewline 10455strSqueak: 10456 .word .LstrSqueak 10457strPrintHex: 10458 .word .LstrPrintHex 10459strPrintLong: 10460 .word .LstrPrintLong 10461 10462/* 10463 * Zero-terminated ASCII string data. 10464 * 10465 * On ARM we have two choices: do like gcc does, and LDR from a .word 10466 * with the address, or use an ADR pseudo-op to get the address 10467 * directly. ADR saves 4 bytes and an indirection, but it's using a 10468 * PC-relative addressing mode and hence has a limited range, which 10469 * makes it not work well with mergeable string sections. 10470 */ 10471 .section .rodata.str1.4,"aMS",%progbits,1 10472 10473.LstrBadEntryPoint: 10474 .asciz "Bad entry point %d\n" 10475.LstrArithmeticException: 10476 .asciz "Ljava/lang/ArithmeticException;" 10477.LstrArrayIndexException: 10478 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 10479.LstrArrayStoreException: 10480 .asciz "Ljava/lang/ArrayStoreException;" 10481.LstrClassCastException: 10482 .asciz "Ljava/lang/ClassCastException;" 10483.LstrDivideByZero: 10484 .asciz "divide by zero" 10485.LstrFilledNewArrayNotImpl: 10486 .asciz "filled-new-array only implemented for objects and 'int'" 10487.LstrInternalError: 10488 .asciz "Ljava/lang/InternalError;" 10489.LstrInstantiationError: 10490 .asciz "Ljava/lang/InstantiationError;" 10491.LstrNegativeArraySizeException: 10492 .asciz "Ljava/lang/NegativeArraySizeException;" 10493.LstrNoSuchMethodError: 10494 .asciz "Ljava/lang/NoSuchMethodError;" 10495.LstrNullPointerException: 10496 .asciz "Ljava/lang/NullPointerException;" 10497 10498.LstrLogTag: 10499 .asciz "mterp" 10500.LstrExceptionNotCaughtLocally: 10501 .asciz "Exception %s from %s:%d not caught locally\n" 10502 10503.LstrNewline: 10504 .asciz "\n" 10505.LstrSqueak: 10506 .asciz "<%d>" 10507.LstrPrintHex: 10508 .asciz "<0x%x>" 10509.LstrPrintLong: 10510 .asciz "<%lld>" 10511 10512