InterpAsm-armv5te-vfp.S revision 8c9ac9ab0ab6fd75b73cb0d99005da3aa90c167c
1/* 2 * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'. 3 * 4 * --> DO NOT EDIT <-- 5 */ 6 7/* File: armv5te/header.S */ 8/* 9 * Copyright (C) 2008 The Android Open Source Project 10 * 11 * Licensed under the Apache License, Version 2.0 (the "License"); 12 * you may not use this file except in compliance with the License. 13 * You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 */ 23 24/* 25 * ARMv5 definitions and declarations. 26 */ 27 28/* 29ARM EABI general notes: 30 31r0-r3 hold first 4 args to a method; they are not preserved across method calls 32r4-r8 are available for general use 33r9 is given special treatment in some situations, but not for us 34r10 (sl) seems to be generally available 35r11 (fp) is used by gcc (unless -fomit-frame-pointer is set) 36r12 (ip) is scratch -- not preserved across method calls 37r13 (sp) should be managed carefully in case a signal arrives 38r14 (lr) must be preserved 39r15 (pc) can be tinkered with directly 40 41r0 holds returns of <= 4 bytes 42r0-r1 hold returns of 8 bytes, low word in r0 43 44Callee must save/restore r4+ (except r12) if it modifies them. If VFP 45is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved, 46s0-s15 (d0-d7, q0-a3) do not need to be. 47 48Stack is "full descending". Only the arguments that don't fit in the first 4 49registers are placed on the stack. "sp" points at the first stacked argument 50(i.e. the 5th arg). 51 52VFP: single-precision results in s0, double-precision results in d0. 53 54In the EABI, "sp" must be 64-bit aligned on entry to a function, and any 5564-bit quantities (long long, double) must be 64-bit aligned. 56*/ 57 58/* 59Mterp and ARM notes: 60 61The following registers have fixed assignments: 62 63 reg nick purpose 64 r4 rPC interpreted program counter, used for fetching instructions 65 r5 rFP interpreted frame pointer, used for accessing locals and args 66 r6 rGLUE MterpGlue pointer 67 r7 rINST first 16-bit code unit of current instruction 68 r8 rIBASE interpreted instruction base pointer, used for computed goto 69 70Macros are provided for common operations. Each macro MUST emit only 71one instruction to make instruction-counting easier. They MUST NOT alter 72unspecified registers or condition codes. 73*/ 74 75/* single-purpose registers, given names for clarity */ 76#define rPC r4 77#define rFP r5 78#define rGLUE r6 79#define rINST r7 80#define rIBASE r8 81 82/* save/restore the PC and/or FP from the glue struct */ 83#define LOAD_PC_FROM_GLUE() ldr rPC, [rGLUE, #offGlue_pc] 84#define SAVE_PC_TO_GLUE() str rPC, [rGLUE, #offGlue_pc] 85#define LOAD_FP_FROM_GLUE() ldr rFP, [rGLUE, #offGlue_fp] 86#define SAVE_FP_TO_GLUE() str rFP, [rGLUE, #offGlue_fp] 87#define LOAD_PC_FP_FROM_GLUE() ldmia rGLUE, {rPC, rFP} 88#define SAVE_PC_FP_TO_GLUE() stmia rGLUE, {rPC, rFP} 89 90/* 91 * "export" the PC to the stack frame, f/b/o future exception objects. Must 92 * be done *before* something calls dvmThrowException. 93 * 94 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e. 95 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc) 96 * 97 * It's okay to do this more than once. 98 */ 99#define EXPORT_PC() \ 100 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)] 101 102/* 103 * Given a frame pointer, find the stack save area. 104 * 105 * In C this is "((StackSaveArea*)(_fp) -1)". 106 */ 107#define SAVEAREA_FROM_FP(_reg, _fpreg) \ 108 sub _reg, _fpreg, #sizeofStackSaveArea 109 110/* 111 * Fetch the next instruction from rPC into rINST. Does not advance rPC. 112 */ 113#define FETCH_INST() ldrh rINST, [rPC] 114 115/* 116 * Fetch the next instruction from the specified offset. Advances rPC 117 * to point to the next instruction. "_count" is in 16-bit code units. 118 * 119 * Because of the limited size of immediate constants on ARM, this is only 120 * suitable for small forward movements (i.e. don't try to implement "goto" 121 * with this). 122 * 123 * This must come AFTER anything that can throw an exception, or the 124 * exception catch may miss. (This also implies that it must come after 125 * EXPORT_PC().) 126 */ 127#define FETCH_ADVANCE_INST(_count) ldrh rINST, [rPC, #(_count*2)]! 128 129/* 130 * The operation performed here is similar to FETCH_ADVANCE_INST, except the 131 * src and dest registers are parameterized (not hard-wired to rPC and rINST). 132 */ 133#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \ 134 ldrh _dreg, [_sreg, #(_count*2)]! 135 136/* 137 * Fetch the next instruction from an offset specified by _reg. Updates 138 * rPC to point to the next instruction. "_reg" must specify the distance 139 * in bytes, *not* 16-bit code units, and may be a signed value. 140 * 141 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the 142 * bits that hold the shift distance are used for the half/byte/sign flags. 143 * In some cases we can pre-double _reg for free, so we require a byte offset 144 * here. 145 */ 146#define FETCH_ADVANCE_INST_RB(_reg) ldrh rINST, [rPC, _reg]! 147 148/* 149 * Fetch a half-word code unit from an offset past the current PC. The 150 * "_count" value is in 16-bit code units. Does not advance rPC. 151 * 152 * The "_S" variant works the same but treats the value as signed. 153 */ 154#define FETCH(_reg, _count) ldrh _reg, [rPC, #(_count*2)] 155#define FETCH_S(_reg, _count) ldrsh _reg, [rPC, #(_count*2)] 156 157/* 158 * Fetch one byte from an offset past the current PC. Pass in the same 159 * "_count" as you would for FETCH, and an additional 0/1 indicating which 160 * byte of the halfword you want (lo/hi). 161 */ 162#define FETCH_B(_reg, _count, _byte) ldrb _reg, [rPC, #(_count*2+_byte)] 163 164/* 165 * Put the instruction's opcode field into the specified register. 166 */ 167#define GET_INST_OPCODE(_reg) and _reg, rINST, #255 168 169/* 170 * Put the prefetched instruction's opcode field into the specified register. 171 */ 172#define GET_PREFETCHED_OPCODE(_oreg, _ireg) and _oreg, _ireg, #255 173 174/* 175 * Begin executing the opcode in _reg. Because this only jumps within the 176 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork. 177 */ 178#define GOTO_OPCODE(_reg) add pc, rIBASE, _reg, lsl #6 179#define GOTO_OPCODE_IFEQ(_reg) addeq pc, rIBASE, _reg, lsl #6 180#define GOTO_OPCODE_IFNE(_reg) addne pc, rIBASE, _reg, lsl #6 181 182/* 183 * Get/set the 32-bit value from a Dalvik register. 184 */ 185#define GET_VREG(_reg, _vreg) ldr _reg, [rFP, _vreg, lsl #2] 186#define SET_VREG(_reg, _vreg) str _reg, [rFP, _vreg, lsl #2] 187 188#if defined(WITH_JIT) 189#define GET_JIT_PROF_TABLE(_reg) ldr _reg,[rGLUE,#offGlue_pJitProfTable] 190#define GET_JIT_THRESHOLD(_reg) ldr _reg,[rGLUE,#offGlue_jitThreshold] 191#endif 192 193/* 194 * Convert a virtual register index into an address. 195 */ 196#define VREG_INDEX_TO_ADDR(_reg, _vreg) \ 197 add _reg, rFP, _vreg, lsl #2 198 199/* 200 * This is a #include, not a %include, because we want the C pre-processor 201 * to expand the macros into assembler assignment statements. 202 */ 203#include "../common/asm-constants.h" 204 205#if defined(WITH_JIT) 206#include "../common/jit-config.h" 207#endif 208 209/* File: armv5te/platform.S */ 210/* 211 * =========================================================================== 212 * CPU-version-specific defines 213 * =========================================================================== 214 */ 215 216/* 217 * Macro for "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/* 247 * Macro for data memory barrier; not meaningful pre-ARMv6K. 248 */ 249.macro SMP_DMB 250.endm 251 252/* 253 * Macro for data memory barrier; not meaningful pre-ARMv6K. 254 */ 255.macro SMP_DMB_ST 256.endm 257 258/* File: armv5te/entry.S */ 259/* 260 * Copyright (C) 2008 The Android Open Source Project 261 * 262 * Licensed under the Apache License, Version 2.0 (the "License"); 263 * you may not use this file except in compliance with the License. 264 * You may obtain a copy of the License at 265 * 266 * http://www.apache.org/licenses/LICENSE-2.0 267 * 268 * Unless required by applicable law or agreed to in writing, software 269 * distributed under the License is distributed on an "AS IS" BASIS, 270 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 271 * See the License for the specific language governing permissions and 272 * limitations under the License. 273 */ 274/* 275 * Interpreter entry point. 276 */ 277 278/* 279 * We don't have formal stack frames, so gdb scans upward in the code 280 * to find the start of the function (a label with the %function type), 281 * and then looks at the next few instructions to figure out what 282 * got pushed onto the stack. From this it figures out how to restore 283 * the registers, including PC, for the previous stack frame. If gdb 284 * sees a non-function label, it stops scanning, so either we need to 285 * have nothing but assembler-local labels between the entry point and 286 * the break, or we need to fake it out. 287 * 288 * When this is defined, we add some stuff to make gdb less confused. 289 */ 290#define ASSIST_DEBUGGER 1 291 292 .text 293 .align 2 294 .global dvmMterpStdRun 295 .type dvmMterpStdRun, %function 296 297/* 298 * On entry: 299 * r0 MterpGlue* glue 300 * 301 * This function returns a boolean "changeInterp" value. The return comes 302 * via a call to dvmMterpStdBail(). 303 */ 304dvmMterpStdRun: 305#define MTERP_ENTRY1 \ 306 .save {r4-r10,fp,lr}; \ 307 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs 308#define MTERP_ENTRY2 \ 309 .pad #4; \ 310 sub sp, sp, #4 @ align 64 311 312 .fnstart 313 MTERP_ENTRY1 314 MTERP_ENTRY2 315 316 /* save stack pointer, add magic word for debuggerd */ 317 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return 318 319 /* set up "named" registers, figure out entry point */ 320 mov rGLUE, r0 @ set rGLUE 321 ldr r1, [r0, #offGlue_entryPoint] @ enum is 4 bytes in aapcs-EABI 322 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue" 323 adr rIBASE, dvmAsmInstructionStart @ set rIBASE 324 cmp r1, #kInterpEntryInstr @ usual case? 325 bne .Lnot_instr @ no, handle it 326 327#if defined(WITH_JIT) 328.LentryInstr: 329 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 330 /* Entry is always a possible trace start */ 331 GET_JIT_PROF_TABLE(r0) 332 FETCH_INST() 333 mov r1, #0 @ prepare the value for the new state 334 str r1, [r10, #offThread_inJitCodeCache] @ back to the interp land 335 cmp r0,#0 @ is profiling disabled? 336#if !defined(WITH_SELF_VERIFICATION) 337 bne common_updateProfile @ profiling is enabled 338#else 339 ldr r2, [r10, #offThread_shadowSpace] @ to find out the jit exit state 340 beq 1f @ profiling is disabled 341 ldr r3, [r2, #offShadowSpace_jitExitState] @ jit exit state 342 cmp r3, #kSVSTraceSelect @ hot trace following? 343 moveq r2,#kJitTSelectRequestHot @ ask for trace selection 344 beq common_selectTrace @ go build the trace 345 cmp r3, #kSVSNoProfile @ don't profile the next instruction? 346 beq 1f @ intrepret the next instruction 347 b common_updateProfile @ collect profiles 348#endif 3491: 350 GET_INST_OPCODE(ip) 351 GOTO_OPCODE(ip) 352#else 353 /* start executing the instruction at rPC */ 354 FETCH_INST() @ load rINST from rPC 355 GET_INST_OPCODE(ip) @ extract opcode from rINST 356 GOTO_OPCODE(ip) @ jump to next instruction 357#endif 358 359.Lnot_instr: 360 cmp r1, #kInterpEntryReturn @ were we returning from a method? 361 beq common_returnFromMethod 362 363.Lnot_return: 364 cmp r1, #kInterpEntryThrow @ were we throwing an exception? 365 beq common_exceptionThrown 366 367#if defined(WITH_JIT) 368.Lnot_throw: 369 ldr r10,[rGLUE, #offGlue_jitResumeNPC] 370 ldr r2,[rGLUE, #offGlue_jitResumeDPC] 371 cmp r1, #kInterpEntryResume @ resuming after Jit single-step? 372 bne .Lbad_arg 373 cmp rPC,r2 374 bne .LentryInstr @ must have branched, don't resume 375#if defined(WITH_SELF_VERIFICATION) 376 @ glue->entryPoint will be set in dvmSelfVerificationSaveState 377 b jitSVShadowRunStart @ re-enter the translation after the 378 @ single-stepped instruction 379 @noreturn 380#endif 381 mov r1, #kInterpEntryInstr 382 str r1, [rGLUE, #offGlue_entryPoint] 383 bx r10 @ re-enter the translation 384#endif 385 386.Lbad_arg: 387 ldr r0, strBadEntryPoint 388 @ r1 holds value of entryPoint 389 bl printf 390 bl dvmAbort 391 .fnend 392 393 394 .global dvmMterpStdBail 395 .type dvmMterpStdBail, %function 396 397/* 398 * Restore the stack pointer and PC from the save point established on entry. 399 * This is essentially the same as a longjmp, but should be cheaper. The 400 * last instruction causes us to return to whoever called dvmMterpStdRun. 401 * 402 * We pushed some registers on the stack in dvmMterpStdRun, then saved 403 * SP and LR. Here we restore SP, restore the registers, and then restore 404 * LR to PC. 405 * 406 * On entry: 407 * r0 MterpGlue* glue 408 * r1 bool changeInterp 409 */ 410dvmMterpStdBail: 411 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 412 mov r0, r1 @ return the changeInterp value 413 add sp, sp, #4 @ un-align 64 414 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return 415 416 417/* 418 * String references. 419 */ 420strBadEntryPoint: 421 .word .LstrBadEntryPoint 422 423 424 .global dvmAsmInstructionStart 425 .type dvmAsmInstructionStart, %function 426dvmAsmInstructionStart = .L_OP_NOP 427 .text 428 429/* ------------------------------ */ 430 .balign 64 431.L_OP_NOP: /* 0x00 */ 432/* File: armv5te/OP_NOP.S */ 433 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST 434 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 435 GOTO_OPCODE(ip) @ execute it 436 437#ifdef ASSIST_DEBUGGER 438 /* insert fake function header to help gdb find the stack frame */ 439 .type dalvik_inst, %function 440dalvik_inst: 441 .fnstart 442 MTERP_ENTRY1 443 MTERP_ENTRY2 444 .fnend 445#endif 446 447/* ------------------------------ */ 448 .balign 64 449.L_OP_MOVE: /* 0x01 */ 450/* File: armv5te/OP_MOVE.S */ 451 /* for move, move-object, long-to-int */ 452 /* op vA, vB */ 453 mov r1, rINST, lsr #12 @ r1<- B from 15:12 454 mov r0, rINST, lsr #8 @ r0<- A from 11:8 455 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 456 GET_VREG(r2, r1) @ r2<- fp[B] 457 and r0, r0, #15 458 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 459 SET_VREG(r2, r0) @ fp[A]<- r2 460 GOTO_OPCODE(ip) @ execute next instruction 461 462/* ------------------------------ */ 463 .balign 64 464.L_OP_MOVE_FROM16: /* 0x02 */ 465/* File: armv5te/OP_MOVE_FROM16.S */ 466 /* for: move/from16, move-object/from16 */ 467 /* op vAA, vBBBB */ 468 FETCH(r1, 1) @ r1<- BBBB 469 mov r0, rINST, lsr #8 @ r0<- AA 470 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 471 GET_VREG(r2, r1) @ r2<- fp[BBBB] 472 GET_INST_OPCODE(ip) @ extract opcode from rINST 473 SET_VREG(r2, r0) @ fp[AA]<- r2 474 GOTO_OPCODE(ip) @ jump to next instruction 475 476/* ------------------------------ */ 477 .balign 64 478.L_OP_MOVE_16: /* 0x03 */ 479/* File: armv5te/OP_MOVE_16.S */ 480 /* for: move/16, move-object/16 */ 481 /* op vAAAA, vBBBB */ 482 FETCH(r1, 2) @ r1<- BBBB 483 FETCH(r0, 1) @ r0<- AAAA 484 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 485 GET_VREG(r2, r1) @ r2<- fp[BBBB] 486 GET_INST_OPCODE(ip) @ extract opcode from rINST 487 SET_VREG(r2, r0) @ fp[AAAA]<- r2 488 GOTO_OPCODE(ip) @ jump to next instruction 489 490/* ------------------------------ */ 491 .balign 64 492.L_OP_MOVE_WIDE: /* 0x04 */ 493/* File: armv5te/OP_MOVE_WIDE.S */ 494 /* move-wide vA, vB */ 495 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 496 mov r2, rINST, lsr #8 @ r2<- A(+) 497 mov r3, rINST, lsr #12 @ r3<- B 498 and r2, r2, #15 499 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 500 add r2, rFP, r2, lsl #2 @ r2<- &fp[A] 501 ldmia r3, {r0-r1} @ r0/r1<- fp[B] 502 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 503 GET_INST_OPCODE(ip) @ extract opcode from rINST 504 stmia r2, {r0-r1} @ fp[A]<- r0/r1 505 GOTO_OPCODE(ip) @ jump to next instruction 506 507/* ------------------------------ */ 508 .balign 64 509.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 510/* File: armv5te/OP_MOVE_WIDE_FROM16.S */ 511 /* move-wide/from16 vAA, vBBBB */ 512 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 513 FETCH(r3, 1) @ r3<- BBBB 514 mov r2, rINST, lsr #8 @ r2<- AA 515 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 516 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 517 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 518 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 519 GET_INST_OPCODE(ip) @ extract opcode from rINST 520 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 521 GOTO_OPCODE(ip) @ jump to next instruction 522 523/* ------------------------------ */ 524 .balign 64 525.L_OP_MOVE_WIDE_16: /* 0x06 */ 526/* File: armv5te/OP_MOVE_WIDE_16.S */ 527 /* move-wide/16 vAAAA, vBBBB */ 528 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 529 FETCH(r3, 2) @ r3<- BBBB 530 FETCH(r2, 1) @ r2<- AAAA 531 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 532 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA] 533 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 534 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 535 GET_INST_OPCODE(ip) @ extract opcode from rINST 536 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1 537 GOTO_OPCODE(ip) @ jump to next instruction 538 539/* ------------------------------ */ 540 .balign 64 541.L_OP_MOVE_OBJECT: /* 0x07 */ 542/* File: armv5te/OP_MOVE_OBJECT.S */ 543/* File: armv5te/OP_MOVE.S */ 544 /* for move, move-object, long-to-int */ 545 /* op vA, vB */ 546 mov r1, rINST, lsr #12 @ r1<- B from 15:12 547 mov r0, rINST, lsr #8 @ r0<- A from 11:8 548 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 549 GET_VREG(r2, r1) @ r2<- fp[B] 550 and r0, r0, #15 551 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 552 SET_VREG(r2, r0) @ fp[A]<- r2 553 GOTO_OPCODE(ip) @ execute next instruction 554 555 556/* ------------------------------ */ 557 .balign 64 558.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 559/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */ 560/* File: armv5te/OP_MOVE_FROM16.S */ 561 /* for: move/from16, move-object/from16 */ 562 /* op vAA, vBBBB */ 563 FETCH(r1, 1) @ r1<- BBBB 564 mov r0, rINST, lsr #8 @ r0<- AA 565 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 566 GET_VREG(r2, r1) @ r2<- fp[BBBB] 567 GET_INST_OPCODE(ip) @ extract opcode from rINST 568 SET_VREG(r2, r0) @ fp[AA]<- r2 569 GOTO_OPCODE(ip) @ jump to next instruction 570 571 572/* ------------------------------ */ 573 .balign 64 574.L_OP_MOVE_OBJECT_16: /* 0x09 */ 575/* File: armv5te/OP_MOVE_OBJECT_16.S */ 576/* File: armv5te/OP_MOVE_16.S */ 577 /* for: move/16, move-object/16 */ 578 /* op vAAAA, vBBBB */ 579 FETCH(r1, 2) @ r1<- BBBB 580 FETCH(r0, 1) @ r0<- AAAA 581 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 582 GET_VREG(r2, r1) @ r2<- fp[BBBB] 583 GET_INST_OPCODE(ip) @ extract opcode from rINST 584 SET_VREG(r2, r0) @ fp[AAAA]<- r2 585 GOTO_OPCODE(ip) @ jump to next instruction 586 587 588/* ------------------------------ */ 589 .balign 64 590.L_OP_MOVE_RESULT: /* 0x0a */ 591/* File: armv5te/OP_MOVE_RESULT.S */ 592 /* for: move-result, move-result-object */ 593 /* op vAA */ 594 mov r2, rINST, lsr #8 @ r2<- AA 595 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 596 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 597 GET_INST_OPCODE(ip) @ extract opcode from rINST 598 SET_VREG(r0, r2) @ fp[AA]<- r0 599 GOTO_OPCODE(ip) @ jump to next instruction 600 601/* ------------------------------ */ 602 .balign 64 603.L_OP_MOVE_RESULT_WIDE: /* 0x0b */ 604/* File: armv5te/OP_MOVE_RESULT_WIDE.S */ 605 /* move-result-wide vAA */ 606 mov r2, rINST, lsr #8 @ r2<- AA 607 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 608 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 609 ldmia r3, {r0-r1} @ r0/r1<- retval.j 610 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 611 GET_INST_OPCODE(ip) @ extract opcode from rINST 612 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 613 GOTO_OPCODE(ip) @ jump to next instruction 614 615/* ------------------------------ */ 616 .balign 64 617.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 618/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */ 619/* File: armv5te/OP_MOVE_RESULT.S */ 620 /* for: move-result, move-result-object */ 621 /* op vAA */ 622 mov r2, rINST, lsr #8 @ r2<- AA 623 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 624 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 625 GET_INST_OPCODE(ip) @ extract opcode from rINST 626 SET_VREG(r0, r2) @ fp[AA]<- r0 627 GOTO_OPCODE(ip) @ jump to next instruction 628 629 630/* ------------------------------ */ 631 .balign 64 632.L_OP_MOVE_EXCEPTION: /* 0x0d */ 633/* File: armv5te/OP_MOVE_EXCEPTION.S */ 634 /* move-exception vAA */ 635 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 636 mov r2, rINST, lsr #8 @ r2<- AA 637 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass 638 mov r1, #0 @ r1<- 0 639 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 640 SET_VREG(r3, r2) @ fp[AA]<- exception obj 641 GET_INST_OPCODE(ip) @ extract opcode from rINST 642 str r1, [r0, #offThread_exception] @ dvmClearException bypass 643 GOTO_OPCODE(ip) @ jump to next instruction 644 645/* ------------------------------ */ 646 .balign 64 647.L_OP_RETURN_VOID: /* 0x0e */ 648/* File: armv5te/OP_RETURN_VOID.S */ 649 b common_returnFromMethod 650 651/* ------------------------------ */ 652 .balign 64 653.L_OP_RETURN: /* 0x0f */ 654/* File: armv5te/OP_RETURN.S */ 655 /* 656 * Return a 32-bit value. Copies the return value into the "glue" 657 * structure, then jumps to the return handler. 658 * 659 * for: return, return-object 660 */ 661 /* op vAA */ 662 mov r2, rINST, lsr #8 @ r2<- AA 663 GET_VREG(r0, r2) @ r0<- vAA 664 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 665 b common_returnFromMethod 666 667/* ------------------------------ */ 668 .balign 64 669.L_OP_RETURN_WIDE: /* 0x10 */ 670/* File: armv5te/OP_RETURN_WIDE.S */ 671 /* 672 * Return a 64-bit value. Copies the return value into the "glue" 673 * structure, then jumps to the return handler. 674 */ 675 /* return-wide vAA */ 676 mov r2, rINST, lsr #8 @ r2<- AA 677 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 678 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 679 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1 680 stmia r3, {r0-r1} @ retval<- r0/r1 681 b common_returnFromMethod 682 683/* ------------------------------ */ 684 .balign 64 685.L_OP_RETURN_OBJECT: /* 0x11 */ 686/* File: armv5te/OP_RETURN_OBJECT.S */ 687/* File: armv5te/OP_RETURN.S */ 688 /* 689 * Return a 32-bit value. Copies the return value into the "glue" 690 * structure, then jumps to the return handler. 691 * 692 * for: return, return-object 693 */ 694 /* op vAA */ 695 mov r2, rINST, lsr #8 @ r2<- AA 696 GET_VREG(r0, r2) @ r0<- vAA 697 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 698 b common_returnFromMethod 699 700 701/* ------------------------------ */ 702 .balign 64 703.L_OP_CONST_4: /* 0x12 */ 704/* File: armv5te/OP_CONST_4.S */ 705 /* const/4 vA, #+B */ 706 mov r1, rINST, lsl #16 @ r1<- Bxxx0000 707 mov r0, rINST, lsr #8 @ r0<- A+ 708 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 709 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended) 710 and r0, r0, #15 711 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 712 SET_VREG(r1, r0) @ fp[A]<- r1 713 GOTO_OPCODE(ip) @ execute next instruction 714 715/* ------------------------------ */ 716 .balign 64 717.L_OP_CONST_16: /* 0x13 */ 718/* File: armv5te/OP_CONST_16.S */ 719 /* const/16 vAA, #+BBBB */ 720 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 721 mov r3, rINST, lsr #8 @ r3<- AA 722 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 723 SET_VREG(r0, r3) @ vAA<- r0 724 GET_INST_OPCODE(ip) @ extract opcode from rINST 725 GOTO_OPCODE(ip) @ jump to next instruction 726 727/* ------------------------------ */ 728 .balign 64 729.L_OP_CONST: /* 0x14 */ 730/* File: armv5te/OP_CONST.S */ 731 /* const vAA, #+BBBBbbbb */ 732 mov r3, rINST, lsr #8 @ r3<- AA 733 FETCH(r0, 1) @ r0<- bbbb (low) 734 FETCH(r1, 2) @ r1<- BBBB (high) 735 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 736 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 737 GET_INST_OPCODE(ip) @ extract opcode from rINST 738 SET_VREG(r0, r3) @ vAA<- r0 739 GOTO_OPCODE(ip) @ jump to next instruction 740 741/* ------------------------------ */ 742 .balign 64 743.L_OP_CONST_HIGH16: /* 0x15 */ 744/* File: armv5te/OP_CONST_HIGH16.S */ 745 /* const/high16 vAA, #+BBBB0000 */ 746 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended) 747 mov r3, rINST, lsr #8 @ r3<- AA 748 mov r0, r0, lsl #16 @ r0<- BBBB0000 749 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 750 SET_VREG(r0, r3) @ vAA<- r0 751 GET_INST_OPCODE(ip) @ extract opcode from rINST 752 GOTO_OPCODE(ip) @ jump to next instruction 753 754/* ------------------------------ */ 755 .balign 64 756.L_OP_CONST_WIDE_16: /* 0x16 */ 757/* File: armv5te/OP_CONST_WIDE_16.S */ 758 /* const-wide/16 vAA, #+BBBB */ 759 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 760 mov r3, rINST, lsr #8 @ r3<- AA 761 mov r1, r0, asr #31 @ r1<- ssssssss 762 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 763 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 764 GET_INST_OPCODE(ip) @ extract opcode from rINST 765 stmia r3, {r0-r1} @ vAA<- r0/r1 766 GOTO_OPCODE(ip) @ jump to next instruction 767 768/* ------------------------------ */ 769 .balign 64 770.L_OP_CONST_WIDE_32: /* 0x17 */ 771/* File: armv5te/OP_CONST_WIDE_32.S */ 772 /* const-wide/32 vAA, #+BBBBbbbb */ 773 FETCH(r0, 1) @ r0<- 0000bbbb (low) 774 mov r3, rINST, lsr #8 @ r3<- AA 775 FETCH_S(r2, 2) @ r2<- ssssBBBB (high) 776 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 777 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb 778 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 779 mov r1, r0, asr #31 @ r1<- ssssssss 780 GET_INST_OPCODE(ip) @ extract opcode from rINST 781 stmia r3, {r0-r1} @ vAA<- r0/r1 782 GOTO_OPCODE(ip) @ jump to next instruction 783 784/* ------------------------------ */ 785 .balign 64 786.L_OP_CONST_WIDE: /* 0x18 */ 787/* File: armv5te/OP_CONST_WIDE.S */ 788 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 789 FETCH(r0, 1) @ r0<- bbbb (low) 790 FETCH(r1, 2) @ r1<- BBBB (low middle) 791 FETCH(r2, 3) @ r2<- hhhh (high middle) 792 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word) 793 FETCH(r3, 4) @ r3<- HHHH (high) 794 mov r9, rINST, lsr #8 @ r9<- AA 795 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word) 796 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 797 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 798 GET_INST_OPCODE(ip) @ extract opcode from rINST 799 stmia r9, {r0-r1} @ vAA<- r0/r1 800 GOTO_OPCODE(ip) @ jump to next instruction 801 802/* ------------------------------ */ 803 .balign 64 804.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 805/* File: armv5te/OP_CONST_WIDE_HIGH16.S */ 806 /* const-wide/high16 vAA, #+BBBB000000000000 */ 807 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended) 808 mov r3, rINST, lsr #8 @ r3<- AA 809 mov r0, #0 @ r0<- 00000000 810 mov r1, r1, lsl #16 @ r1<- BBBB0000 811 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 812 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 813 GET_INST_OPCODE(ip) @ extract opcode from rINST 814 stmia r3, {r0-r1} @ vAA<- r0/r1 815 GOTO_OPCODE(ip) @ jump to next instruction 816 817/* ------------------------------ */ 818 .balign 64 819.L_OP_CONST_STRING: /* 0x1a */ 820/* File: armv5te/OP_CONST_STRING.S */ 821 /* const/string vAA, String@BBBB */ 822 FETCH(r1, 1) @ r1<- BBBB 823 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 824 mov r9, rINST, lsr #8 @ r9<- AA 825 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 826 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 827 cmp r0, #0 @ not yet resolved? 828 beq .LOP_CONST_STRING_resolve 829 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 830 GET_INST_OPCODE(ip) @ extract opcode from rINST 831 SET_VREG(r0, r9) @ vAA<- r0 832 GOTO_OPCODE(ip) @ jump to next instruction 833 834/* ------------------------------ */ 835 .balign 64 836.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 837/* File: armv5te/OP_CONST_STRING_JUMBO.S */ 838 /* const/string vAA, String@BBBBBBBB */ 839 FETCH(r0, 1) @ r0<- bbbb (low) 840 FETCH(r1, 2) @ r1<- BBBB (high) 841 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 842 mov r9, rINST, lsr #8 @ r9<- AA 843 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 844 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 845 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 846 cmp r0, #0 847 beq .LOP_CONST_STRING_JUMBO_resolve 848 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 849 GET_INST_OPCODE(ip) @ extract opcode from rINST 850 SET_VREG(r0, r9) @ vAA<- r0 851 GOTO_OPCODE(ip) @ jump to next instruction 852 853/* ------------------------------ */ 854 .balign 64 855.L_OP_CONST_CLASS: /* 0x1c */ 856/* File: armv5te/OP_CONST_CLASS.S */ 857 /* const/class vAA, Class@BBBB */ 858 FETCH(r1, 1) @ r1<- BBBB 859 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 860 mov r9, rINST, lsr #8 @ r9<- AA 861 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 862 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB] 863 cmp r0, #0 @ not yet resolved? 864 beq .LOP_CONST_CLASS_resolve 865 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 866 GET_INST_OPCODE(ip) @ extract opcode from rINST 867 SET_VREG(r0, r9) @ vAA<- r0 868 GOTO_OPCODE(ip) @ jump to next instruction 869 870/* ------------------------------ */ 871 .balign 64 872.L_OP_MONITOR_ENTER: /* 0x1d */ 873/* File: armv5te/OP_MONITOR_ENTER.S */ 874 /* 875 * Synchronize on an object. 876 */ 877 /* monitor-enter vAA */ 878 mov r2, rINST, lsr #8 @ r2<- AA 879 GET_VREG(r1, r2) @ r1<- vAA (object) 880 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 881 cmp r1, #0 @ null object? 882 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING 883 beq common_errNullObject @ null object, throw an exception 884 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 885 bl dvmLockObject @ call(self, obj) 886#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ 887 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 888 ldr r1, [r0, #offThread_exception] @ check for exception 889 cmp r1, #0 890 bne common_exceptionThrown @ exception raised, bail out 891#endif 892 GET_INST_OPCODE(ip) @ extract opcode from rINST 893 GOTO_OPCODE(ip) @ jump to next instruction 894 895/* ------------------------------ */ 896 .balign 64 897.L_OP_MONITOR_EXIT: /* 0x1e */ 898/* File: armv5te/OP_MONITOR_EXIT.S */ 899 /* 900 * Unlock an object. 901 * 902 * Exceptions that occur when unlocking a monitor need to appear as 903 * if they happened at the following instruction. See the Dalvik 904 * instruction spec. 905 */ 906 /* monitor-exit vAA */ 907 mov r2, rINST, lsr #8 @ r2<- AA 908 EXPORT_PC() @ before fetch: export the PC 909 GET_VREG(r1, r2) @ r1<- vAA (object) 910 cmp r1, #0 @ null object? 911 beq 1f @ yes 912 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 913 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 914 cmp r0, #0 @ failed? 915 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 916 beq common_exceptionThrown @ yes, exception is pending 917 GET_INST_OPCODE(ip) @ extract opcode from rINST 918 GOTO_OPCODE(ip) @ jump to next instruction 9191: 920 FETCH_ADVANCE_INST(1) @ advance before throw 921 b common_errNullObject 922 923/* ------------------------------ */ 924 .balign 64 925.L_OP_CHECK_CAST: /* 0x1f */ 926/* File: armv5te/OP_CHECK_CAST.S */ 927 /* 928 * Check to see if a cast from one class to another is allowed. 929 */ 930 /* check-cast vAA, class@BBBB */ 931 mov r3, rINST, lsr #8 @ r3<- AA 932 FETCH(r2, 1) @ r2<- BBBB 933 GET_VREG(r9, r3) @ r9<- object 934 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 935 cmp r9, #0 @ is object null? 936 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 937 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 938 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 939 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 940 cmp r1, #0 @ have we resolved this before? 941 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 942.LOP_CHECK_CAST_resolved: 943 cmp r0, r1 @ same class (trivial success)? 944 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 945.LOP_CHECK_CAST_okay: 946 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 947 GET_INST_OPCODE(ip) @ extract opcode from rINST 948 GOTO_OPCODE(ip) @ jump to next instruction 949 950/* ------------------------------ */ 951 .balign 64 952.L_OP_INSTANCE_OF: /* 0x20 */ 953/* File: armv5te/OP_INSTANCE_OF.S */ 954 /* 955 * Check to see if an object reference is an instance of a class. 956 * 957 * Most common situation is a non-null object, being compared against 958 * an already-resolved class. 959 */ 960 /* instance-of vA, vB, class@CCCC */ 961 mov r3, rINST, lsr #12 @ r3<- B 962 mov r9, rINST, lsr #8 @ r9<- A+ 963 GET_VREG(r0, r3) @ r0<- vB (object) 964 and r9, r9, #15 @ r9<- A 965 cmp r0, #0 @ is object null? 966 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 967 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 968 FETCH(r3, 1) @ r3<- CCCC 969 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 970 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 971 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 972 cmp r1, #0 @ have we resolved this before? 973 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 974.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 975 cmp r0, r1 @ same class (trivial success)? 976 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 977 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 978 979/* ------------------------------ */ 980 .balign 64 981.L_OP_ARRAY_LENGTH: /* 0x21 */ 982/* File: armv5te/OP_ARRAY_LENGTH.S */ 983 /* 984 * Return the length of an array. 985 */ 986 mov r1, rINST, lsr #12 @ r1<- B 987 mov r2, rINST, lsr #8 @ r2<- A+ 988 GET_VREG(r0, r1) @ r0<- vB (object ref) 989 and r2, r2, #15 @ r2<- A 990 cmp r0, #0 @ is object null? 991 beq common_errNullObject @ yup, fail 992 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 993 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 994 GET_INST_OPCODE(ip) @ extract opcode from rINST 995 SET_VREG(r3, r2) @ vB<- length 996 GOTO_OPCODE(ip) @ jump to next instruction 997 998/* ------------------------------ */ 999 .balign 64 1000.L_OP_NEW_INSTANCE: /* 0x22 */ 1001/* File: armv5te/OP_NEW_INSTANCE.S */ 1002 /* 1003 * Create a new instance of a class. 1004 */ 1005 /* new-instance vAA, class@BBBB */ 1006 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1007 FETCH(r1, 1) @ r1<- BBBB 1008 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1009 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1010 EXPORT_PC() @ req'd for init, resolve, alloc 1011 cmp r0, #0 @ already resolved? 1012 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 1013.LOP_NEW_INSTANCE_resolved: @ r0=class 1014 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 1015 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 1016 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 1017.LOP_NEW_INSTANCE_initialized: @ r0=class 1018 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 1019 bl dvmAllocObject @ r0<- new object 1020 b .LOP_NEW_INSTANCE_finish @ continue 1021 1022/* ------------------------------ */ 1023 .balign 64 1024.L_OP_NEW_ARRAY: /* 0x23 */ 1025/* File: armv5te/OP_NEW_ARRAY.S */ 1026 /* 1027 * Allocate an array of objects, specified with the array class 1028 * and a count. 1029 * 1030 * The verifier guarantees that this is an array class, so we don't 1031 * check for it here. 1032 */ 1033 /* new-array vA, vB, class@CCCC */ 1034 mov r0, rINST, lsr #12 @ r0<- B 1035 FETCH(r2, 1) @ r2<- CCCC 1036 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1037 GET_VREG(r1, r0) @ r1<- vB (array length) 1038 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1039 cmp r1, #0 @ check length 1040 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 1041 bmi common_errNegativeArraySize @ negative length, bail 1042 cmp r0, #0 @ already resolved? 1043 EXPORT_PC() @ req'd for resolve, alloc 1044 bne .LOP_NEW_ARRAY_finish @ resolved, continue 1045 b .LOP_NEW_ARRAY_resolve @ do resolve now 1046 1047/* ------------------------------ */ 1048 .balign 64 1049.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1050/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1051 /* 1052 * Create a new array with elements filled from registers. 1053 * 1054 * for: filled-new-array, filled-new-array/range 1055 */ 1056 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1057 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1058 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1059 FETCH(r1, 1) @ r1<- BBBB 1060 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1061 EXPORT_PC() @ need for resolve and alloc 1062 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1063 mov r10, rINST, lsr #8 @ r10<- AA or BA 1064 cmp r0, #0 @ already resolved? 1065 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10668: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1067 mov r2, #0 @ r2<- false 1068 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1069 bl dvmResolveClass @ r0<- call(clazz, ref) 1070 cmp r0, #0 @ got null? 1071 beq common_exceptionThrown @ yes, handle exception 1072 b .LOP_FILLED_NEW_ARRAY_continue 1073 1074/* ------------------------------ */ 1075 .balign 64 1076.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1077/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1078/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1079 /* 1080 * Create a new array with elements filled from registers. 1081 * 1082 * for: filled-new-array, filled-new-array/range 1083 */ 1084 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1085 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1086 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1087 FETCH(r1, 1) @ r1<- BBBB 1088 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1089 EXPORT_PC() @ need for resolve and alloc 1090 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1091 mov r10, rINST, lsr #8 @ r10<- AA or BA 1092 cmp r0, #0 @ already resolved? 1093 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10948: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1095 mov r2, #0 @ r2<- false 1096 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1097 bl dvmResolveClass @ r0<- call(clazz, ref) 1098 cmp r0, #0 @ got null? 1099 beq common_exceptionThrown @ yes, handle exception 1100 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1101 1102 1103/* ------------------------------ */ 1104 .balign 64 1105.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1106/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1107 /* fill-array-data vAA, +BBBBBBBB */ 1108 FETCH(r0, 1) @ r0<- bbbb (lo) 1109 FETCH(r1, 2) @ r1<- BBBB (hi) 1110 mov r3, rINST, lsr #8 @ r3<- AA 1111 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1112 GET_VREG(r0, r3) @ r0<- vAA (array object) 1113 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1114 EXPORT_PC(); 1115 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1116 cmp r0, #0 @ 0 means an exception is thrown 1117 beq common_exceptionThrown @ has exception 1118 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1119 GET_INST_OPCODE(ip) @ extract opcode from rINST 1120 GOTO_OPCODE(ip) @ jump to next instruction 1121 1122/* ------------------------------ */ 1123 .balign 64 1124.L_OP_THROW: /* 0x27 */ 1125/* File: armv5te/OP_THROW.S */ 1126 /* 1127 * Throw an exception object in the current thread. 1128 */ 1129 /* throw vAA */ 1130 mov r2, rINST, lsr #8 @ r2<- AA 1131 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1132 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1133 EXPORT_PC() @ exception handler can throw 1134 cmp r1, #0 @ null object? 1135 beq common_errNullObject @ yes, throw an NPE instead 1136 @ bypass dvmSetException, just store it 1137 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1138 b common_exceptionThrown 1139 1140/* ------------------------------ */ 1141 .balign 64 1142.L_OP_GOTO: /* 0x28 */ 1143/* File: armv5te/OP_GOTO.S */ 1144 /* 1145 * Unconditional branch, 8-bit offset. 1146 * 1147 * The branch distance is a signed code-unit offset, which we need to 1148 * double to get a byte offset. 1149 */ 1150 /* goto +AA */ 1151 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1152 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1153 mov r9, r9, lsl #1 @ r9<- byte offset 1154 bmi common_backwardBranch @ backward branch, do periodic checks 1155#if defined(WITH_JIT) 1156 GET_JIT_PROF_TABLE(r0) 1157 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1158 cmp r0,#0 1159 bne common_updateProfile 1160 GET_INST_OPCODE(ip) @ extract opcode from rINST 1161 GOTO_OPCODE(ip) @ jump to next instruction 1162#else 1163 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1164 GET_INST_OPCODE(ip) @ extract opcode from rINST 1165 GOTO_OPCODE(ip) @ jump to next instruction 1166#endif 1167 1168/* ------------------------------ */ 1169 .balign 64 1170.L_OP_GOTO_16: /* 0x29 */ 1171/* File: armv5te/OP_GOTO_16.S */ 1172 /* 1173 * Unconditional branch, 16-bit offset. 1174 * 1175 * The branch distance is a signed code-unit offset, which we need to 1176 * double to get a byte offset. 1177 */ 1178 /* goto/16 +AAAA */ 1179 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1180 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1181 bmi common_backwardBranch @ backward branch, do periodic checks 1182#if defined(WITH_JIT) 1183 GET_JIT_PROF_TABLE(r0) 1184 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1185 cmp r0,#0 1186 bne common_updateProfile 1187 GET_INST_OPCODE(ip) @ extract opcode from rINST 1188 GOTO_OPCODE(ip) @ jump to next instruction 1189#else 1190 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1191 GET_INST_OPCODE(ip) @ extract opcode from rINST 1192 GOTO_OPCODE(ip) @ jump to next instruction 1193#endif 1194 1195/* ------------------------------ */ 1196 .balign 64 1197.L_OP_GOTO_32: /* 0x2a */ 1198/* File: armv5te/OP_GOTO_32.S */ 1199 /* 1200 * Unconditional branch, 32-bit offset. 1201 * 1202 * The branch distance is a signed code-unit offset, which we need to 1203 * double to get a byte offset. 1204 * 1205 * Unlike most opcodes, this one is allowed to branch to itself, so 1206 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1207 * instruction doesn't affect the V flag, so we need to clear it 1208 * explicitly. 1209 */ 1210 /* goto/32 +AAAAAAAA */ 1211 FETCH(r0, 1) @ r0<- aaaa (lo) 1212 FETCH(r1, 2) @ r1<- AAAA (hi) 1213 cmp ip, ip @ (clear V flag during stall) 1214 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1215 mov r9, r0, asl #1 @ r9<- byte offset 1216 ble common_backwardBranch @ backward branch, do periodic checks 1217#if defined(WITH_JIT) 1218 GET_JIT_PROF_TABLE(r0) 1219 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1220 cmp r0,#0 1221 bne common_updateProfile 1222 GET_INST_OPCODE(ip) @ extract opcode from rINST 1223 GOTO_OPCODE(ip) @ jump to next instruction 1224#else 1225 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1226 GET_INST_OPCODE(ip) @ extract opcode from rINST 1227 GOTO_OPCODE(ip) @ jump to next instruction 1228#endif 1229 1230/* ------------------------------ */ 1231 .balign 64 1232.L_OP_PACKED_SWITCH: /* 0x2b */ 1233/* File: armv5te/OP_PACKED_SWITCH.S */ 1234 /* 1235 * Handle a packed-switch or sparse-switch instruction. In both cases 1236 * we decode it and hand it off to a helper function. 1237 * 1238 * We don't really expect backward branches in a switch statement, but 1239 * they're perfectly legal, so we check for them here. 1240 * 1241 * for: packed-switch, sparse-switch 1242 */ 1243 /* op vAA, +BBBB */ 1244 FETCH(r0, 1) @ r0<- bbbb (lo) 1245 FETCH(r1, 2) @ r1<- BBBB (hi) 1246 mov r3, rINST, lsr #8 @ r3<- AA 1247 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1248 GET_VREG(r1, r3) @ r1<- vAA 1249 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1250 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1251 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1252 bmi common_backwardBranch @ backward branch, do periodic checks 1253 beq common_backwardBranch @ (want to use BLE but V is unknown) 1254#if defined(WITH_JIT) 1255 GET_JIT_PROF_TABLE(r0) 1256 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1257 cmp r0,#0 1258 bne common_updateProfile 1259 GET_INST_OPCODE(ip) @ extract opcode from rINST 1260 GOTO_OPCODE(ip) @ jump to next instruction 1261#else 1262 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1263 GET_INST_OPCODE(ip) @ extract opcode from rINST 1264 GOTO_OPCODE(ip) @ jump to next instruction 1265#endif 1266 1267/* ------------------------------ */ 1268 .balign 64 1269.L_OP_SPARSE_SWITCH: /* 0x2c */ 1270/* File: armv5te/OP_SPARSE_SWITCH.S */ 1271/* File: armv5te/OP_PACKED_SWITCH.S */ 1272 /* 1273 * Handle a packed-switch or sparse-switch instruction. In both cases 1274 * we decode it and hand it off to a helper function. 1275 * 1276 * We don't really expect backward branches in a switch statement, but 1277 * they're perfectly legal, so we check for them here. 1278 * 1279 * for: packed-switch, sparse-switch 1280 */ 1281 /* op vAA, +BBBB */ 1282 FETCH(r0, 1) @ r0<- bbbb (lo) 1283 FETCH(r1, 2) @ r1<- BBBB (hi) 1284 mov r3, rINST, lsr #8 @ r3<- AA 1285 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1286 GET_VREG(r1, r3) @ r1<- vAA 1287 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1288 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1289 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1290 bmi common_backwardBranch @ backward branch, do periodic checks 1291 beq common_backwardBranch @ (want to use BLE but V is unknown) 1292#if defined(WITH_JIT) 1293 GET_JIT_PROF_TABLE(r0) 1294 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1295 cmp r0,#0 1296 bne common_updateProfile 1297 GET_INST_OPCODE(ip) @ extract opcode from rINST 1298 GOTO_OPCODE(ip) @ jump to next instruction 1299#else 1300 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1301 GET_INST_OPCODE(ip) @ extract opcode from rINST 1302 GOTO_OPCODE(ip) @ jump to next instruction 1303#endif 1304 1305 1306/* ------------------------------ */ 1307 .balign 64 1308.L_OP_CMPL_FLOAT: /* 0x2d */ 1309/* File: arm-vfp/OP_CMPL_FLOAT.S */ 1310 /* 1311 * Compare two floating-point values. Puts 0, 1, or -1 into the 1312 * destination register based on the results of the comparison. 1313 * 1314 * int compare(x, y) { 1315 * if (x == y) { 1316 * return 0; 1317 * } else if (x > y) { 1318 * return 1; 1319 * } else if (x < y) { 1320 * return -1; 1321 * } else { 1322 * return -1; 1323 * } 1324 * } 1325 */ 1326 /* op vAA, vBB, vCC */ 1327 FETCH(r0, 1) @ r0<- CCBB 1328 mov r9, rINST, lsr #8 @ r9<- AA 1329 and r2, r0, #255 @ r2<- BB 1330 mov r3, r0, lsr #8 @ r3<- CC 1331 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1332 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1333 flds s0, [r2] @ s0<- vBB 1334 flds s1, [r3] @ s1<- vCC 1335 fcmpes s0, s1 @ compare (vBB, vCC) 1336 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1337 mvn r0, #0 @ r0<- -1 (default) 1338 GET_INST_OPCODE(ip) @ extract opcode from rINST 1339 fmstat @ export status flags 1340 movgt r0, #1 @ (greater than) r1<- 1 1341 moveq r0, #0 @ (equal) r1<- 0 1342 b .LOP_CMPL_FLOAT_finish @ argh 1343 1344 1345/* ------------------------------ */ 1346 .balign 64 1347.L_OP_CMPG_FLOAT: /* 0x2e */ 1348/* File: arm-vfp/OP_CMPG_FLOAT.S */ 1349 /* 1350 * Compare two floating-point values. Puts 0, 1, or -1 into the 1351 * destination register based on the results of the comparison. 1352 * 1353 * int compare(x, y) { 1354 * if (x == y) { 1355 * return 0; 1356 * } else if (x < y) { 1357 * return -1; 1358 * } else if (x > y) { 1359 * return 1; 1360 * } else { 1361 * return 1; 1362 * } 1363 * } 1364 */ 1365 /* op vAA, vBB, vCC */ 1366 FETCH(r0, 1) @ r0<- CCBB 1367 mov r9, rINST, lsr #8 @ r9<- AA 1368 and r2, r0, #255 @ r2<- BB 1369 mov r3, r0, lsr #8 @ r3<- CC 1370 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1371 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1372 flds s0, [r2] @ s0<- vBB 1373 flds s1, [r3] @ s1<- vCC 1374 fcmpes s0, s1 @ compare (vBB, vCC) 1375 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1376 mov r0, #1 @ r0<- 1 (default) 1377 GET_INST_OPCODE(ip) @ extract opcode from rINST 1378 fmstat @ export status flags 1379 mvnmi r0, #0 @ (less than) r1<- -1 1380 moveq r0, #0 @ (equal) r1<- 0 1381 b .LOP_CMPG_FLOAT_finish @ argh 1382 1383 1384/* ------------------------------ */ 1385 .balign 64 1386.L_OP_CMPL_DOUBLE: /* 0x2f */ 1387/* File: arm-vfp/OP_CMPL_DOUBLE.S */ 1388 /* 1389 * Compare two floating-point values. Puts 0, 1, or -1 into the 1390 * destination register based on the results of the comparison. 1391 * 1392 * int compare(x, y) { 1393 * if (x == y) { 1394 * return 0; 1395 * } else if (x > y) { 1396 * return 1; 1397 * } else if (x < y) { 1398 * return -1; 1399 * } else { 1400 * return -1; 1401 * } 1402 * } 1403 */ 1404 /* op vAA, vBB, vCC */ 1405 FETCH(r0, 1) @ r0<- CCBB 1406 mov r9, rINST, lsr #8 @ r9<- AA 1407 and r2, r0, #255 @ r2<- BB 1408 mov r3, r0, lsr #8 @ r3<- CC 1409 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1410 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1411 fldd d0, [r2] @ d0<- vBB 1412 fldd d1, [r3] @ d1<- vCC 1413 fcmped d0, d1 @ compare (vBB, vCC) 1414 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1415 mvn r0, #0 @ r0<- -1 (default) 1416 GET_INST_OPCODE(ip) @ extract opcode from rINST 1417 fmstat @ export status flags 1418 movgt r0, #1 @ (greater than) r1<- 1 1419 moveq r0, #0 @ (equal) r1<- 0 1420 b .LOP_CMPL_DOUBLE_finish @ argh 1421 1422 1423/* ------------------------------ */ 1424 .balign 64 1425.L_OP_CMPG_DOUBLE: /* 0x30 */ 1426/* File: arm-vfp/OP_CMPG_DOUBLE.S */ 1427 /* 1428 * Compare two floating-point values. Puts 0, 1, or -1 into the 1429 * destination register based on the results of the comparison. 1430 * 1431 * int compare(x, y) { 1432 * if (x == y) { 1433 * return 0; 1434 * } else if (x < y) { 1435 * return -1; 1436 * } else if (x > y) { 1437 * return 1; 1438 * } else { 1439 * return 1; 1440 * } 1441 * } 1442 */ 1443 /* op vAA, vBB, vCC */ 1444 FETCH(r0, 1) @ r0<- CCBB 1445 mov r9, rINST, lsr #8 @ r9<- AA 1446 and r2, r0, #255 @ r2<- BB 1447 mov r3, r0, lsr #8 @ r3<- CC 1448 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1449 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1450 fldd d0, [r2] @ d0<- vBB 1451 fldd d1, [r3] @ d1<- vCC 1452 fcmped d0, d1 @ compare (vBB, vCC) 1453 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1454 mov r0, #1 @ r0<- 1 (default) 1455 GET_INST_OPCODE(ip) @ extract opcode from rINST 1456 fmstat @ export status flags 1457 mvnmi r0, #0 @ (less than) r1<- -1 1458 moveq r0, #0 @ (equal) r1<- 0 1459 b .LOP_CMPG_DOUBLE_finish @ argh 1460 1461 1462/* ------------------------------ */ 1463 .balign 64 1464.L_OP_CMP_LONG: /* 0x31 */ 1465/* File: armv5te/OP_CMP_LONG.S */ 1466 /* 1467 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1468 * register based on the results of the comparison. 1469 * 1470 * We load the full values with LDM, but in practice many values could 1471 * be resolved by only looking at the high word. This could be made 1472 * faster or slower by splitting the LDM into a pair of LDRs. 1473 * 1474 * If we just wanted to set condition flags, we could do this: 1475 * subs ip, r0, r2 1476 * sbcs ip, r1, r3 1477 * subeqs ip, r0, r2 1478 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1479 * integer value, which we can do with 2 conditional mov/mvn instructions 1480 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1481 * us a constant 5-cycle path plus a branch at the end to the 1482 * instruction epilogue code. The multi-compare approach below needs 1483 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1484 * in the worst case (the 64-bit values are equal). 1485 */ 1486 /* cmp-long vAA, vBB, vCC */ 1487 FETCH(r0, 1) @ r0<- CCBB 1488 mov r9, rINST, lsr #8 @ r9<- AA 1489 and r2, r0, #255 @ r2<- BB 1490 mov r3, r0, lsr #8 @ r3<- CC 1491 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1492 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1493 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1494 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1495 cmp r1, r3 @ compare (vBB+1, vCC+1) 1496 blt .LOP_CMP_LONG_less @ signed compare on high part 1497 bgt .LOP_CMP_LONG_greater 1498 subs r1, r0, r2 @ r1<- r0 - r2 1499 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1500 bne .LOP_CMP_LONG_less 1501 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1502 1503/* ------------------------------ */ 1504 .balign 64 1505.L_OP_IF_EQ: /* 0x32 */ 1506/* File: armv5te/OP_IF_EQ.S */ 1507/* File: armv5te/bincmp.S */ 1508 /* 1509 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1510 * fragment that specifies the *reverse* comparison to perform, e.g. 1511 * for "if-le" you would use "gt". 1512 * 1513 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1514 */ 1515 /* if-cmp vA, vB, +CCCC */ 1516 mov r0, rINST, lsr #8 @ r0<- A+ 1517 mov r1, rINST, lsr #12 @ r1<- B 1518 and r0, r0, #15 1519 GET_VREG(r3, r1) @ r3<- vB 1520 GET_VREG(r2, r0) @ r2<- vA 1521 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1522 cmp r2, r3 @ compare (vA, vB) 1523 bne 1f @ branch to 1 if comparison failed 1524 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1525 movs r9, r9, asl #1 @ convert to bytes, check sign 1526 bmi common_backwardBranch @ yes, do periodic checks 15271: 1528#if defined(WITH_JIT) 1529 GET_JIT_PROF_TABLE(r0) 1530 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1531 b common_testUpdateProfile 1532#else 1533 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1534 GET_INST_OPCODE(ip) @ extract opcode from rINST 1535 GOTO_OPCODE(ip) @ jump to next instruction 1536#endif 1537 1538 1539/* ------------------------------ */ 1540 .balign 64 1541.L_OP_IF_NE: /* 0x33 */ 1542/* File: armv5te/OP_IF_NE.S */ 1543/* File: armv5te/bincmp.S */ 1544 /* 1545 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1546 * fragment that specifies the *reverse* comparison to perform, e.g. 1547 * for "if-le" you would use "gt". 1548 * 1549 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1550 */ 1551 /* if-cmp vA, vB, +CCCC */ 1552 mov r0, rINST, lsr #8 @ r0<- A+ 1553 mov r1, rINST, lsr #12 @ r1<- B 1554 and r0, r0, #15 1555 GET_VREG(r3, r1) @ r3<- vB 1556 GET_VREG(r2, r0) @ r2<- vA 1557 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1558 cmp r2, r3 @ compare (vA, vB) 1559 beq 1f @ branch to 1 if comparison failed 1560 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1561 movs r9, r9, asl #1 @ convert to bytes, check sign 1562 bmi common_backwardBranch @ yes, do periodic checks 15631: 1564#if defined(WITH_JIT) 1565 GET_JIT_PROF_TABLE(r0) 1566 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1567 b common_testUpdateProfile 1568#else 1569 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1570 GET_INST_OPCODE(ip) @ extract opcode from rINST 1571 GOTO_OPCODE(ip) @ jump to next instruction 1572#endif 1573 1574 1575/* ------------------------------ */ 1576 .balign 64 1577.L_OP_IF_LT: /* 0x34 */ 1578/* File: armv5te/OP_IF_LT.S */ 1579/* File: armv5te/bincmp.S */ 1580 /* 1581 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1582 * fragment that specifies the *reverse* comparison to perform, e.g. 1583 * for "if-le" you would use "gt". 1584 * 1585 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1586 */ 1587 /* if-cmp vA, vB, +CCCC */ 1588 mov r0, rINST, lsr #8 @ r0<- A+ 1589 mov r1, rINST, lsr #12 @ r1<- B 1590 and r0, r0, #15 1591 GET_VREG(r3, r1) @ r3<- vB 1592 GET_VREG(r2, r0) @ r2<- vA 1593 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1594 cmp r2, r3 @ compare (vA, vB) 1595 bge 1f @ branch to 1 if comparison failed 1596 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1597 movs r9, r9, asl #1 @ convert to bytes, check sign 1598 bmi common_backwardBranch @ yes, do periodic checks 15991: 1600#if defined(WITH_JIT) 1601 GET_JIT_PROF_TABLE(r0) 1602 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1603 b common_testUpdateProfile 1604#else 1605 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1606 GET_INST_OPCODE(ip) @ extract opcode from rINST 1607 GOTO_OPCODE(ip) @ jump to next instruction 1608#endif 1609 1610 1611/* ------------------------------ */ 1612 .balign 64 1613.L_OP_IF_GE: /* 0x35 */ 1614/* File: armv5te/OP_IF_GE.S */ 1615/* File: armv5te/bincmp.S */ 1616 /* 1617 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1618 * fragment that specifies the *reverse* comparison to perform, e.g. 1619 * for "if-le" you would use "gt". 1620 * 1621 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1622 */ 1623 /* if-cmp vA, vB, +CCCC */ 1624 mov r0, rINST, lsr #8 @ r0<- A+ 1625 mov r1, rINST, lsr #12 @ r1<- B 1626 and r0, r0, #15 1627 GET_VREG(r3, r1) @ r3<- vB 1628 GET_VREG(r2, r0) @ r2<- vA 1629 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1630 cmp r2, r3 @ compare (vA, vB) 1631 blt 1f @ branch to 1 if comparison failed 1632 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1633 movs r9, r9, asl #1 @ convert to bytes, check sign 1634 bmi common_backwardBranch @ yes, do periodic checks 16351: 1636#if defined(WITH_JIT) 1637 GET_JIT_PROF_TABLE(r0) 1638 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1639 b common_testUpdateProfile 1640#else 1641 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1642 GET_INST_OPCODE(ip) @ extract opcode from rINST 1643 GOTO_OPCODE(ip) @ jump to next instruction 1644#endif 1645 1646 1647/* ------------------------------ */ 1648 .balign 64 1649.L_OP_IF_GT: /* 0x36 */ 1650/* File: armv5te/OP_IF_GT.S */ 1651/* File: armv5te/bincmp.S */ 1652 /* 1653 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1654 * fragment that specifies the *reverse* comparison to perform, e.g. 1655 * for "if-le" you would use "gt". 1656 * 1657 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1658 */ 1659 /* if-cmp vA, vB, +CCCC */ 1660 mov r0, rINST, lsr #8 @ r0<- A+ 1661 mov r1, rINST, lsr #12 @ r1<- B 1662 and r0, r0, #15 1663 GET_VREG(r3, r1) @ r3<- vB 1664 GET_VREG(r2, r0) @ r2<- vA 1665 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1666 cmp r2, r3 @ compare (vA, vB) 1667 ble 1f @ branch to 1 if comparison failed 1668 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1669 movs r9, r9, asl #1 @ convert to bytes, check sign 1670 bmi common_backwardBranch @ yes, do periodic checks 16711: 1672#if defined(WITH_JIT) 1673 GET_JIT_PROF_TABLE(r0) 1674 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1675 b common_testUpdateProfile 1676#else 1677 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1678 GET_INST_OPCODE(ip) @ extract opcode from rINST 1679 GOTO_OPCODE(ip) @ jump to next instruction 1680#endif 1681 1682 1683/* ------------------------------ */ 1684 .balign 64 1685.L_OP_IF_LE: /* 0x37 */ 1686/* File: armv5te/OP_IF_LE.S */ 1687/* File: armv5te/bincmp.S */ 1688 /* 1689 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1690 * fragment that specifies the *reverse* comparison to perform, e.g. 1691 * for "if-le" you would use "gt". 1692 * 1693 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1694 */ 1695 /* if-cmp vA, vB, +CCCC */ 1696 mov r0, rINST, lsr #8 @ r0<- A+ 1697 mov r1, rINST, lsr #12 @ r1<- B 1698 and r0, r0, #15 1699 GET_VREG(r3, r1) @ r3<- vB 1700 GET_VREG(r2, r0) @ r2<- vA 1701 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1702 cmp r2, r3 @ compare (vA, vB) 1703 bgt 1f @ branch to 1 if comparison failed 1704 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1705 movs r9, r9, asl #1 @ convert to bytes, check sign 1706 bmi common_backwardBranch @ yes, do periodic checks 17071: 1708#if defined(WITH_JIT) 1709 GET_JIT_PROF_TABLE(r0) 1710 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1711 b common_testUpdateProfile 1712#else 1713 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1714 GET_INST_OPCODE(ip) @ extract opcode from rINST 1715 GOTO_OPCODE(ip) @ jump to next instruction 1716#endif 1717 1718 1719/* ------------------------------ */ 1720 .balign 64 1721.L_OP_IF_EQZ: /* 0x38 */ 1722/* File: armv5te/OP_IF_EQZ.S */ 1723/* File: armv5te/zcmp.S */ 1724 /* 1725 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1726 * fragment that specifies the *reverse* comparison to perform, e.g. 1727 * for "if-le" you would use "gt". 1728 * 1729 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1730 */ 1731 /* if-cmp vAA, +BBBB */ 1732 mov r0, rINST, lsr #8 @ r0<- AA 1733 GET_VREG(r2, r0) @ r2<- vAA 1734 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1735 cmp r2, #0 @ compare (vA, 0) 1736 bne 1f @ branch to 1 if comparison failed 1737 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1738 movs r9, r9, asl #1 @ convert to bytes, check sign 1739 bmi common_backwardBranch @ backward branch, do periodic checks 17401: 1741#if defined(WITH_JIT) 1742 GET_JIT_PROF_TABLE(r0) 1743 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1744 cmp r0,#0 1745 bne common_updateProfile 1746 GET_INST_OPCODE(ip) @ extract opcode from rINST 1747 GOTO_OPCODE(ip) @ jump to next instruction 1748#else 1749 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1750 GET_INST_OPCODE(ip) @ extract opcode from rINST 1751 GOTO_OPCODE(ip) @ jump to next instruction 1752#endif 1753 1754 1755/* ------------------------------ */ 1756 .balign 64 1757.L_OP_IF_NEZ: /* 0x39 */ 1758/* File: armv5te/OP_IF_NEZ.S */ 1759/* File: armv5te/zcmp.S */ 1760 /* 1761 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1762 * fragment that specifies the *reverse* comparison to perform, e.g. 1763 * for "if-le" you would use "gt". 1764 * 1765 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1766 */ 1767 /* if-cmp vAA, +BBBB */ 1768 mov r0, rINST, lsr #8 @ r0<- AA 1769 GET_VREG(r2, r0) @ r2<- vAA 1770 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1771 cmp r2, #0 @ compare (vA, 0) 1772 beq 1f @ branch to 1 if comparison failed 1773 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1774 movs r9, r9, asl #1 @ convert to bytes, check sign 1775 bmi common_backwardBranch @ backward branch, do periodic checks 17761: 1777#if defined(WITH_JIT) 1778 GET_JIT_PROF_TABLE(r0) 1779 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1780 cmp r0,#0 1781 bne common_updateProfile 1782 GET_INST_OPCODE(ip) @ extract opcode from rINST 1783 GOTO_OPCODE(ip) @ jump to next instruction 1784#else 1785 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1786 GET_INST_OPCODE(ip) @ extract opcode from rINST 1787 GOTO_OPCODE(ip) @ jump to next instruction 1788#endif 1789 1790 1791/* ------------------------------ */ 1792 .balign 64 1793.L_OP_IF_LTZ: /* 0x3a */ 1794/* File: armv5te/OP_IF_LTZ.S */ 1795/* File: armv5te/zcmp.S */ 1796 /* 1797 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1798 * fragment that specifies the *reverse* comparison to perform, e.g. 1799 * for "if-le" you would use "gt". 1800 * 1801 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1802 */ 1803 /* if-cmp vAA, +BBBB */ 1804 mov r0, rINST, lsr #8 @ r0<- AA 1805 GET_VREG(r2, r0) @ r2<- vAA 1806 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1807 cmp r2, #0 @ compare (vA, 0) 1808 bge 1f @ branch to 1 if comparison failed 1809 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1810 movs r9, r9, asl #1 @ convert to bytes, check sign 1811 bmi common_backwardBranch @ backward branch, do periodic checks 18121: 1813#if defined(WITH_JIT) 1814 GET_JIT_PROF_TABLE(r0) 1815 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1816 cmp r0,#0 1817 bne common_updateProfile 1818 GET_INST_OPCODE(ip) @ extract opcode from rINST 1819 GOTO_OPCODE(ip) @ jump to next instruction 1820#else 1821 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1822 GET_INST_OPCODE(ip) @ extract opcode from rINST 1823 GOTO_OPCODE(ip) @ jump to next instruction 1824#endif 1825 1826 1827/* ------------------------------ */ 1828 .balign 64 1829.L_OP_IF_GEZ: /* 0x3b */ 1830/* File: armv5te/OP_IF_GEZ.S */ 1831/* File: armv5te/zcmp.S */ 1832 /* 1833 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1834 * fragment that specifies the *reverse* comparison to perform, e.g. 1835 * for "if-le" you would use "gt". 1836 * 1837 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1838 */ 1839 /* if-cmp vAA, +BBBB */ 1840 mov r0, rINST, lsr #8 @ r0<- AA 1841 GET_VREG(r2, r0) @ r2<- vAA 1842 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1843 cmp r2, #0 @ compare (vA, 0) 1844 blt 1f @ branch to 1 if comparison failed 1845 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1846 movs r9, r9, asl #1 @ convert to bytes, check sign 1847 bmi common_backwardBranch @ backward branch, do periodic checks 18481: 1849#if defined(WITH_JIT) 1850 GET_JIT_PROF_TABLE(r0) 1851 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1852 cmp r0,#0 1853 bne common_updateProfile 1854 GET_INST_OPCODE(ip) @ extract opcode from rINST 1855 GOTO_OPCODE(ip) @ jump to next instruction 1856#else 1857 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1858 GET_INST_OPCODE(ip) @ extract opcode from rINST 1859 GOTO_OPCODE(ip) @ jump to next instruction 1860#endif 1861 1862 1863/* ------------------------------ */ 1864 .balign 64 1865.L_OP_IF_GTZ: /* 0x3c */ 1866/* File: armv5te/OP_IF_GTZ.S */ 1867/* File: armv5te/zcmp.S */ 1868 /* 1869 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1870 * fragment that specifies the *reverse* comparison to perform, e.g. 1871 * for "if-le" you would use "gt". 1872 * 1873 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1874 */ 1875 /* if-cmp vAA, +BBBB */ 1876 mov r0, rINST, lsr #8 @ r0<- AA 1877 GET_VREG(r2, r0) @ r2<- vAA 1878 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1879 cmp r2, #0 @ compare (vA, 0) 1880 ble 1f @ branch to 1 if comparison failed 1881 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1882 movs r9, r9, asl #1 @ convert to bytes, check sign 1883 bmi common_backwardBranch @ backward branch, do periodic checks 18841: 1885#if defined(WITH_JIT) 1886 GET_JIT_PROF_TABLE(r0) 1887 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1888 cmp r0,#0 1889 bne common_updateProfile 1890 GET_INST_OPCODE(ip) @ extract opcode from rINST 1891 GOTO_OPCODE(ip) @ jump to next instruction 1892#else 1893 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1894 GET_INST_OPCODE(ip) @ extract opcode from rINST 1895 GOTO_OPCODE(ip) @ jump to next instruction 1896#endif 1897 1898 1899/* ------------------------------ */ 1900 .balign 64 1901.L_OP_IF_LEZ: /* 0x3d */ 1902/* File: armv5te/OP_IF_LEZ.S */ 1903/* File: armv5te/zcmp.S */ 1904 /* 1905 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1906 * fragment that specifies the *reverse* comparison to perform, e.g. 1907 * for "if-le" you would use "gt". 1908 * 1909 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1910 */ 1911 /* if-cmp vAA, +BBBB */ 1912 mov r0, rINST, lsr #8 @ r0<- AA 1913 GET_VREG(r2, r0) @ r2<- vAA 1914 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1915 cmp r2, #0 @ compare (vA, 0) 1916 bgt 1f @ branch to 1 if comparison failed 1917 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1918 movs r9, r9, asl #1 @ convert to bytes, check sign 1919 bmi common_backwardBranch @ backward branch, do periodic checks 19201: 1921#if defined(WITH_JIT) 1922 GET_JIT_PROF_TABLE(r0) 1923 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1924 cmp r0,#0 1925 bne common_updateProfile 1926 GET_INST_OPCODE(ip) @ extract opcode from rINST 1927 GOTO_OPCODE(ip) @ jump to next instruction 1928#else 1929 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1930 GET_INST_OPCODE(ip) @ extract opcode from rINST 1931 GOTO_OPCODE(ip) @ jump to next instruction 1932#endif 1933 1934 1935/* ------------------------------ */ 1936 .balign 64 1937.L_OP_UNUSED_3E: /* 0x3e */ 1938/* File: armv5te/OP_UNUSED_3E.S */ 1939/* File: armv5te/unused.S */ 1940 bl common_abort 1941 1942 1943/* ------------------------------ */ 1944 .balign 64 1945.L_OP_UNUSED_3F: /* 0x3f */ 1946/* File: armv5te/OP_UNUSED_3F.S */ 1947/* File: armv5te/unused.S */ 1948 bl common_abort 1949 1950 1951/* ------------------------------ */ 1952 .balign 64 1953.L_OP_UNUSED_40: /* 0x40 */ 1954/* File: armv5te/OP_UNUSED_40.S */ 1955/* File: armv5te/unused.S */ 1956 bl common_abort 1957 1958 1959/* ------------------------------ */ 1960 .balign 64 1961.L_OP_UNUSED_41: /* 0x41 */ 1962/* File: armv5te/OP_UNUSED_41.S */ 1963/* File: armv5te/unused.S */ 1964 bl common_abort 1965 1966 1967/* ------------------------------ */ 1968 .balign 64 1969.L_OP_UNUSED_42: /* 0x42 */ 1970/* File: armv5te/OP_UNUSED_42.S */ 1971/* File: armv5te/unused.S */ 1972 bl common_abort 1973 1974 1975/* ------------------------------ */ 1976 .balign 64 1977.L_OP_UNUSED_43: /* 0x43 */ 1978/* File: armv5te/OP_UNUSED_43.S */ 1979/* File: armv5te/unused.S */ 1980 bl common_abort 1981 1982 1983/* ------------------------------ */ 1984 .balign 64 1985.L_OP_AGET: /* 0x44 */ 1986/* File: armv5te/OP_AGET.S */ 1987 /* 1988 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1989 * 1990 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1991 * instructions. We use a pair of FETCH_Bs instead. 1992 * 1993 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1994 */ 1995 /* op vAA, vBB, vCC */ 1996 FETCH_B(r2, 1, 0) @ r2<- BB 1997 mov r9, rINST, lsr #8 @ r9<- AA 1998 FETCH_B(r3, 1, 1) @ r3<- CC 1999 GET_VREG(r0, r2) @ r0<- vBB (array object) 2000 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2001 cmp r0, #0 @ null array object? 2002 beq common_errNullObject @ yes, bail 2003 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2004 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2005 cmp r1, r3 @ compare unsigned index, length 2006 bcs common_errArrayIndex @ index >= length, bail 2007 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2008 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2009 GET_INST_OPCODE(ip) @ extract opcode from rINST 2010 SET_VREG(r2, r9) @ vAA<- r2 2011 GOTO_OPCODE(ip) @ jump to next instruction 2012 2013/* ------------------------------ */ 2014 .balign 64 2015.L_OP_AGET_WIDE: /* 0x45 */ 2016/* File: armv5te/OP_AGET_WIDE.S */ 2017 /* 2018 * Array get, 64 bits. vAA <- vBB[vCC]. 2019 * 2020 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 2021 */ 2022 /* aget-wide vAA, vBB, vCC */ 2023 FETCH(r0, 1) @ r0<- CCBB 2024 mov r9, rINST, lsr #8 @ r9<- AA 2025 and r2, r0, #255 @ r2<- BB 2026 mov r3, r0, lsr #8 @ r3<- CC 2027 GET_VREG(r0, r2) @ r0<- vBB (array object) 2028 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2029 cmp r0, #0 @ null array object? 2030 beq common_errNullObject @ yes, bail 2031 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2032 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2033 cmp r1, r3 @ compare unsigned index, length 2034 bcc .LOP_AGET_WIDE_finish @ okay, continue below 2035 b common_errArrayIndex @ index >= length, bail 2036 @ May want to swap the order of these two branches depending on how the 2037 @ branch prediction (if any) handles conditional forward branches vs. 2038 @ unconditional forward branches. 2039 2040/* ------------------------------ */ 2041 .balign 64 2042.L_OP_AGET_OBJECT: /* 0x46 */ 2043/* File: armv5te/OP_AGET_OBJECT.S */ 2044/* File: armv5te/OP_AGET.S */ 2045 /* 2046 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2047 * 2048 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2049 * instructions. We use a pair of FETCH_Bs instead. 2050 * 2051 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2052 */ 2053 /* op vAA, vBB, vCC */ 2054 FETCH_B(r2, 1, 0) @ r2<- BB 2055 mov r9, rINST, lsr #8 @ r9<- AA 2056 FETCH_B(r3, 1, 1) @ r3<- CC 2057 GET_VREG(r0, r2) @ r0<- vBB (array object) 2058 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2059 cmp r0, #0 @ null array object? 2060 beq common_errNullObject @ yes, bail 2061 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2062 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2063 cmp r1, r3 @ compare unsigned index, length 2064 bcs common_errArrayIndex @ index >= length, bail 2065 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2066 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2067 GET_INST_OPCODE(ip) @ extract opcode from rINST 2068 SET_VREG(r2, r9) @ vAA<- r2 2069 GOTO_OPCODE(ip) @ jump to next instruction 2070 2071 2072/* ------------------------------ */ 2073 .balign 64 2074.L_OP_AGET_BOOLEAN: /* 0x47 */ 2075/* File: armv5te/OP_AGET_BOOLEAN.S */ 2076/* File: armv5te/OP_AGET.S */ 2077 /* 2078 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2079 * 2080 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2081 * instructions. We use a pair of FETCH_Bs instead. 2082 * 2083 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2084 */ 2085 /* op vAA, vBB, vCC */ 2086 FETCH_B(r2, 1, 0) @ r2<- BB 2087 mov r9, rINST, lsr #8 @ r9<- AA 2088 FETCH_B(r3, 1, 1) @ r3<- CC 2089 GET_VREG(r0, r2) @ r0<- vBB (array object) 2090 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2091 cmp r0, #0 @ null array object? 2092 beq common_errNullObject @ yes, bail 2093 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2094 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2095 cmp r1, r3 @ compare unsigned index, length 2096 bcs common_errArrayIndex @ index >= length, bail 2097 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2098 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2099 GET_INST_OPCODE(ip) @ extract opcode from rINST 2100 SET_VREG(r2, r9) @ vAA<- r2 2101 GOTO_OPCODE(ip) @ jump to next instruction 2102 2103 2104/* ------------------------------ */ 2105 .balign 64 2106.L_OP_AGET_BYTE: /* 0x48 */ 2107/* File: armv5te/OP_AGET_BYTE.S */ 2108/* File: armv5te/OP_AGET.S */ 2109 /* 2110 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2111 * 2112 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2113 * instructions. We use a pair of FETCH_Bs instead. 2114 * 2115 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2116 */ 2117 /* op vAA, vBB, vCC */ 2118 FETCH_B(r2, 1, 0) @ r2<- BB 2119 mov r9, rINST, lsr #8 @ r9<- AA 2120 FETCH_B(r3, 1, 1) @ r3<- CC 2121 GET_VREG(r0, r2) @ r0<- vBB (array object) 2122 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2123 cmp r0, #0 @ null array object? 2124 beq common_errNullObject @ yes, bail 2125 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2126 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2127 cmp r1, r3 @ compare unsigned index, length 2128 bcs common_errArrayIndex @ index >= length, bail 2129 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2130 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2131 GET_INST_OPCODE(ip) @ extract opcode from rINST 2132 SET_VREG(r2, r9) @ vAA<- r2 2133 GOTO_OPCODE(ip) @ jump to next instruction 2134 2135 2136/* ------------------------------ */ 2137 .balign 64 2138.L_OP_AGET_CHAR: /* 0x49 */ 2139/* File: armv5te/OP_AGET_CHAR.S */ 2140/* File: armv5te/OP_AGET.S */ 2141 /* 2142 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2143 * 2144 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2145 * instructions. We use a pair of FETCH_Bs instead. 2146 * 2147 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2148 */ 2149 /* op vAA, vBB, vCC */ 2150 FETCH_B(r2, 1, 0) @ r2<- BB 2151 mov r9, rINST, lsr #8 @ r9<- AA 2152 FETCH_B(r3, 1, 1) @ r3<- CC 2153 GET_VREG(r0, r2) @ r0<- vBB (array object) 2154 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2155 cmp r0, #0 @ null array object? 2156 beq common_errNullObject @ yes, bail 2157 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2158 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2159 cmp r1, r3 @ compare unsigned index, length 2160 bcs common_errArrayIndex @ index >= length, bail 2161 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2162 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2163 GET_INST_OPCODE(ip) @ extract opcode from rINST 2164 SET_VREG(r2, r9) @ vAA<- r2 2165 GOTO_OPCODE(ip) @ jump to next instruction 2166 2167 2168/* ------------------------------ */ 2169 .balign 64 2170.L_OP_AGET_SHORT: /* 0x4a */ 2171/* File: armv5te/OP_AGET_SHORT.S */ 2172/* File: armv5te/OP_AGET.S */ 2173 /* 2174 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2175 * 2176 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2177 * instructions. We use a pair of FETCH_Bs instead. 2178 * 2179 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2180 */ 2181 /* op vAA, vBB, vCC */ 2182 FETCH_B(r2, 1, 0) @ r2<- BB 2183 mov r9, rINST, lsr #8 @ r9<- AA 2184 FETCH_B(r3, 1, 1) @ r3<- CC 2185 GET_VREG(r0, r2) @ r0<- vBB (array object) 2186 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2187 cmp r0, #0 @ null array object? 2188 beq common_errNullObject @ yes, bail 2189 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2190 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2191 cmp r1, r3 @ compare unsigned index, length 2192 bcs common_errArrayIndex @ index >= length, bail 2193 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2194 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2195 GET_INST_OPCODE(ip) @ extract opcode from rINST 2196 SET_VREG(r2, r9) @ vAA<- r2 2197 GOTO_OPCODE(ip) @ jump to next instruction 2198 2199 2200/* ------------------------------ */ 2201 .balign 64 2202.L_OP_APUT: /* 0x4b */ 2203/* File: armv5te/OP_APUT.S */ 2204 /* 2205 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2206 * 2207 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2208 * instructions. We use a pair of FETCH_Bs instead. 2209 * 2210 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2211 */ 2212 /* op vAA, vBB, vCC */ 2213 FETCH_B(r2, 1, 0) @ r2<- BB 2214 mov r9, rINST, lsr #8 @ r9<- AA 2215 FETCH_B(r3, 1, 1) @ r3<- CC 2216 GET_VREG(r0, r2) @ r0<- vBB (array object) 2217 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2218 cmp r0, #0 @ null array object? 2219 beq common_errNullObject @ yes, bail 2220 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2221 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2222 cmp r1, r3 @ compare unsigned index, length 2223 bcs common_errArrayIndex @ index >= length, bail 2224 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2225 GET_VREG(r2, r9) @ r2<- vAA 2226 GET_INST_OPCODE(ip) @ extract opcode from rINST 2227 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2228 GOTO_OPCODE(ip) @ jump to next instruction 2229 2230/* ------------------------------ */ 2231 .balign 64 2232.L_OP_APUT_WIDE: /* 0x4c */ 2233/* File: armv5te/OP_APUT_WIDE.S */ 2234 /* 2235 * Array put, 64 bits. vBB[vCC] <- vAA. 2236 * 2237 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 2238 */ 2239 /* aput-wide vAA, vBB, vCC */ 2240 FETCH(r0, 1) @ r0<- CCBB 2241 mov r9, rINST, lsr #8 @ r9<- AA 2242 and r2, r0, #255 @ r2<- BB 2243 mov r3, r0, lsr #8 @ r3<- CC 2244 GET_VREG(r0, r2) @ r0<- vBB (array object) 2245 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2246 cmp r0, #0 @ null array object? 2247 beq common_errNullObject @ yes, bail 2248 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2249 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2250 cmp r1, r3 @ compare unsigned index, length 2251 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2252 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2253 b common_errArrayIndex @ index >= length, bail 2254 @ May want to swap the order of these two branches depending on how the 2255 @ branch prediction (if any) handles conditional forward branches vs. 2256 @ unconditional forward branches. 2257 2258/* ------------------------------ */ 2259 .balign 64 2260.L_OP_APUT_OBJECT: /* 0x4d */ 2261/* File: armv5te/OP_APUT_OBJECT.S */ 2262 /* 2263 * Store an object into an array. vBB[vCC] <- vAA. 2264 * 2265 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2266 * instructions. We use a pair of FETCH_Bs instead. 2267 */ 2268 /* op vAA, vBB, vCC */ 2269 FETCH(r0, 1) @ r0<- CCBB 2270 mov r9, rINST, lsr #8 @ r9<- AA 2271 and r2, r0, #255 @ r2<- BB 2272 mov r3, r0, lsr #8 @ r3<- CC 2273 GET_VREG(rINST, r2) @ rINST<- vBB (array object) 2274 GET_VREG(r0, r3) @ r0<- vCC (requested index) 2275 cmp rINST, #0 @ null array object? 2276 GET_VREG(r9, r9) @ r9<- vAA 2277 beq common_errNullObject @ yes, bail 2278 ldr r3, [rINST, #offArrayObject_length] @ r3<- arrayObj->length 2279 add r10, rINST, r0, lsl #2 @ r10<- arrayObj + index*width 2280 cmp r0, r3 @ compare unsigned index, length 2281 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2282 b common_errArrayIndex @ index >= length, bail 2283 2284 2285/* ------------------------------ */ 2286 .balign 64 2287.L_OP_APUT_BOOLEAN: /* 0x4e */ 2288/* File: armv5te/OP_APUT_BOOLEAN.S */ 2289/* File: armv5te/OP_APUT.S */ 2290 /* 2291 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2292 * 2293 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2294 * instructions. We use a pair of FETCH_Bs instead. 2295 * 2296 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2297 */ 2298 /* op vAA, vBB, vCC */ 2299 FETCH_B(r2, 1, 0) @ r2<- BB 2300 mov r9, rINST, lsr #8 @ r9<- AA 2301 FETCH_B(r3, 1, 1) @ r3<- CC 2302 GET_VREG(r0, r2) @ r0<- vBB (array object) 2303 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2304 cmp r0, #0 @ null array object? 2305 beq common_errNullObject @ yes, bail 2306 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2307 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2308 cmp r1, r3 @ compare unsigned index, length 2309 bcs common_errArrayIndex @ index >= length, bail 2310 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2311 GET_VREG(r2, r9) @ r2<- vAA 2312 GET_INST_OPCODE(ip) @ extract opcode from rINST 2313 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2314 GOTO_OPCODE(ip) @ jump to next instruction 2315 2316 2317/* ------------------------------ */ 2318 .balign 64 2319.L_OP_APUT_BYTE: /* 0x4f */ 2320/* File: armv5te/OP_APUT_BYTE.S */ 2321/* File: armv5te/OP_APUT.S */ 2322 /* 2323 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2324 * 2325 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2326 * instructions. We use a pair of FETCH_Bs instead. 2327 * 2328 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2329 */ 2330 /* op vAA, vBB, vCC */ 2331 FETCH_B(r2, 1, 0) @ r2<- BB 2332 mov r9, rINST, lsr #8 @ r9<- AA 2333 FETCH_B(r3, 1, 1) @ r3<- CC 2334 GET_VREG(r0, r2) @ r0<- vBB (array object) 2335 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2336 cmp r0, #0 @ null array object? 2337 beq common_errNullObject @ yes, bail 2338 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2339 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2340 cmp r1, r3 @ compare unsigned index, length 2341 bcs common_errArrayIndex @ index >= length, bail 2342 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2343 GET_VREG(r2, r9) @ r2<- vAA 2344 GET_INST_OPCODE(ip) @ extract opcode from rINST 2345 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2346 GOTO_OPCODE(ip) @ jump to next instruction 2347 2348 2349/* ------------------------------ */ 2350 .balign 64 2351.L_OP_APUT_CHAR: /* 0x50 */ 2352/* File: armv5te/OP_APUT_CHAR.S */ 2353/* File: armv5te/OP_APUT.S */ 2354 /* 2355 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2356 * 2357 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2358 * instructions. We use a pair of FETCH_Bs instead. 2359 * 2360 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2361 */ 2362 /* op vAA, vBB, vCC */ 2363 FETCH_B(r2, 1, 0) @ r2<- BB 2364 mov r9, rINST, lsr #8 @ r9<- AA 2365 FETCH_B(r3, 1, 1) @ r3<- CC 2366 GET_VREG(r0, r2) @ r0<- vBB (array object) 2367 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2368 cmp r0, #0 @ null array object? 2369 beq common_errNullObject @ yes, bail 2370 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2371 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2372 cmp r1, r3 @ compare unsigned index, length 2373 bcs common_errArrayIndex @ index >= length, bail 2374 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2375 GET_VREG(r2, r9) @ r2<- vAA 2376 GET_INST_OPCODE(ip) @ extract opcode from rINST 2377 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2378 GOTO_OPCODE(ip) @ jump to next instruction 2379 2380 2381/* ------------------------------ */ 2382 .balign 64 2383.L_OP_APUT_SHORT: /* 0x51 */ 2384/* File: armv5te/OP_APUT_SHORT.S */ 2385/* File: armv5te/OP_APUT.S */ 2386 /* 2387 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2388 * 2389 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2390 * instructions. We use a pair of FETCH_Bs instead. 2391 * 2392 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2393 */ 2394 /* op vAA, vBB, vCC */ 2395 FETCH_B(r2, 1, 0) @ r2<- BB 2396 mov r9, rINST, lsr #8 @ r9<- AA 2397 FETCH_B(r3, 1, 1) @ r3<- CC 2398 GET_VREG(r0, r2) @ r0<- vBB (array object) 2399 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2400 cmp r0, #0 @ null array object? 2401 beq common_errNullObject @ yes, bail 2402 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2403 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2404 cmp r1, r3 @ compare unsigned index, length 2405 bcs common_errArrayIndex @ index >= length, bail 2406 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2407 GET_VREG(r2, r9) @ r2<- vAA 2408 GET_INST_OPCODE(ip) @ extract opcode from rINST 2409 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2410 GOTO_OPCODE(ip) @ jump to next instruction 2411 2412 2413/* ------------------------------ */ 2414 .balign 64 2415.L_OP_IGET: /* 0x52 */ 2416/* File: armv5te/OP_IGET.S */ 2417 /* 2418 * General 32-bit instance field get. 2419 * 2420 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2421 */ 2422 /* op vA, vB, field@CCCC */ 2423 mov r0, rINST, lsr #12 @ r0<- B 2424 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2425 FETCH(r1, 1) @ r1<- field ref CCCC 2426 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2427 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2428 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2429 cmp r0, #0 @ is resolved entry null? 2430 bne .LOP_IGET_finish @ no, already resolved 24318: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2432 EXPORT_PC() @ resolve() could throw 2433 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2434 bl dvmResolveInstField @ r0<- resolved InstField ptr 2435 cmp r0, #0 2436 bne .LOP_IGET_finish 2437 b common_exceptionThrown 2438 2439/* ------------------------------ */ 2440 .balign 64 2441.L_OP_IGET_WIDE: /* 0x53 */ 2442/* File: armv5te/OP_IGET_WIDE.S */ 2443 /* 2444 * Wide 32-bit instance field get. 2445 */ 2446 /* iget-wide vA, vB, field@CCCC */ 2447 mov r0, rINST, lsr #12 @ r0<- B 2448 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2449 FETCH(r1, 1) @ r1<- field ref CCCC 2450 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2451 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2452 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2453 cmp r0, #0 @ is resolved entry null? 2454 bne .LOP_IGET_WIDE_finish @ no, already resolved 24558: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2456 EXPORT_PC() @ resolve() could throw 2457 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2458 bl dvmResolveInstField @ r0<- resolved InstField ptr 2459 cmp r0, #0 2460 bne .LOP_IGET_WIDE_finish 2461 b common_exceptionThrown 2462 2463/* ------------------------------ */ 2464 .balign 64 2465.L_OP_IGET_OBJECT: /* 0x54 */ 2466/* File: armv5te/OP_IGET_OBJECT.S */ 2467/* File: armv5te/OP_IGET.S */ 2468 /* 2469 * General 32-bit instance field get. 2470 * 2471 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2472 */ 2473 /* op vA, vB, field@CCCC */ 2474 mov r0, rINST, lsr #12 @ r0<- B 2475 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2476 FETCH(r1, 1) @ r1<- field ref CCCC 2477 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2478 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2479 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2480 cmp r0, #0 @ is resolved entry null? 2481 bne .LOP_IGET_OBJECT_finish @ no, already resolved 24828: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2483 EXPORT_PC() @ resolve() could throw 2484 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2485 bl dvmResolveInstField @ r0<- resolved InstField ptr 2486 cmp r0, #0 2487 bne .LOP_IGET_OBJECT_finish 2488 b common_exceptionThrown 2489 2490 2491/* ------------------------------ */ 2492 .balign 64 2493.L_OP_IGET_BOOLEAN: /* 0x55 */ 2494/* File: armv5te/OP_IGET_BOOLEAN.S */ 2495@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2496/* File: armv5te/OP_IGET.S */ 2497 /* 2498 * General 32-bit instance field get. 2499 * 2500 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2501 */ 2502 /* op vA, vB, field@CCCC */ 2503 mov r0, rINST, lsr #12 @ r0<- B 2504 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2505 FETCH(r1, 1) @ r1<- field ref CCCC 2506 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2507 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2508 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2509 cmp r0, #0 @ is resolved entry null? 2510 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 25118: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2512 EXPORT_PC() @ resolve() could throw 2513 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2514 bl dvmResolveInstField @ r0<- resolved InstField ptr 2515 cmp r0, #0 2516 bne .LOP_IGET_BOOLEAN_finish 2517 b common_exceptionThrown 2518 2519 2520/* ------------------------------ */ 2521 .balign 64 2522.L_OP_IGET_BYTE: /* 0x56 */ 2523/* File: armv5te/OP_IGET_BYTE.S */ 2524@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2525/* File: armv5te/OP_IGET.S */ 2526 /* 2527 * General 32-bit instance field get. 2528 * 2529 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2530 */ 2531 /* op vA, vB, field@CCCC */ 2532 mov r0, rINST, lsr #12 @ r0<- B 2533 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2534 FETCH(r1, 1) @ r1<- field ref CCCC 2535 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2536 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2537 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2538 cmp r0, #0 @ is resolved entry null? 2539 bne .LOP_IGET_BYTE_finish @ no, already resolved 25408: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2541 EXPORT_PC() @ resolve() could throw 2542 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2543 bl dvmResolveInstField @ r0<- resolved InstField ptr 2544 cmp r0, #0 2545 bne .LOP_IGET_BYTE_finish 2546 b common_exceptionThrown 2547 2548 2549/* ------------------------------ */ 2550 .balign 64 2551.L_OP_IGET_CHAR: /* 0x57 */ 2552/* File: armv5te/OP_IGET_CHAR.S */ 2553@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2554/* File: armv5te/OP_IGET.S */ 2555 /* 2556 * General 32-bit instance field get. 2557 * 2558 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2559 */ 2560 /* op vA, vB, field@CCCC */ 2561 mov r0, rINST, lsr #12 @ r0<- B 2562 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2563 FETCH(r1, 1) @ r1<- field ref CCCC 2564 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2565 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2566 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2567 cmp r0, #0 @ is resolved entry null? 2568 bne .LOP_IGET_CHAR_finish @ no, already resolved 25698: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2570 EXPORT_PC() @ resolve() could throw 2571 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2572 bl dvmResolveInstField @ r0<- resolved InstField ptr 2573 cmp r0, #0 2574 bne .LOP_IGET_CHAR_finish 2575 b common_exceptionThrown 2576 2577 2578/* ------------------------------ */ 2579 .balign 64 2580.L_OP_IGET_SHORT: /* 0x58 */ 2581/* File: armv5te/OP_IGET_SHORT.S */ 2582@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2583/* File: armv5te/OP_IGET.S */ 2584 /* 2585 * General 32-bit instance field get. 2586 * 2587 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2588 */ 2589 /* op vA, vB, field@CCCC */ 2590 mov r0, rINST, lsr #12 @ r0<- B 2591 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2592 FETCH(r1, 1) @ r1<- field ref CCCC 2593 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2594 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2595 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2596 cmp r0, #0 @ is resolved entry null? 2597 bne .LOP_IGET_SHORT_finish @ no, already resolved 25988: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2599 EXPORT_PC() @ resolve() could throw 2600 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2601 bl dvmResolveInstField @ r0<- resolved InstField ptr 2602 cmp r0, #0 2603 bne .LOP_IGET_SHORT_finish 2604 b common_exceptionThrown 2605 2606 2607/* ------------------------------ */ 2608 .balign 64 2609.L_OP_IPUT: /* 0x59 */ 2610/* File: armv5te/OP_IPUT.S */ 2611 /* 2612 * General 32-bit instance field put. 2613 * 2614 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2615 */ 2616 /* op vA, vB, field@CCCC */ 2617 mov r0, rINST, lsr #12 @ r0<- B 2618 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2619 FETCH(r1, 1) @ r1<- field ref CCCC 2620 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2621 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2622 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2623 cmp r0, #0 @ is resolved entry null? 2624 bne .LOP_IPUT_finish @ no, already resolved 26258: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2626 EXPORT_PC() @ resolve() could throw 2627 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2628 bl dvmResolveInstField @ r0<- resolved InstField ptr 2629 cmp r0, #0 @ success? 2630 bne .LOP_IPUT_finish @ yes, finish up 2631 b common_exceptionThrown 2632 2633/* ------------------------------ */ 2634 .balign 64 2635.L_OP_IPUT_WIDE: /* 0x5a */ 2636/* File: armv5te/OP_IPUT_WIDE.S */ 2637 /* iput-wide vA, vB, field@CCCC */ 2638 mov r0, rINST, lsr #12 @ r0<- B 2639 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2640 FETCH(r1, 1) @ r1<- field ref CCCC 2641 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2642 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2643 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2644 cmp r0, #0 @ is resolved entry null? 2645 bne .LOP_IPUT_WIDE_finish @ no, already resolved 26468: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2647 EXPORT_PC() @ resolve() could throw 2648 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2649 bl dvmResolveInstField @ r0<- resolved InstField ptr 2650 cmp r0, #0 @ success? 2651 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2652 b common_exceptionThrown 2653 2654/* ------------------------------ */ 2655 .balign 64 2656.L_OP_IPUT_OBJECT: /* 0x5b */ 2657/* File: armv5te/OP_IPUT_OBJECT.S */ 2658 /* 2659 * 32-bit instance field put. 2660 * 2661 * for: iput-object, iput-object-volatile 2662 */ 2663 /* op vA, vB, field@CCCC */ 2664 mov r0, rINST, lsr #12 @ r0<- B 2665 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2666 FETCH(r1, 1) @ r1<- field ref CCCC 2667 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2668 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2669 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2670 cmp r0, #0 @ is resolved entry null? 2671 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 26728: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2673 EXPORT_PC() @ resolve() could throw 2674 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2675 bl dvmResolveInstField @ r0<- resolved InstField ptr 2676 cmp r0, #0 @ success? 2677 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2678 b common_exceptionThrown 2679 2680/* ------------------------------ */ 2681 .balign 64 2682.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2683/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2684@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2685/* File: armv5te/OP_IPUT.S */ 2686 /* 2687 * General 32-bit instance field put. 2688 * 2689 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2690 */ 2691 /* op vA, vB, field@CCCC */ 2692 mov r0, rINST, lsr #12 @ r0<- B 2693 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2694 FETCH(r1, 1) @ r1<- field ref CCCC 2695 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2696 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2697 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2698 cmp r0, #0 @ is resolved entry null? 2699 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 27008: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2701 EXPORT_PC() @ resolve() could throw 2702 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2703 bl dvmResolveInstField @ r0<- resolved InstField ptr 2704 cmp r0, #0 @ success? 2705 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2706 b common_exceptionThrown 2707 2708 2709/* ------------------------------ */ 2710 .balign 64 2711.L_OP_IPUT_BYTE: /* 0x5d */ 2712/* File: armv5te/OP_IPUT_BYTE.S */ 2713@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2714/* File: armv5te/OP_IPUT.S */ 2715 /* 2716 * General 32-bit instance field put. 2717 * 2718 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2719 */ 2720 /* op vA, vB, field@CCCC */ 2721 mov r0, rINST, lsr #12 @ r0<- B 2722 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2723 FETCH(r1, 1) @ r1<- field ref CCCC 2724 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2725 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2726 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2727 cmp r0, #0 @ is resolved entry null? 2728 bne .LOP_IPUT_BYTE_finish @ no, already resolved 27298: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2730 EXPORT_PC() @ resolve() could throw 2731 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2732 bl dvmResolveInstField @ r0<- resolved InstField ptr 2733 cmp r0, #0 @ success? 2734 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2735 b common_exceptionThrown 2736 2737 2738/* ------------------------------ */ 2739 .balign 64 2740.L_OP_IPUT_CHAR: /* 0x5e */ 2741/* File: armv5te/OP_IPUT_CHAR.S */ 2742@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2743/* File: armv5te/OP_IPUT.S */ 2744 /* 2745 * General 32-bit instance field put. 2746 * 2747 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2748 */ 2749 /* op vA, vB, field@CCCC */ 2750 mov r0, rINST, lsr #12 @ r0<- B 2751 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2752 FETCH(r1, 1) @ r1<- field ref CCCC 2753 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2754 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2755 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2756 cmp r0, #0 @ is resolved entry null? 2757 bne .LOP_IPUT_CHAR_finish @ no, already resolved 27588: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2759 EXPORT_PC() @ resolve() could throw 2760 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2761 bl dvmResolveInstField @ r0<- resolved InstField ptr 2762 cmp r0, #0 @ success? 2763 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2764 b common_exceptionThrown 2765 2766 2767/* ------------------------------ */ 2768 .balign 64 2769.L_OP_IPUT_SHORT: /* 0x5f */ 2770/* File: armv5te/OP_IPUT_SHORT.S */ 2771@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2772/* File: armv5te/OP_IPUT.S */ 2773 /* 2774 * General 32-bit instance field put. 2775 * 2776 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2777 */ 2778 /* op vA, vB, field@CCCC */ 2779 mov r0, rINST, lsr #12 @ r0<- B 2780 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2781 FETCH(r1, 1) @ r1<- field ref CCCC 2782 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2783 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2784 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2785 cmp r0, #0 @ is resolved entry null? 2786 bne .LOP_IPUT_SHORT_finish @ no, already resolved 27878: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2788 EXPORT_PC() @ resolve() could throw 2789 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2790 bl dvmResolveInstField @ r0<- resolved InstField ptr 2791 cmp r0, #0 @ success? 2792 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2793 b common_exceptionThrown 2794 2795 2796/* ------------------------------ */ 2797 .balign 64 2798.L_OP_SGET: /* 0x60 */ 2799/* File: armv5te/OP_SGET.S */ 2800 /* 2801 * General 32-bit SGET handler. 2802 * 2803 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2804 */ 2805 /* op vAA, field@BBBB */ 2806 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2807 FETCH(r1, 1) @ r1<- field ref BBBB 2808 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2809 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2810 cmp r0, #0 @ is resolved entry null? 2811 beq .LOP_SGET_resolve @ yes, do resolve 2812.LOP_SGET_finish: @ field ptr in r0 2813 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2814 @ no-op @ acquiring load 2815 mov r2, rINST, lsr #8 @ r2<- AA 2816 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2817 SET_VREG(r1, r2) @ fp[AA]<- r1 2818 GET_INST_OPCODE(ip) @ extract opcode from rINST 2819 GOTO_OPCODE(ip) @ jump to next instruction 2820 2821/* ------------------------------ */ 2822 .balign 64 2823.L_OP_SGET_WIDE: /* 0x61 */ 2824/* File: armv5te/OP_SGET_WIDE.S */ 2825 /* 2826 * 64-bit SGET handler. 2827 */ 2828 /* sget-wide vAA, field@BBBB */ 2829 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2830 FETCH(r1, 1) @ r1<- field ref BBBB 2831 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2832 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2833 cmp r0, #0 @ is resolved entry null? 2834 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2835.LOP_SGET_WIDE_finish: 2836 mov r9, rINST, lsr #8 @ r9<- AA 2837 .if 0 2838 add r0, r0, #offStaticField_value @ r0<- pointer to data 2839 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 2840 .else 2841 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 2842 .endif 2843 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2844 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2845 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 2846 GET_INST_OPCODE(ip) @ extract opcode from rINST 2847 GOTO_OPCODE(ip) @ jump to next instruction 2848 2849/* ------------------------------ */ 2850 .balign 64 2851.L_OP_SGET_OBJECT: /* 0x62 */ 2852/* File: armv5te/OP_SGET_OBJECT.S */ 2853/* File: armv5te/OP_SGET.S */ 2854 /* 2855 * General 32-bit SGET handler. 2856 * 2857 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2858 */ 2859 /* op vAA, field@BBBB */ 2860 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2861 FETCH(r1, 1) @ r1<- field ref BBBB 2862 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2863 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2864 cmp r0, #0 @ is resolved entry null? 2865 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2866.LOP_SGET_OBJECT_finish: @ field ptr in r0 2867 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2868 @ no-op @ acquiring load 2869 mov r2, rINST, lsr #8 @ r2<- AA 2870 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2871 SET_VREG(r1, r2) @ fp[AA]<- r1 2872 GET_INST_OPCODE(ip) @ extract opcode from rINST 2873 GOTO_OPCODE(ip) @ jump to next instruction 2874 2875 2876/* ------------------------------ */ 2877 .balign 64 2878.L_OP_SGET_BOOLEAN: /* 0x63 */ 2879/* File: armv5te/OP_SGET_BOOLEAN.S */ 2880/* File: armv5te/OP_SGET.S */ 2881 /* 2882 * General 32-bit SGET handler. 2883 * 2884 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2885 */ 2886 /* op vAA, field@BBBB */ 2887 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2888 FETCH(r1, 1) @ r1<- field ref BBBB 2889 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2890 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2891 cmp r0, #0 @ is resolved entry null? 2892 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2893.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2894 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2895 @ no-op @ acquiring load 2896 mov r2, rINST, lsr #8 @ r2<- AA 2897 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2898 SET_VREG(r1, r2) @ fp[AA]<- r1 2899 GET_INST_OPCODE(ip) @ extract opcode from rINST 2900 GOTO_OPCODE(ip) @ jump to next instruction 2901 2902 2903/* ------------------------------ */ 2904 .balign 64 2905.L_OP_SGET_BYTE: /* 0x64 */ 2906/* File: armv5te/OP_SGET_BYTE.S */ 2907/* File: armv5te/OP_SGET.S */ 2908 /* 2909 * General 32-bit SGET handler. 2910 * 2911 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2912 */ 2913 /* op vAA, field@BBBB */ 2914 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2915 FETCH(r1, 1) @ r1<- field ref BBBB 2916 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2917 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2918 cmp r0, #0 @ is resolved entry null? 2919 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2920.LOP_SGET_BYTE_finish: @ field ptr in r0 2921 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2922 @ no-op @ acquiring load 2923 mov r2, rINST, lsr #8 @ r2<- AA 2924 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2925 SET_VREG(r1, r2) @ fp[AA]<- r1 2926 GET_INST_OPCODE(ip) @ extract opcode from rINST 2927 GOTO_OPCODE(ip) @ jump to next instruction 2928 2929 2930/* ------------------------------ */ 2931 .balign 64 2932.L_OP_SGET_CHAR: /* 0x65 */ 2933/* File: armv5te/OP_SGET_CHAR.S */ 2934/* File: armv5te/OP_SGET.S */ 2935 /* 2936 * General 32-bit SGET handler. 2937 * 2938 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2939 */ 2940 /* op vAA, field@BBBB */ 2941 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2942 FETCH(r1, 1) @ r1<- field ref BBBB 2943 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2944 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2945 cmp r0, #0 @ is resolved entry null? 2946 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2947.LOP_SGET_CHAR_finish: @ field ptr in r0 2948 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2949 @ no-op @ acquiring load 2950 mov r2, rINST, lsr #8 @ r2<- AA 2951 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2952 SET_VREG(r1, r2) @ fp[AA]<- r1 2953 GET_INST_OPCODE(ip) @ extract opcode from rINST 2954 GOTO_OPCODE(ip) @ jump to next instruction 2955 2956 2957/* ------------------------------ */ 2958 .balign 64 2959.L_OP_SGET_SHORT: /* 0x66 */ 2960/* File: armv5te/OP_SGET_SHORT.S */ 2961/* File: armv5te/OP_SGET.S */ 2962 /* 2963 * General 32-bit SGET handler. 2964 * 2965 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2966 */ 2967 /* op vAA, field@BBBB */ 2968 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2969 FETCH(r1, 1) @ r1<- field ref BBBB 2970 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2971 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2972 cmp r0, #0 @ is resolved entry null? 2973 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 2974.LOP_SGET_SHORT_finish: @ field ptr in r0 2975 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2976 @ no-op @ acquiring load 2977 mov r2, rINST, lsr #8 @ r2<- AA 2978 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2979 SET_VREG(r1, r2) @ fp[AA]<- r1 2980 GET_INST_OPCODE(ip) @ extract opcode from rINST 2981 GOTO_OPCODE(ip) @ jump to next instruction 2982 2983 2984/* ------------------------------ */ 2985 .balign 64 2986.L_OP_SPUT: /* 0x67 */ 2987/* File: armv5te/OP_SPUT.S */ 2988 /* 2989 * General 32-bit SPUT handler. 2990 * 2991 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 2992 */ 2993 /* op vAA, field@BBBB */ 2994 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2995 FETCH(r1, 1) @ r1<- field ref BBBB 2996 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2997 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2998 cmp r0, #0 @ is resolved entry null? 2999 beq .LOP_SPUT_resolve @ yes, do resolve 3000.LOP_SPUT_finish: @ field ptr in r0 3001 mov r2, rINST, lsr #8 @ r2<- AA 3002 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3003 GET_VREG(r1, r2) @ r1<- fp[AA] 3004 GET_INST_OPCODE(ip) @ extract opcode from rINST 3005 @ no-op @ releasing store 3006 str r1, [r0, #offStaticField_value] @ field<- vAA 3007 GOTO_OPCODE(ip) @ jump to next instruction 3008 3009/* ------------------------------ */ 3010 .balign 64 3011.L_OP_SPUT_WIDE: /* 0x68 */ 3012/* File: armv5te/OP_SPUT_WIDE.S */ 3013 /* 3014 * 64-bit SPUT handler. 3015 */ 3016 /* sput-wide vAA, field@BBBB */ 3017 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 3018 FETCH(r1, 1) @ r1<- field ref BBBB 3019 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 3020 mov r9, rINST, lsr #8 @ r9<- AA 3021 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 3022 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 3023 cmp r2, #0 @ is resolved entry null? 3024 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 3025.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9 3026 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3027 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 3028 GET_INST_OPCODE(r10) @ extract opcode from rINST 3029 .if 0 3030 add r2, r2, #offStaticField_value @ r2<- pointer to data 3031 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 3032 .else 3033 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 3034 .endif 3035 GOTO_OPCODE(r10) @ jump to next instruction 3036 3037/* ------------------------------ */ 3038 .balign 64 3039.L_OP_SPUT_OBJECT: /* 0x69 */ 3040/* File: armv5te/OP_SPUT_OBJECT.S */ 3041 /* 3042 * 32-bit SPUT handler for objects 3043 * 3044 * for: sput-object, sput-object-volatile 3045 */ 3046 /* op vAA, field@BBBB */ 3047 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3048 FETCH(r1, 1) @ r1<- field ref BBBB 3049 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3050 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3051 cmp r0, #0 @ is resolved entry null? 3052 bne .LOP_SPUT_OBJECT_finish @ no, continue 3053 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3054 EXPORT_PC() @ resolve() could throw, so export now 3055 ldr r0, [r9, #offMethod_clazz] @ r0<- method->clazz 3056 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 3057 cmp r0, #0 @ success? 3058 bne .LOP_SPUT_OBJECT_finish @ yes, finish 3059 b common_exceptionThrown @ no, handle exception 3060 3061 3062/* ------------------------------ */ 3063 .balign 64 3064.L_OP_SPUT_BOOLEAN: /* 0x6a */ 3065/* File: armv5te/OP_SPUT_BOOLEAN.S */ 3066/* File: armv5te/OP_SPUT.S */ 3067 /* 3068 * General 32-bit SPUT handler. 3069 * 3070 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3071 */ 3072 /* op vAA, field@BBBB */ 3073 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3074 FETCH(r1, 1) @ r1<- field ref BBBB 3075 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3076 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3077 cmp r0, #0 @ is resolved entry null? 3078 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 3079.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 3080 mov r2, rINST, lsr #8 @ r2<- AA 3081 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3082 GET_VREG(r1, r2) @ r1<- fp[AA] 3083 GET_INST_OPCODE(ip) @ extract opcode from rINST 3084 @ no-op @ releasing store 3085 str r1, [r0, #offStaticField_value] @ field<- vAA 3086 GOTO_OPCODE(ip) @ jump to next instruction 3087 3088 3089/* ------------------------------ */ 3090 .balign 64 3091.L_OP_SPUT_BYTE: /* 0x6b */ 3092/* File: armv5te/OP_SPUT_BYTE.S */ 3093/* File: armv5te/OP_SPUT.S */ 3094 /* 3095 * General 32-bit SPUT handler. 3096 * 3097 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3098 */ 3099 /* op vAA, field@BBBB */ 3100 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3101 FETCH(r1, 1) @ r1<- field ref BBBB 3102 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3103 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3104 cmp r0, #0 @ is resolved entry null? 3105 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 3106.LOP_SPUT_BYTE_finish: @ field ptr in r0 3107 mov r2, rINST, lsr #8 @ r2<- AA 3108 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3109 GET_VREG(r1, r2) @ r1<- fp[AA] 3110 GET_INST_OPCODE(ip) @ extract opcode from rINST 3111 @ no-op @ releasing store 3112 str r1, [r0, #offStaticField_value] @ field<- vAA 3113 GOTO_OPCODE(ip) @ jump to next instruction 3114 3115 3116/* ------------------------------ */ 3117 .balign 64 3118.L_OP_SPUT_CHAR: /* 0x6c */ 3119/* File: armv5te/OP_SPUT_CHAR.S */ 3120/* File: armv5te/OP_SPUT.S */ 3121 /* 3122 * General 32-bit SPUT handler. 3123 * 3124 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3125 */ 3126 /* op vAA, field@BBBB */ 3127 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3128 FETCH(r1, 1) @ r1<- field ref BBBB 3129 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3130 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3131 cmp r0, #0 @ is resolved entry null? 3132 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 3133.LOP_SPUT_CHAR_finish: @ field ptr in r0 3134 mov r2, rINST, lsr #8 @ r2<- AA 3135 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3136 GET_VREG(r1, r2) @ r1<- fp[AA] 3137 GET_INST_OPCODE(ip) @ extract opcode from rINST 3138 @ no-op @ releasing store 3139 str r1, [r0, #offStaticField_value] @ field<- vAA 3140 GOTO_OPCODE(ip) @ jump to next instruction 3141 3142 3143/* ------------------------------ */ 3144 .balign 64 3145.L_OP_SPUT_SHORT: /* 0x6d */ 3146/* File: armv5te/OP_SPUT_SHORT.S */ 3147/* File: armv5te/OP_SPUT.S */ 3148 /* 3149 * General 32-bit SPUT handler. 3150 * 3151 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3152 */ 3153 /* op vAA, field@BBBB */ 3154 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3155 FETCH(r1, 1) @ r1<- field ref BBBB 3156 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3157 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3158 cmp r0, #0 @ is resolved entry null? 3159 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 3160.LOP_SPUT_SHORT_finish: @ field ptr in r0 3161 mov r2, rINST, lsr #8 @ r2<- AA 3162 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3163 GET_VREG(r1, r2) @ r1<- fp[AA] 3164 GET_INST_OPCODE(ip) @ extract opcode from rINST 3165 @ no-op @ releasing store 3166 str r1, [r0, #offStaticField_value] @ field<- vAA 3167 GOTO_OPCODE(ip) @ jump to next instruction 3168 3169 3170/* ------------------------------ */ 3171 .balign 64 3172.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3173/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3174 /* 3175 * Handle a virtual method call. 3176 * 3177 * for: invoke-virtual, invoke-virtual/range 3178 */ 3179 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3180 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3181 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3182 FETCH(r1, 1) @ r1<- BBBB 3183 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3184 FETCH(r10, 2) @ r10<- GFED or CCCC 3185 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3186 .if (!0) 3187 and r10, r10, #15 @ r10<- D (or stays CCCC) 3188 .endif 3189 cmp r0, #0 @ already resolved? 3190 EXPORT_PC() @ must export for invoke 3191 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3192 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3193 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3194 mov r2, #METHOD_VIRTUAL @ resolver method type 3195 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3196 cmp r0, #0 @ got null? 3197 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3198 b common_exceptionThrown @ yes, handle exception 3199 3200/* ------------------------------ */ 3201 .balign 64 3202.L_OP_INVOKE_SUPER: /* 0x6f */ 3203/* File: armv5te/OP_INVOKE_SUPER.S */ 3204 /* 3205 * Handle a "super" method call. 3206 * 3207 * for: invoke-super, invoke-super/range 3208 */ 3209 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3210 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3211 FETCH(r10, 2) @ r10<- GFED or CCCC 3212 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3213 .if (!0) 3214 and r10, r10, #15 @ r10<- D (or stays CCCC) 3215 .endif 3216 FETCH(r1, 1) @ r1<- BBBB 3217 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3218 GET_VREG(r2, r10) @ r2<- "this" ptr 3219 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3220 cmp r2, #0 @ null "this"? 3221 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3222 beq common_errNullObject @ null "this", throw exception 3223 cmp r0, #0 @ already resolved? 3224 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3225 EXPORT_PC() @ must export for invoke 3226 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3227 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3228 3229/* ------------------------------ */ 3230 .balign 64 3231.L_OP_INVOKE_DIRECT: /* 0x70 */ 3232/* File: armv5te/OP_INVOKE_DIRECT.S */ 3233 /* 3234 * Handle a direct method call. 3235 * 3236 * (We could defer the "is 'this' pointer null" test to the common 3237 * method invocation code, and use a flag to indicate that static 3238 * calls don't count. If we do this as part of copying the arguments 3239 * out we could avoiding loading the first arg twice.) 3240 * 3241 * for: invoke-direct, invoke-direct/range 3242 */ 3243 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3244 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3245 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3246 FETCH(r1, 1) @ r1<- BBBB 3247 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3248 FETCH(r10, 2) @ r10<- GFED or CCCC 3249 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3250 .if (!0) 3251 and r10, r10, #15 @ r10<- D (or stays CCCC) 3252 .endif 3253 cmp r0, #0 @ already resolved? 3254 EXPORT_PC() @ must export for invoke 3255 GET_VREG(r2, r10) @ r2<- "this" ptr 3256 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3257.LOP_INVOKE_DIRECT_finish: 3258 cmp r2, #0 @ null "this" ref? 3259 bne common_invokeMethodNoRange @ no, continue on 3260 b common_errNullObject @ yes, throw exception 3261 3262/* ------------------------------ */ 3263 .balign 64 3264.L_OP_INVOKE_STATIC: /* 0x71 */ 3265/* File: armv5te/OP_INVOKE_STATIC.S */ 3266 /* 3267 * Handle a static method call. 3268 * 3269 * for: invoke-static, invoke-static/range 3270 */ 3271 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3272 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3273 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3274 FETCH(r1, 1) @ r1<- BBBB 3275 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3276 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3277 cmp r0, #0 @ already resolved? 3278 EXPORT_PC() @ must export for invoke 3279 bne common_invokeMethodNoRange @ yes, continue on 32800: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3281 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3282 mov r2, #METHOD_STATIC @ resolver method type 3283 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3284 cmp r0, #0 @ got null? 3285 bne common_invokeMethodNoRange @ no, continue 3286 b common_exceptionThrown @ yes, handle exception 3287 3288/* ------------------------------ */ 3289 .balign 64 3290.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3291/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3292 /* 3293 * Handle an interface method call. 3294 * 3295 * for: invoke-interface, invoke-interface/range 3296 */ 3297 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3298 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3299 FETCH(r2, 2) @ r2<- FEDC or CCCC 3300 FETCH(r1, 1) @ r1<- BBBB 3301 .if (!0) 3302 and r2, r2, #15 @ r2<- C (or stays CCCC) 3303 .endif 3304 EXPORT_PC() @ must export for invoke 3305 GET_VREG(r0, r2) @ r0<- first arg ("this") 3306 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3307 cmp r0, #0 @ null obj? 3308 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3309 beq common_errNullObject @ yes, fail 3310 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3311 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3312 cmp r0, #0 @ failed? 3313 beq common_exceptionThrown @ yes, handle exception 3314 b common_invokeMethodNoRange @ jump to common handler 3315 3316/* ------------------------------ */ 3317 .balign 64 3318.L_OP_UNUSED_73: /* 0x73 */ 3319/* File: armv5te/OP_UNUSED_73.S */ 3320/* File: armv5te/unused.S */ 3321 bl common_abort 3322 3323 3324/* ------------------------------ */ 3325 .balign 64 3326.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3327/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3328/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3329 /* 3330 * Handle a virtual method call. 3331 * 3332 * for: invoke-virtual, invoke-virtual/range 3333 */ 3334 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3335 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3336 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3337 FETCH(r1, 1) @ r1<- BBBB 3338 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3339 FETCH(r10, 2) @ r10<- GFED or CCCC 3340 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3341 .if (!1) 3342 and r10, r10, #15 @ r10<- D (or stays CCCC) 3343 .endif 3344 cmp r0, #0 @ already resolved? 3345 EXPORT_PC() @ must export for invoke 3346 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3347 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3348 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3349 mov r2, #METHOD_VIRTUAL @ resolver method type 3350 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3351 cmp r0, #0 @ got null? 3352 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3353 b common_exceptionThrown @ yes, handle exception 3354 3355 3356/* ------------------------------ */ 3357 .balign 64 3358.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3359/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3360/* File: armv5te/OP_INVOKE_SUPER.S */ 3361 /* 3362 * Handle a "super" method call. 3363 * 3364 * for: invoke-super, invoke-super/range 3365 */ 3366 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3367 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3368 FETCH(r10, 2) @ r10<- GFED or CCCC 3369 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3370 .if (!1) 3371 and r10, r10, #15 @ r10<- D (or stays CCCC) 3372 .endif 3373 FETCH(r1, 1) @ r1<- BBBB 3374 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3375 GET_VREG(r2, r10) @ r2<- "this" ptr 3376 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3377 cmp r2, #0 @ null "this"? 3378 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3379 beq common_errNullObject @ null "this", throw exception 3380 cmp r0, #0 @ already resolved? 3381 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3382 EXPORT_PC() @ must export for invoke 3383 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3384 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3385 3386 3387/* ------------------------------ */ 3388 .balign 64 3389.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3390/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3391/* File: armv5te/OP_INVOKE_DIRECT.S */ 3392 /* 3393 * Handle a direct method call. 3394 * 3395 * (We could defer the "is 'this' pointer null" test to the common 3396 * method invocation code, and use a flag to indicate that static 3397 * calls don't count. If we do this as part of copying the arguments 3398 * out we could avoiding loading the first arg twice.) 3399 * 3400 * for: invoke-direct, invoke-direct/range 3401 */ 3402 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3403 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3404 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3405 FETCH(r1, 1) @ r1<- BBBB 3406 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3407 FETCH(r10, 2) @ r10<- GFED or CCCC 3408 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3409 .if (!1) 3410 and r10, r10, #15 @ r10<- D (or stays CCCC) 3411 .endif 3412 cmp r0, #0 @ already resolved? 3413 EXPORT_PC() @ must export for invoke 3414 GET_VREG(r2, r10) @ r2<- "this" ptr 3415 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3416.LOP_INVOKE_DIRECT_RANGE_finish: 3417 cmp r2, #0 @ null "this" ref? 3418 bne common_invokeMethodRange @ no, continue on 3419 b common_errNullObject @ yes, throw exception 3420 3421 3422/* ------------------------------ */ 3423 .balign 64 3424.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3425/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3426/* File: armv5te/OP_INVOKE_STATIC.S */ 3427 /* 3428 * Handle a static method call. 3429 * 3430 * for: invoke-static, invoke-static/range 3431 */ 3432 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3433 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3434 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3435 FETCH(r1, 1) @ r1<- BBBB 3436 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3437 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3438 cmp r0, #0 @ already resolved? 3439 EXPORT_PC() @ must export for invoke 3440 bne common_invokeMethodRange @ yes, continue on 34410: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3442 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3443 mov r2, #METHOD_STATIC @ resolver method type 3444 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3445 cmp r0, #0 @ got null? 3446 bne common_invokeMethodRange @ no, continue 3447 b common_exceptionThrown @ yes, handle exception 3448 3449 3450/* ------------------------------ */ 3451 .balign 64 3452.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3453/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3454/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3455 /* 3456 * Handle an interface method call. 3457 * 3458 * for: invoke-interface, invoke-interface/range 3459 */ 3460 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3461 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3462 FETCH(r2, 2) @ r2<- FEDC or CCCC 3463 FETCH(r1, 1) @ r1<- BBBB 3464 .if (!1) 3465 and r2, r2, #15 @ r2<- C (or stays CCCC) 3466 .endif 3467 EXPORT_PC() @ must export for invoke 3468 GET_VREG(r0, r2) @ r0<- first arg ("this") 3469 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3470 cmp r0, #0 @ null obj? 3471 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3472 beq common_errNullObject @ yes, fail 3473 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3474 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3475 cmp r0, #0 @ failed? 3476 beq common_exceptionThrown @ yes, handle exception 3477 b common_invokeMethodRange @ jump to common handler 3478 3479 3480/* ------------------------------ */ 3481 .balign 64 3482.L_OP_UNUSED_79: /* 0x79 */ 3483/* File: armv5te/OP_UNUSED_79.S */ 3484/* File: armv5te/unused.S */ 3485 bl common_abort 3486 3487 3488/* ------------------------------ */ 3489 .balign 64 3490.L_OP_UNUSED_7A: /* 0x7a */ 3491/* File: armv5te/OP_UNUSED_7A.S */ 3492/* File: armv5te/unused.S */ 3493 bl common_abort 3494 3495 3496/* ------------------------------ */ 3497 .balign 64 3498.L_OP_NEG_INT: /* 0x7b */ 3499/* File: armv5te/OP_NEG_INT.S */ 3500/* File: armv5te/unop.S */ 3501 /* 3502 * Generic 32-bit unary operation. Provide an "instr" line that 3503 * specifies an instruction that performs "result = op r0". 3504 * This could be an ARM instruction or a function call. 3505 * 3506 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3507 * int-to-byte, int-to-char, int-to-short 3508 */ 3509 /* unop vA, vB */ 3510 mov r3, rINST, lsr #12 @ r3<- B 3511 mov r9, rINST, lsr #8 @ r9<- A+ 3512 GET_VREG(r0, r3) @ r0<- vB 3513 and r9, r9, #15 3514 @ optional op; may set condition codes 3515 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3516 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3517 GET_INST_OPCODE(ip) @ extract opcode from rINST 3518 SET_VREG(r0, r9) @ vAA<- r0 3519 GOTO_OPCODE(ip) @ jump to next instruction 3520 /* 9-10 instructions */ 3521 3522 3523/* ------------------------------ */ 3524 .balign 64 3525.L_OP_NOT_INT: /* 0x7c */ 3526/* File: armv5te/OP_NOT_INT.S */ 3527/* File: armv5te/unop.S */ 3528 /* 3529 * Generic 32-bit unary operation. Provide an "instr" line that 3530 * specifies an instruction that performs "result = op r0". 3531 * This could be an ARM instruction or a function call. 3532 * 3533 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3534 * int-to-byte, int-to-char, int-to-short 3535 */ 3536 /* unop vA, vB */ 3537 mov r3, rINST, lsr #12 @ r3<- B 3538 mov r9, rINST, lsr #8 @ r9<- A+ 3539 GET_VREG(r0, r3) @ r0<- vB 3540 and r9, r9, #15 3541 @ optional op; may set condition codes 3542 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3543 mvn r0, r0 @ r0<- op, r0-r3 changed 3544 GET_INST_OPCODE(ip) @ extract opcode from rINST 3545 SET_VREG(r0, r9) @ vAA<- r0 3546 GOTO_OPCODE(ip) @ jump to next instruction 3547 /* 9-10 instructions */ 3548 3549 3550/* ------------------------------ */ 3551 .balign 64 3552.L_OP_NEG_LONG: /* 0x7d */ 3553/* File: armv5te/OP_NEG_LONG.S */ 3554/* File: armv5te/unopWide.S */ 3555 /* 3556 * Generic 64-bit unary operation. Provide an "instr" line that 3557 * specifies an instruction that performs "result = op r0/r1". 3558 * This could be an ARM instruction or a function call. 3559 * 3560 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3561 */ 3562 /* unop vA, vB */ 3563 mov r9, rINST, lsr #8 @ r9<- A+ 3564 mov r3, rINST, lsr #12 @ r3<- B 3565 and r9, r9, #15 3566 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3567 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3568 ldmia r3, {r0-r1} @ r0/r1<- vAA 3569 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3570 rsbs r0, r0, #0 @ optional op; may set condition codes 3571 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3572 GET_INST_OPCODE(ip) @ extract opcode from rINST 3573 stmia r9, {r0-r1} @ vAA<- r0/r1 3574 GOTO_OPCODE(ip) @ jump to next instruction 3575 /* 12-13 instructions */ 3576 3577 3578/* ------------------------------ */ 3579 .balign 64 3580.L_OP_NOT_LONG: /* 0x7e */ 3581/* File: armv5te/OP_NOT_LONG.S */ 3582/* File: armv5te/unopWide.S */ 3583 /* 3584 * Generic 64-bit unary operation. Provide an "instr" line that 3585 * specifies an instruction that performs "result = op r0/r1". 3586 * This could be an ARM instruction or a function call. 3587 * 3588 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3589 */ 3590 /* unop vA, vB */ 3591 mov r9, rINST, lsr #8 @ r9<- A+ 3592 mov r3, rINST, lsr #12 @ r3<- B 3593 and r9, r9, #15 3594 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3595 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3596 ldmia r3, {r0-r1} @ r0/r1<- vAA 3597 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3598 mvn r0, r0 @ optional op; may set condition codes 3599 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3600 GET_INST_OPCODE(ip) @ extract opcode from rINST 3601 stmia r9, {r0-r1} @ vAA<- r0/r1 3602 GOTO_OPCODE(ip) @ jump to next instruction 3603 /* 12-13 instructions */ 3604 3605 3606/* ------------------------------ */ 3607 .balign 64 3608.L_OP_NEG_FLOAT: /* 0x7f */ 3609/* File: armv5te/OP_NEG_FLOAT.S */ 3610/* File: armv5te/unop.S */ 3611 /* 3612 * Generic 32-bit unary operation. Provide an "instr" line that 3613 * specifies an instruction that performs "result = op r0". 3614 * This could be an ARM instruction or a function call. 3615 * 3616 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3617 * int-to-byte, int-to-char, int-to-short 3618 */ 3619 /* unop vA, vB */ 3620 mov r3, rINST, lsr #12 @ r3<- B 3621 mov r9, rINST, lsr #8 @ r9<- A+ 3622 GET_VREG(r0, r3) @ r0<- vB 3623 and r9, r9, #15 3624 @ optional op; may set condition codes 3625 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3626 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3627 GET_INST_OPCODE(ip) @ extract opcode from rINST 3628 SET_VREG(r0, r9) @ vAA<- r0 3629 GOTO_OPCODE(ip) @ jump to next instruction 3630 /* 9-10 instructions */ 3631 3632 3633/* ------------------------------ */ 3634 .balign 64 3635.L_OP_NEG_DOUBLE: /* 0x80 */ 3636/* File: armv5te/OP_NEG_DOUBLE.S */ 3637/* File: armv5te/unopWide.S */ 3638 /* 3639 * Generic 64-bit unary operation. Provide an "instr" line that 3640 * specifies an instruction that performs "result = op r0/r1". 3641 * This could be an ARM instruction or a function call. 3642 * 3643 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3644 */ 3645 /* unop vA, vB */ 3646 mov r9, rINST, lsr #8 @ r9<- A+ 3647 mov r3, rINST, lsr #12 @ r3<- B 3648 and r9, r9, #15 3649 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3650 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3651 ldmia r3, {r0-r1} @ r0/r1<- vAA 3652 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3653 @ optional op; may set condition codes 3654 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3655 GET_INST_OPCODE(ip) @ extract opcode from rINST 3656 stmia r9, {r0-r1} @ vAA<- r0/r1 3657 GOTO_OPCODE(ip) @ jump to next instruction 3658 /* 12-13 instructions */ 3659 3660 3661/* ------------------------------ */ 3662 .balign 64 3663.L_OP_INT_TO_LONG: /* 0x81 */ 3664/* File: armv5te/OP_INT_TO_LONG.S */ 3665/* File: armv5te/unopWider.S */ 3666 /* 3667 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3668 * that specifies an instruction that performs "result = op r0", where 3669 * "result" is a 64-bit quantity in r0/r1. 3670 * 3671 * For: int-to-long, int-to-double, float-to-long, float-to-double 3672 */ 3673 /* unop vA, vB */ 3674 mov r9, rINST, lsr #8 @ r9<- A+ 3675 mov r3, rINST, lsr #12 @ r3<- B 3676 and r9, r9, #15 3677 GET_VREG(r0, r3) @ r0<- vB 3678 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3679 @ optional op; may set condition codes 3680 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3681 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3682 GET_INST_OPCODE(ip) @ extract opcode from rINST 3683 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3684 GOTO_OPCODE(ip) @ jump to next instruction 3685 /* 10-11 instructions */ 3686 3687 3688/* ------------------------------ */ 3689 .balign 64 3690.L_OP_INT_TO_FLOAT: /* 0x82 */ 3691/* File: arm-vfp/OP_INT_TO_FLOAT.S */ 3692/* File: arm-vfp/funop.S */ 3693 /* 3694 * Generic 32-bit unary floating-point operation. Provide an "instr" 3695 * line that specifies an instruction that performs "s1 = op s0". 3696 * 3697 * for: int-to-float, float-to-int 3698 */ 3699 /* unop vA, vB */ 3700 mov r3, rINST, lsr #12 @ r3<- B 3701 mov r9, rINST, lsr #8 @ r9<- A+ 3702 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3703 flds s0, [r3] @ s0<- vB 3704 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3705 and r9, r9, #15 @ r9<- A 3706 fsitos s1, s0 @ s1<- op 3707 GET_INST_OPCODE(ip) @ extract opcode from rINST 3708 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3709 fsts s1, [r9] @ vA<- s1 3710 GOTO_OPCODE(ip) @ jump to next instruction 3711 3712 3713/* ------------------------------ */ 3714 .balign 64 3715.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3716/* File: arm-vfp/OP_INT_TO_DOUBLE.S */ 3717/* File: arm-vfp/funopWider.S */ 3718 /* 3719 * Generic 32bit-to-64bit floating point unary operation. Provide an 3720 * "instr" line that specifies an instruction that performs "d0 = op s0". 3721 * 3722 * For: int-to-double, float-to-double 3723 */ 3724 /* unop vA, vB */ 3725 mov r3, rINST, lsr #12 @ r3<- B 3726 mov r9, rINST, lsr #8 @ r9<- A+ 3727 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3728 flds s0, [r3] @ s0<- vB 3729 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3730 and r9, r9, #15 @ r9<- A 3731 fsitod d0, s0 @ d0<- op 3732 GET_INST_OPCODE(ip) @ extract opcode from rINST 3733 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3734 fstd d0, [r9] @ vA<- d0 3735 GOTO_OPCODE(ip) @ jump to next instruction 3736 3737 3738/* ------------------------------ */ 3739 .balign 64 3740.L_OP_LONG_TO_INT: /* 0x84 */ 3741/* File: armv5te/OP_LONG_TO_INT.S */ 3742/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3743/* File: armv5te/OP_MOVE.S */ 3744 /* for move, move-object, long-to-int */ 3745 /* op vA, vB */ 3746 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3747 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3748 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3749 GET_VREG(r2, r1) @ r2<- fp[B] 3750 and r0, r0, #15 3751 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3752 SET_VREG(r2, r0) @ fp[A]<- r2 3753 GOTO_OPCODE(ip) @ execute next instruction 3754 3755 3756/* ------------------------------ */ 3757 .balign 64 3758.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3759/* File: armv5te/OP_LONG_TO_FLOAT.S */ 3760/* File: armv5te/unopNarrower.S */ 3761 /* 3762 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3763 * that specifies an instruction that performs "result = op r0/r1", where 3764 * "result" is a 32-bit quantity in r0. 3765 * 3766 * For: long-to-float, double-to-int, double-to-float 3767 * 3768 * (This would work for long-to-int, but that instruction is actually 3769 * an exact match for OP_MOVE.) 3770 */ 3771 /* unop vA, vB */ 3772 mov r3, rINST, lsr #12 @ r3<- B 3773 mov r9, rINST, lsr #8 @ r9<- A+ 3774 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3775 and r9, r9, #15 3776 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3777 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3778 @ optional op; may set condition codes 3779 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3780 GET_INST_OPCODE(ip) @ extract opcode from rINST 3781 SET_VREG(r0, r9) @ vA<- r0 3782 GOTO_OPCODE(ip) @ jump to next instruction 3783 /* 10-11 instructions */ 3784 3785 3786/* ------------------------------ */ 3787 .balign 64 3788.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3789/* File: armv5te/OP_LONG_TO_DOUBLE.S */ 3790/* File: armv5te/unopWide.S */ 3791 /* 3792 * Generic 64-bit unary operation. Provide an "instr" line that 3793 * specifies an instruction that performs "result = op r0/r1". 3794 * This could be an ARM instruction or a function call. 3795 * 3796 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3797 */ 3798 /* unop vA, vB */ 3799 mov r9, rINST, lsr #8 @ r9<- A+ 3800 mov r3, rINST, lsr #12 @ r3<- B 3801 and r9, r9, #15 3802 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3803 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3804 ldmia r3, {r0-r1} @ r0/r1<- vAA 3805 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3806 @ optional op; may set condition codes 3807 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3808 GET_INST_OPCODE(ip) @ extract opcode from rINST 3809 stmia r9, {r0-r1} @ vAA<- r0/r1 3810 GOTO_OPCODE(ip) @ jump to next instruction 3811 /* 12-13 instructions */ 3812 3813 3814/* ------------------------------ */ 3815 .balign 64 3816.L_OP_FLOAT_TO_INT: /* 0x87 */ 3817/* File: arm-vfp/OP_FLOAT_TO_INT.S */ 3818/* File: arm-vfp/funop.S */ 3819 /* 3820 * Generic 32-bit unary floating-point operation. Provide an "instr" 3821 * line that specifies an instruction that performs "s1 = op s0". 3822 * 3823 * for: int-to-float, float-to-int 3824 */ 3825 /* unop vA, vB */ 3826 mov r3, rINST, lsr #12 @ r3<- B 3827 mov r9, rINST, lsr #8 @ r9<- A+ 3828 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3829 flds s0, [r3] @ s0<- vB 3830 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3831 and r9, r9, #15 @ r9<- A 3832 ftosizs s1, s0 @ s1<- op 3833 GET_INST_OPCODE(ip) @ extract opcode from rINST 3834 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3835 fsts s1, [r9] @ vA<- s1 3836 GOTO_OPCODE(ip) @ jump to next instruction 3837 3838 3839/* ------------------------------ */ 3840 .balign 64 3841.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3842/* File: armv5te/OP_FLOAT_TO_LONG.S */ 3843@include "armv5te/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3844/* File: armv5te/unopWider.S */ 3845 /* 3846 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3847 * that specifies an instruction that performs "result = op r0", where 3848 * "result" is a 64-bit quantity in r0/r1. 3849 * 3850 * For: int-to-long, int-to-double, float-to-long, float-to-double 3851 */ 3852 /* unop vA, vB */ 3853 mov r9, rINST, lsr #8 @ r9<- A+ 3854 mov r3, rINST, lsr #12 @ r3<- B 3855 and r9, r9, #15 3856 GET_VREG(r0, r3) @ r0<- vB 3857 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3858 @ optional op; may set condition codes 3859 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3860 bl f2l_doconv @ r0<- op, r0-r3 changed 3861 GET_INST_OPCODE(ip) @ extract opcode from rINST 3862 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3863 GOTO_OPCODE(ip) @ jump to next instruction 3864 /* 10-11 instructions */ 3865 3866 3867 3868/* ------------------------------ */ 3869 .balign 64 3870.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3871/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */ 3872/* File: arm-vfp/funopWider.S */ 3873 /* 3874 * Generic 32bit-to-64bit floating point unary operation. Provide an 3875 * "instr" line that specifies an instruction that performs "d0 = op s0". 3876 * 3877 * For: int-to-double, float-to-double 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 flds s0, [r3] @ s0<- vB 3884 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3885 and r9, r9, #15 @ r9<- A 3886 fcvtds d0, s0 @ d0<- op 3887 GET_INST_OPCODE(ip) @ extract opcode from rINST 3888 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3889 fstd d0, [r9] @ vA<- d0 3890 GOTO_OPCODE(ip) @ jump to next instruction 3891 3892 3893/* ------------------------------ */ 3894 .balign 64 3895.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3896/* File: arm-vfp/OP_DOUBLE_TO_INT.S */ 3897/* File: arm-vfp/funopNarrower.S */ 3898 /* 3899 * Generic 64bit-to-32bit unary floating point operation. Provide an 3900 * "instr" line that specifies an instruction that performs "s0 = op d0". 3901 * 3902 * For: double-to-int, double-to-float 3903 */ 3904 /* unop vA, vB */ 3905 mov r3, rINST, lsr #12 @ r3<- B 3906 mov r9, rINST, lsr #8 @ r9<- A+ 3907 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3908 fldd d0, [r3] @ d0<- vB 3909 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3910 and r9, r9, #15 @ r9<- A 3911 ftosizd s0, d0 @ s0<- op 3912 GET_INST_OPCODE(ip) @ extract opcode from rINST 3913 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3914 fsts s0, [r9] @ vA<- s0 3915 GOTO_OPCODE(ip) @ jump to next instruction 3916 3917 3918/* ------------------------------ */ 3919 .balign 64 3920.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3921/* File: armv5te/OP_DOUBLE_TO_LONG.S */ 3922@include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"} 3923/* File: armv5te/unopWide.S */ 3924 /* 3925 * Generic 64-bit unary operation. Provide an "instr" line that 3926 * specifies an instruction that performs "result = op r0/r1". 3927 * This could be an ARM instruction or a function call. 3928 * 3929 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3930 */ 3931 /* unop vA, vB */ 3932 mov r9, rINST, lsr #8 @ r9<- A+ 3933 mov r3, rINST, lsr #12 @ r3<- B 3934 and r9, r9, #15 3935 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3936 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3937 ldmia r3, {r0-r1} @ r0/r1<- vAA 3938 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3939 @ optional op; may set condition codes 3940 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 3941 GET_INST_OPCODE(ip) @ extract opcode from rINST 3942 stmia r9, {r0-r1} @ vAA<- r0/r1 3943 GOTO_OPCODE(ip) @ jump to next instruction 3944 /* 12-13 instructions */ 3945 3946 3947 3948/* ------------------------------ */ 3949 .balign 64 3950.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3951/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */ 3952/* File: arm-vfp/funopNarrower.S */ 3953 /* 3954 * Generic 64bit-to-32bit unary floating point operation. Provide an 3955 * "instr" line that specifies an instruction that performs "s0 = op d0". 3956 * 3957 * For: double-to-int, double-to-float 3958 */ 3959 /* unop vA, vB */ 3960 mov r3, rINST, lsr #12 @ r3<- B 3961 mov r9, rINST, lsr #8 @ r9<- A+ 3962 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3963 fldd d0, [r3] @ d0<- vB 3964 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3965 and r9, r9, #15 @ r9<- A 3966 fcvtsd s0, d0 @ s0<- op 3967 GET_INST_OPCODE(ip) @ extract opcode from rINST 3968 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3969 fsts s0, [r9] @ vA<- s0 3970 GOTO_OPCODE(ip) @ jump to next instruction 3971 3972 3973/* ------------------------------ */ 3974 .balign 64 3975.L_OP_INT_TO_BYTE: /* 0x8d */ 3976/* File: armv5te/OP_INT_TO_BYTE.S */ 3977/* File: armv5te/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 mov r9, rINST, lsr #8 @ r9<- A+ 3989 GET_VREG(r0, r3) @ r0<- vB 3990 and r9, r9, #15 3991 mov r0, r0, asl #24 @ optional op; may set condition codes 3992 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3993 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed 3994 GET_INST_OPCODE(ip) @ extract opcode from rINST 3995 SET_VREG(r0, r9) @ vAA<- r0 3996 GOTO_OPCODE(ip) @ jump to next instruction 3997 /* 9-10 instructions */ 3998 3999 4000/* ------------------------------ */ 4001 .balign 64 4002.L_OP_INT_TO_CHAR: /* 0x8e */ 4003/* File: armv5te/OP_INT_TO_CHAR.S */ 4004/* File: armv5te/unop.S */ 4005 /* 4006 * Generic 32-bit unary operation. Provide an "instr" line that 4007 * specifies an instruction that performs "result = op r0". 4008 * This could be an ARM instruction or a function call. 4009 * 4010 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4011 * int-to-byte, int-to-char, int-to-short 4012 */ 4013 /* unop vA, vB */ 4014 mov r3, rINST, lsr #12 @ r3<- B 4015 mov r9, rINST, lsr #8 @ r9<- A+ 4016 GET_VREG(r0, r3) @ r0<- vB 4017 and r9, r9, #15 4018 mov r0, r0, asl #16 @ optional op; may set condition codes 4019 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4020 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed 4021 GET_INST_OPCODE(ip) @ extract opcode from rINST 4022 SET_VREG(r0, r9) @ vAA<- r0 4023 GOTO_OPCODE(ip) @ jump to next instruction 4024 /* 9-10 instructions */ 4025 4026 4027/* ------------------------------ */ 4028 .balign 64 4029.L_OP_INT_TO_SHORT: /* 0x8f */ 4030/* File: armv5te/OP_INT_TO_SHORT.S */ 4031/* File: armv5te/unop.S */ 4032 /* 4033 * Generic 32-bit unary operation. Provide an "instr" line that 4034 * specifies an instruction that performs "result = op r0". 4035 * This could be an ARM instruction or a function call. 4036 * 4037 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4038 * int-to-byte, int-to-char, int-to-short 4039 */ 4040 /* unop vA, vB */ 4041 mov r3, rINST, lsr #12 @ r3<- B 4042 mov r9, rINST, lsr #8 @ r9<- A+ 4043 GET_VREG(r0, r3) @ r0<- vB 4044 and r9, r9, #15 4045 mov r0, r0, asl #16 @ optional op; may set condition codes 4046 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4047 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed 4048 GET_INST_OPCODE(ip) @ extract opcode from rINST 4049 SET_VREG(r0, r9) @ vAA<- r0 4050 GOTO_OPCODE(ip) @ jump to next instruction 4051 /* 9-10 instructions */ 4052 4053 4054/* ------------------------------ */ 4055 .balign 64 4056.L_OP_ADD_INT: /* 0x90 */ 4057/* File: armv5te/OP_ADD_INT.S */ 4058/* File: armv5te/binop.S */ 4059 /* 4060 * Generic 32-bit binary operation. Provide an "instr" line that 4061 * specifies an instruction that performs "result = r0 op r1". 4062 * This could be an ARM instruction or a function call. (If the result 4063 * comes back in a register other than r0, you can override "result".) 4064 * 4065 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4066 * vCC (r1). Useful for integer division and modulus. Note that we 4067 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4068 * handles it correctly. 4069 * 4070 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4071 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4072 * mul-float, div-float, rem-float 4073 */ 4074 /* binop vAA, vBB, vCC */ 4075 FETCH(r0, 1) @ r0<- CCBB 4076 mov r9, rINST, lsr #8 @ r9<- AA 4077 mov r3, r0, lsr #8 @ r3<- CC 4078 and r2, r0, #255 @ r2<- BB 4079 GET_VREG(r1, r3) @ r1<- vCC 4080 GET_VREG(r0, r2) @ r0<- vBB 4081 .if 0 4082 cmp r1, #0 @ is second operand zero? 4083 beq common_errDivideByZero 4084 .endif 4085 4086 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4087 @ optional op; may set condition codes 4088 add r0, r0, r1 @ r0<- op, r0-r3 changed 4089 GET_INST_OPCODE(ip) @ extract opcode from rINST 4090 SET_VREG(r0, r9) @ vAA<- r0 4091 GOTO_OPCODE(ip) @ jump to next instruction 4092 /* 11-14 instructions */ 4093 4094 4095/* ------------------------------ */ 4096 .balign 64 4097.L_OP_SUB_INT: /* 0x91 */ 4098/* File: armv5te/OP_SUB_INT.S */ 4099/* File: armv5te/binop.S */ 4100 /* 4101 * Generic 32-bit binary operation. Provide an "instr" line that 4102 * specifies an instruction that performs "result = r0 op r1". 4103 * This could be an ARM instruction or a function call. (If the result 4104 * comes back in a register other than r0, you can override "result".) 4105 * 4106 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4107 * vCC (r1). Useful for integer division and modulus. Note that we 4108 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4109 * handles it correctly. 4110 * 4111 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4112 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4113 * mul-float, div-float, rem-float 4114 */ 4115 /* binop vAA, vBB, vCC */ 4116 FETCH(r0, 1) @ r0<- CCBB 4117 mov r9, rINST, lsr #8 @ r9<- AA 4118 mov r3, r0, lsr #8 @ r3<- CC 4119 and r2, r0, #255 @ r2<- BB 4120 GET_VREG(r1, r3) @ r1<- vCC 4121 GET_VREG(r0, r2) @ r0<- vBB 4122 .if 0 4123 cmp r1, #0 @ is second operand zero? 4124 beq common_errDivideByZero 4125 .endif 4126 4127 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4128 @ optional op; may set condition codes 4129 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4130 GET_INST_OPCODE(ip) @ extract opcode from rINST 4131 SET_VREG(r0, r9) @ vAA<- r0 4132 GOTO_OPCODE(ip) @ jump to next instruction 4133 /* 11-14 instructions */ 4134 4135 4136/* ------------------------------ */ 4137 .balign 64 4138.L_OP_MUL_INT: /* 0x92 */ 4139/* File: armv5te/OP_MUL_INT.S */ 4140/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4141/* File: armv5te/binop.S */ 4142 /* 4143 * Generic 32-bit binary operation. Provide an "instr" line that 4144 * specifies an instruction that performs "result = r0 op r1". 4145 * This could be an ARM instruction or a function call. (If the result 4146 * comes back in a register other than r0, you can override "result".) 4147 * 4148 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4149 * vCC (r1). Useful for integer division and modulus. Note that we 4150 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4151 * handles it correctly. 4152 * 4153 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4154 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4155 * mul-float, div-float, rem-float 4156 */ 4157 /* binop vAA, vBB, vCC */ 4158 FETCH(r0, 1) @ r0<- CCBB 4159 mov r9, rINST, lsr #8 @ r9<- AA 4160 mov r3, r0, lsr #8 @ r3<- CC 4161 and r2, r0, #255 @ r2<- BB 4162 GET_VREG(r1, r3) @ r1<- vCC 4163 GET_VREG(r0, r2) @ r0<- vBB 4164 .if 0 4165 cmp r1, #0 @ is second operand zero? 4166 beq common_errDivideByZero 4167 .endif 4168 4169 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4170 @ optional op; may set condition codes 4171 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4172 GET_INST_OPCODE(ip) @ extract opcode from rINST 4173 SET_VREG(r0, r9) @ vAA<- r0 4174 GOTO_OPCODE(ip) @ jump to next instruction 4175 /* 11-14 instructions */ 4176 4177 4178/* ------------------------------ */ 4179 .balign 64 4180.L_OP_DIV_INT: /* 0x93 */ 4181/* File: armv5te/OP_DIV_INT.S */ 4182/* File: armv5te/binop.S */ 4183 /* 4184 * Generic 32-bit binary operation. Provide an "instr" line that 4185 * specifies an instruction that performs "result = r0 op r1". 4186 * This could be an ARM instruction or a function call. (If the result 4187 * comes back in a register other than r0, you can override "result".) 4188 * 4189 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4190 * vCC (r1). Useful for integer division and modulus. Note that we 4191 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4192 * handles it correctly. 4193 * 4194 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4195 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4196 * mul-float, div-float, rem-float 4197 */ 4198 /* binop vAA, vBB, vCC */ 4199 FETCH(r0, 1) @ r0<- CCBB 4200 mov r9, rINST, lsr #8 @ r9<- AA 4201 mov r3, r0, lsr #8 @ r3<- CC 4202 and r2, r0, #255 @ r2<- BB 4203 GET_VREG(r1, r3) @ r1<- vCC 4204 GET_VREG(r0, r2) @ r0<- vBB 4205 .if 1 4206 cmp r1, #0 @ is second operand zero? 4207 beq common_errDivideByZero 4208 .endif 4209 4210 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4211 @ optional op; may set condition codes 4212 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4213 GET_INST_OPCODE(ip) @ extract opcode from rINST 4214 SET_VREG(r0, r9) @ vAA<- r0 4215 GOTO_OPCODE(ip) @ jump to next instruction 4216 /* 11-14 instructions */ 4217 4218 4219/* ------------------------------ */ 4220 .balign 64 4221.L_OP_REM_INT: /* 0x94 */ 4222/* File: armv5te/OP_REM_INT.S */ 4223/* idivmod returns quotient in r0 and remainder in r1 */ 4224/* File: armv5te/binop.S */ 4225 /* 4226 * Generic 32-bit binary operation. Provide an "instr" line that 4227 * specifies an instruction that performs "result = r0 op r1". 4228 * This could be an ARM instruction or a function call. (If the result 4229 * comes back in a register other than r0, you can override "result".) 4230 * 4231 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4232 * vCC (r1). Useful for integer division and modulus. Note that we 4233 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4234 * handles it correctly. 4235 * 4236 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4237 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4238 * mul-float, div-float, rem-float 4239 */ 4240 /* binop vAA, vBB, vCC */ 4241 FETCH(r0, 1) @ r0<- CCBB 4242 mov r9, rINST, lsr #8 @ r9<- AA 4243 mov r3, r0, lsr #8 @ r3<- CC 4244 and r2, r0, #255 @ r2<- BB 4245 GET_VREG(r1, r3) @ r1<- vCC 4246 GET_VREG(r0, r2) @ r0<- vBB 4247 .if 1 4248 cmp r1, #0 @ is second operand zero? 4249 beq common_errDivideByZero 4250 .endif 4251 4252 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4253 @ optional op; may set condition codes 4254 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4255 GET_INST_OPCODE(ip) @ extract opcode from rINST 4256 SET_VREG(r1, r9) @ vAA<- r1 4257 GOTO_OPCODE(ip) @ jump to next instruction 4258 /* 11-14 instructions */ 4259 4260 4261/* ------------------------------ */ 4262 .balign 64 4263.L_OP_AND_INT: /* 0x95 */ 4264/* File: armv5te/OP_AND_INT.S */ 4265/* File: armv5te/binop.S */ 4266 /* 4267 * Generic 32-bit binary operation. Provide an "instr" line that 4268 * specifies an instruction that performs "result = r0 op r1". 4269 * This could be an ARM instruction or a function call. (If the result 4270 * comes back in a register other than r0, you can override "result".) 4271 * 4272 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4273 * vCC (r1). Useful for integer division and modulus. Note that we 4274 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4275 * handles it correctly. 4276 * 4277 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4278 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4279 * mul-float, div-float, rem-float 4280 */ 4281 /* binop vAA, vBB, vCC */ 4282 FETCH(r0, 1) @ r0<- CCBB 4283 mov r9, rINST, lsr #8 @ r9<- AA 4284 mov r3, r0, lsr #8 @ r3<- CC 4285 and r2, r0, #255 @ r2<- BB 4286 GET_VREG(r1, r3) @ r1<- vCC 4287 GET_VREG(r0, r2) @ r0<- vBB 4288 .if 0 4289 cmp r1, #0 @ is second operand zero? 4290 beq common_errDivideByZero 4291 .endif 4292 4293 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4294 @ optional op; may set condition codes 4295 and r0, r0, r1 @ r0<- op, r0-r3 changed 4296 GET_INST_OPCODE(ip) @ extract opcode from rINST 4297 SET_VREG(r0, r9) @ vAA<- r0 4298 GOTO_OPCODE(ip) @ jump to next instruction 4299 /* 11-14 instructions */ 4300 4301 4302/* ------------------------------ */ 4303 .balign 64 4304.L_OP_OR_INT: /* 0x96 */ 4305/* File: armv5te/OP_OR_INT.S */ 4306/* File: armv5te/binop.S */ 4307 /* 4308 * Generic 32-bit binary operation. Provide an "instr" line that 4309 * specifies an instruction that performs "result = r0 op r1". 4310 * This could be an ARM instruction or a function call. (If the result 4311 * comes back in a register other than r0, you can override "result".) 4312 * 4313 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4314 * vCC (r1). Useful for integer division and modulus. Note that we 4315 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4316 * handles it correctly. 4317 * 4318 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4319 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4320 * mul-float, div-float, rem-float 4321 */ 4322 /* binop vAA, vBB, vCC */ 4323 FETCH(r0, 1) @ r0<- CCBB 4324 mov r9, rINST, lsr #8 @ r9<- AA 4325 mov r3, r0, lsr #8 @ r3<- CC 4326 and r2, r0, #255 @ r2<- BB 4327 GET_VREG(r1, r3) @ r1<- vCC 4328 GET_VREG(r0, r2) @ r0<- vBB 4329 .if 0 4330 cmp r1, #0 @ is second operand zero? 4331 beq common_errDivideByZero 4332 .endif 4333 4334 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4335 @ optional op; may set condition codes 4336 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4337 GET_INST_OPCODE(ip) @ extract opcode from rINST 4338 SET_VREG(r0, r9) @ vAA<- r0 4339 GOTO_OPCODE(ip) @ jump to next instruction 4340 /* 11-14 instructions */ 4341 4342 4343/* ------------------------------ */ 4344 .balign 64 4345.L_OP_XOR_INT: /* 0x97 */ 4346/* File: armv5te/OP_XOR_INT.S */ 4347/* File: armv5te/binop.S */ 4348 /* 4349 * Generic 32-bit binary operation. Provide an "instr" line that 4350 * specifies an instruction that performs "result = r0 op r1". 4351 * This could be an ARM instruction or a function call. (If the result 4352 * comes back in a register other than r0, you can override "result".) 4353 * 4354 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4355 * vCC (r1). Useful for integer division and modulus. Note that we 4356 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4357 * handles it correctly. 4358 * 4359 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4360 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4361 * mul-float, div-float, rem-float 4362 */ 4363 /* binop vAA, vBB, vCC */ 4364 FETCH(r0, 1) @ r0<- CCBB 4365 mov r9, rINST, lsr #8 @ r9<- AA 4366 mov r3, r0, lsr #8 @ r3<- CC 4367 and r2, r0, #255 @ r2<- BB 4368 GET_VREG(r1, r3) @ r1<- vCC 4369 GET_VREG(r0, r2) @ r0<- vBB 4370 .if 0 4371 cmp r1, #0 @ is second operand zero? 4372 beq common_errDivideByZero 4373 .endif 4374 4375 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4376 @ optional op; may set condition codes 4377 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4378 GET_INST_OPCODE(ip) @ extract opcode from rINST 4379 SET_VREG(r0, r9) @ vAA<- r0 4380 GOTO_OPCODE(ip) @ jump to next instruction 4381 /* 11-14 instructions */ 4382 4383 4384/* ------------------------------ */ 4385 .balign 64 4386.L_OP_SHL_INT: /* 0x98 */ 4387/* File: armv5te/OP_SHL_INT.S */ 4388/* File: armv5te/binop.S */ 4389 /* 4390 * Generic 32-bit binary operation. Provide an "instr" line that 4391 * specifies an instruction that performs "result = r0 op r1". 4392 * This could be an ARM instruction or a function call. (If the result 4393 * comes back in a register other than r0, you can override "result".) 4394 * 4395 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4396 * vCC (r1). Useful for integer division and modulus. Note that we 4397 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4398 * handles it correctly. 4399 * 4400 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4401 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4402 * mul-float, div-float, rem-float 4403 */ 4404 /* binop vAA, vBB, vCC */ 4405 FETCH(r0, 1) @ r0<- CCBB 4406 mov r9, rINST, lsr #8 @ r9<- AA 4407 mov r3, r0, lsr #8 @ r3<- CC 4408 and r2, r0, #255 @ r2<- BB 4409 GET_VREG(r1, r3) @ r1<- vCC 4410 GET_VREG(r0, r2) @ r0<- vBB 4411 .if 0 4412 cmp r1, #0 @ is second operand zero? 4413 beq common_errDivideByZero 4414 .endif 4415 4416 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4417 and r1, r1, #31 @ optional op; may set condition codes 4418 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4419 GET_INST_OPCODE(ip) @ extract opcode from rINST 4420 SET_VREG(r0, r9) @ vAA<- r0 4421 GOTO_OPCODE(ip) @ jump to next instruction 4422 /* 11-14 instructions */ 4423 4424 4425/* ------------------------------ */ 4426 .balign 64 4427.L_OP_SHR_INT: /* 0x99 */ 4428/* File: armv5te/OP_SHR_INT.S */ 4429/* File: armv5te/binop.S */ 4430 /* 4431 * Generic 32-bit binary operation. Provide an "instr" line that 4432 * specifies an instruction that performs "result = r0 op r1". 4433 * This could be an ARM instruction or a function call. (If the result 4434 * comes back in a register other than r0, you can override "result".) 4435 * 4436 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4437 * vCC (r1). Useful for integer division and modulus. Note that we 4438 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4439 * handles it correctly. 4440 * 4441 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4442 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4443 * mul-float, div-float, rem-float 4444 */ 4445 /* binop vAA, vBB, vCC */ 4446 FETCH(r0, 1) @ r0<- CCBB 4447 mov r9, rINST, lsr #8 @ r9<- AA 4448 mov r3, r0, lsr #8 @ r3<- CC 4449 and r2, r0, #255 @ r2<- BB 4450 GET_VREG(r1, r3) @ r1<- vCC 4451 GET_VREG(r0, r2) @ r0<- vBB 4452 .if 0 4453 cmp r1, #0 @ is second operand zero? 4454 beq common_errDivideByZero 4455 .endif 4456 4457 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4458 and r1, r1, #31 @ optional op; may set condition codes 4459 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4460 GET_INST_OPCODE(ip) @ extract opcode from rINST 4461 SET_VREG(r0, r9) @ vAA<- r0 4462 GOTO_OPCODE(ip) @ jump to next instruction 4463 /* 11-14 instructions */ 4464 4465 4466/* ------------------------------ */ 4467 .balign 64 4468.L_OP_USHR_INT: /* 0x9a */ 4469/* File: armv5te/OP_USHR_INT.S */ 4470/* File: armv5te/binop.S */ 4471 /* 4472 * Generic 32-bit binary operation. Provide an "instr" line that 4473 * specifies an instruction that performs "result = r0 op r1". 4474 * This could be an ARM instruction or a function call. (If the result 4475 * comes back in a register other than r0, you can override "result".) 4476 * 4477 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4478 * vCC (r1). Useful for integer division and modulus. Note that we 4479 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4480 * handles it correctly. 4481 * 4482 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4483 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4484 * mul-float, div-float, rem-float 4485 */ 4486 /* binop vAA, vBB, vCC */ 4487 FETCH(r0, 1) @ r0<- CCBB 4488 mov r9, rINST, lsr #8 @ r9<- AA 4489 mov r3, r0, lsr #8 @ r3<- CC 4490 and r2, r0, #255 @ r2<- BB 4491 GET_VREG(r1, r3) @ r1<- vCC 4492 GET_VREG(r0, r2) @ r0<- vBB 4493 .if 0 4494 cmp r1, #0 @ is second operand zero? 4495 beq common_errDivideByZero 4496 .endif 4497 4498 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4499 and r1, r1, #31 @ optional op; may set condition codes 4500 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4501 GET_INST_OPCODE(ip) @ extract opcode from rINST 4502 SET_VREG(r0, r9) @ vAA<- r0 4503 GOTO_OPCODE(ip) @ jump to next instruction 4504 /* 11-14 instructions */ 4505 4506 4507/* ------------------------------ */ 4508 .balign 64 4509.L_OP_ADD_LONG: /* 0x9b */ 4510/* File: armv5te/OP_ADD_LONG.S */ 4511/* File: armv5te/binopWide.S */ 4512 /* 4513 * Generic 64-bit binary operation. Provide an "instr" line that 4514 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4515 * This could be an ARM instruction or a function call. (If the result 4516 * comes back in a register other than r0, you can override "result".) 4517 * 4518 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4519 * vCC (r1). Useful for integer division and modulus. 4520 * 4521 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4522 * xor-long, add-double, sub-double, mul-double, div-double, 4523 * rem-double 4524 * 4525 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4526 */ 4527 /* binop vAA, vBB, vCC */ 4528 FETCH(r0, 1) @ r0<- CCBB 4529 mov r9, rINST, lsr #8 @ r9<- AA 4530 and r2, r0, #255 @ r2<- BB 4531 mov r3, r0, lsr #8 @ r3<- CC 4532 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4533 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4534 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4535 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4536 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4537 .if 0 4538 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4539 beq common_errDivideByZero 4540 .endif 4541 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4542 4543 adds r0, r0, r2 @ optional op; may set condition codes 4544 adc r1, r1, r3 @ result<- op, r0-r3 changed 4545 GET_INST_OPCODE(ip) @ extract opcode from rINST 4546 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4547 GOTO_OPCODE(ip) @ jump to next instruction 4548 /* 14-17 instructions */ 4549 4550 4551/* ------------------------------ */ 4552 .balign 64 4553.L_OP_SUB_LONG: /* 0x9c */ 4554/* File: armv5te/OP_SUB_LONG.S */ 4555/* File: armv5te/binopWide.S */ 4556 /* 4557 * Generic 64-bit binary operation. Provide an "instr" line that 4558 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4559 * This could be an ARM instruction or a function call. (If the result 4560 * comes back in a register other than r0, you can override "result".) 4561 * 4562 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4563 * vCC (r1). Useful for integer division and modulus. 4564 * 4565 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4566 * xor-long, add-double, sub-double, mul-double, div-double, 4567 * rem-double 4568 * 4569 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4570 */ 4571 /* binop vAA, vBB, vCC */ 4572 FETCH(r0, 1) @ r0<- CCBB 4573 mov r9, rINST, lsr #8 @ r9<- AA 4574 and r2, r0, #255 @ r2<- BB 4575 mov r3, r0, lsr #8 @ r3<- CC 4576 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4577 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4578 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4579 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4580 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4581 .if 0 4582 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4583 beq common_errDivideByZero 4584 .endif 4585 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4586 4587 subs r0, r0, r2 @ optional op; may set condition codes 4588 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4589 GET_INST_OPCODE(ip) @ extract opcode from rINST 4590 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4591 GOTO_OPCODE(ip) @ jump to next instruction 4592 /* 14-17 instructions */ 4593 4594 4595/* ------------------------------ */ 4596 .balign 64 4597.L_OP_MUL_LONG: /* 0x9d */ 4598/* File: armv5te/OP_MUL_LONG.S */ 4599 /* 4600 * Signed 64-bit integer multiply. 4601 * 4602 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4603 * WX 4604 * x YZ 4605 * -------- 4606 * ZW ZX 4607 * YW YX 4608 * 4609 * The low word of the result holds ZX, the high word holds 4610 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4611 * it doesn't fit in the low 64 bits. 4612 * 4613 * Unlike most ARM math operations, multiply instructions have 4614 * restrictions on using the same register more than once (Rd and Rm 4615 * cannot be the same). 4616 */ 4617 /* mul-long vAA, vBB, vCC */ 4618 FETCH(r0, 1) @ r0<- CCBB 4619 and r2, r0, #255 @ r2<- BB 4620 mov r3, r0, lsr #8 @ r3<- CC 4621 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4622 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4623 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4624 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4625 mul ip, r2, r1 @ ip<- ZxW 4626 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4627 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4628 mov r0, rINST, lsr #8 @ r0<- AA 4629 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4630 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4631 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4632 b .LOP_MUL_LONG_finish 4633 4634/* ------------------------------ */ 4635 .balign 64 4636.L_OP_DIV_LONG: /* 0x9e */ 4637/* File: armv5te/OP_DIV_LONG.S */ 4638/* File: armv5te/binopWide.S */ 4639 /* 4640 * Generic 64-bit binary operation. Provide an "instr" line that 4641 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4642 * This could be an ARM instruction or a function call. (If the result 4643 * comes back in a register other than r0, you can override "result".) 4644 * 4645 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4646 * vCC (r1). Useful for integer division and modulus. 4647 * 4648 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4649 * xor-long, add-double, sub-double, mul-double, div-double, 4650 * rem-double 4651 * 4652 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4653 */ 4654 /* binop vAA, vBB, vCC */ 4655 FETCH(r0, 1) @ r0<- CCBB 4656 mov r9, rINST, lsr #8 @ r9<- AA 4657 and r2, r0, #255 @ r2<- BB 4658 mov r3, r0, lsr #8 @ r3<- CC 4659 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4660 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4661 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4662 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4663 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4664 .if 1 4665 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4666 beq common_errDivideByZero 4667 .endif 4668 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4669 4670 @ optional op; may set condition codes 4671 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4672 GET_INST_OPCODE(ip) @ extract opcode from rINST 4673 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4674 GOTO_OPCODE(ip) @ jump to next instruction 4675 /* 14-17 instructions */ 4676 4677 4678/* ------------------------------ */ 4679 .balign 64 4680.L_OP_REM_LONG: /* 0x9f */ 4681/* File: armv5te/OP_REM_LONG.S */ 4682/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4683/* File: armv5te/binopWide.S */ 4684 /* 4685 * Generic 64-bit binary operation. Provide an "instr" line that 4686 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4687 * This could be an ARM instruction or a function call. (If the result 4688 * comes back in a register other than r0, you can override "result".) 4689 * 4690 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4691 * vCC (r1). Useful for integer division and modulus. 4692 * 4693 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4694 * xor-long, add-double, sub-double, mul-double, div-double, 4695 * rem-double 4696 * 4697 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4698 */ 4699 /* binop vAA, vBB, vCC */ 4700 FETCH(r0, 1) @ r0<- CCBB 4701 mov r9, rINST, lsr #8 @ r9<- AA 4702 and r2, r0, #255 @ r2<- BB 4703 mov r3, r0, lsr #8 @ r3<- CC 4704 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4705 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4706 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4707 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4708 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4709 .if 1 4710 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4711 beq common_errDivideByZero 4712 .endif 4713 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4714 4715 @ optional op; may set condition codes 4716 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4717 GET_INST_OPCODE(ip) @ extract opcode from rINST 4718 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4719 GOTO_OPCODE(ip) @ jump to next instruction 4720 /* 14-17 instructions */ 4721 4722 4723/* ------------------------------ */ 4724 .balign 64 4725.L_OP_AND_LONG: /* 0xa0 */ 4726/* File: armv5te/OP_AND_LONG.S */ 4727/* File: armv5te/binopWide.S */ 4728 /* 4729 * Generic 64-bit binary operation. Provide an "instr" line that 4730 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4731 * This could be an ARM instruction or a function call. (If the result 4732 * comes back in a register other than r0, you can override "result".) 4733 * 4734 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4735 * vCC (r1). Useful for integer division and modulus. 4736 * 4737 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4738 * xor-long, add-double, sub-double, mul-double, div-double, 4739 * rem-double 4740 * 4741 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4742 */ 4743 /* binop vAA, vBB, vCC */ 4744 FETCH(r0, 1) @ r0<- CCBB 4745 mov r9, rINST, lsr #8 @ r9<- AA 4746 and r2, r0, #255 @ r2<- BB 4747 mov r3, r0, lsr #8 @ r3<- CC 4748 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4749 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4750 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4751 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4752 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4753 .if 0 4754 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4755 beq common_errDivideByZero 4756 .endif 4757 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4758 4759 and r0, r0, r2 @ optional op; may set condition codes 4760 and r1, r1, r3 @ result<- op, r0-r3 changed 4761 GET_INST_OPCODE(ip) @ extract opcode from rINST 4762 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4763 GOTO_OPCODE(ip) @ jump to next instruction 4764 /* 14-17 instructions */ 4765 4766 4767/* ------------------------------ */ 4768 .balign 64 4769.L_OP_OR_LONG: /* 0xa1 */ 4770/* File: armv5te/OP_OR_LONG.S */ 4771/* File: armv5te/binopWide.S */ 4772 /* 4773 * Generic 64-bit binary operation. Provide an "instr" line that 4774 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4775 * This could be an ARM instruction or a function call. (If the result 4776 * comes back in a register other than r0, you can override "result".) 4777 * 4778 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4779 * vCC (r1). Useful for integer division and modulus. 4780 * 4781 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4782 * xor-long, add-double, sub-double, mul-double, div-double, 4783 * rem-double 4784 * 4785 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4786 */ 4787 /* binop vAA, vBB, vCC */ 4788 FETCH(r0, 1) @ r0<- CCBB 4789 mov r9, rINST, lsr #8 @ r9<- AA 4790 and r2, r0, #255 @ r2<- BB 4791 mov r3, r0, lsr #8 @ r3<- CC 4792 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4793 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4794 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4795 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4796 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4797 .if 0 4798 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4799 beq common_errDivideByZero 4800 .endif 4801 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4802 4803 orr r0, r0, r2 @ optional op; may set condition codes 4804 orr r1, r1, r3 @ result<- op, r0-r3 changed 4805 GET_INST_OPCODE(ip) @ extract opcode from rINST 4806 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4807 GOTO_OPCODE(ip) @ jump to next instruction 4808 /* 14-17 instructions */ 4809 4810 4811/* ------------------------------ */ 4812 .balign 64 4813.L_OP_XOR_LONG: /* 0xa2 */ 4814/* File: armv5te/OP_XOR_LONG.S */ 4815/* File: armv5te/binopWide.S */ 4816 /* 4817 * Generic 64-bit binary operation. Provide an "instr" line that 4818 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4819 * This could be an ARM instruction or a function call. (If the result 4820 * comes back in a register other than r0, you can override "result".) 4821 * 4822 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4823 * vCC (r1). Useful for integer division and modulus. 4824 * 4825 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4826 * xor-long, add-double, sub-double, mul-double, div-double, 4827 * rem-double 4828 * 4829 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4830 */ 4831 /* binop vAA, vBB, vCC */ 4832 FETCH(r0, 1) @ r0<- CCBB 4833 mov r9, rINST, lsr #8 @ r9<- AA 4834 and r2, r0, #255 @ r2<- BB 4835 mov r3, r0, lsr #8 @ r3<- CC 4836 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4837 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4838 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4839 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4840 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4841 .if 0 4842 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4843 beq common_errDivideByZero 4844 .endif 4845 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4846 4847 eor r0, r0, r2 @ optional op; may set condition codes 4848 eor r1, r1, r3 @ result<- op, r0-r3 changed 4849 GET_INST_OPCODE(ip) @ extract opcode from rINST 4850 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4851 GOTO_OPCODE(ip) @ jump to next instruction 4852 /* 14-17 instructions */ 4853 4854 4855/* ------------------------------ */ 4856 .balign 64 4857.L_OP_SHL_LONG: /* 0xa3 */ 4858/* File: armv5te/OP_SHL_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 /* shl-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 @ r2<- r2 & 0x3f 4874 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4875 4876 mov r1, r1, asl r2 @ r1<- r1 << r2 4877 rsb r3, r2, #32 @ r3<- 32 - r2 4878 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 4879 subs ip, r2, #32 @ ip<- r2 - 32 4880 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 4881 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4882 b .LOP_SHL_LONG_finish 4883 4884/* ------------------------------ */ 4885 .balign 64 4886.L_OP_SHR_LONG: /* 0xa4 */ 4887/* File: armv5te/OP_SHR_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 /* shr-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, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 4910 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4911 b .LOP_SHR_LONG_finish 4912 4913/* ------------------------------ */ 4914 .balign 64 4915.L_OP_USHR_LONG: /* 0xa5 */ 4916/* File: armv5te/OP_USHR_LONG.S */ 4917 /* 4918 * Long integer shift. This is different from the generic 32/64-bit 4919 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4920 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4921 * 6 bits of the shift distance. 4922 */ 4923 /* ushr-long vAA, vBB, vCC */ 4924 FETCH(r0, 1) @ r0<- CCBB 4925 mov r9, rINST, lsr #8 @ r9<- AA 4926 and r3, r0, #255 @ r3<- BB 4927 mov r0, r0, lsr #8 @ r0<- CC 4928 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4929 GET_VREG(r2, r0) @ r2<- vCC 4930 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4931 and r2, r2, #63 @ r0<- r0 & 0x3f 4932 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4933 4934 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4935 rsb r3, r2, #32 @ r3<- 32 - r2 4936 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4937 subs ip, r2, #32 @ ip<- r2 - 32 4938 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 4939 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4940 b .LOP_USHR_LONG_finish 4941 4942/* ------------------------------ */ 4943 .balign 64 4944.L_OP_ADD_FLOAT: /* 0xa6 */ 4945/* File: arm-vfp/OP_ADD_FLOAT.S */ 4946/* File: arm-vfp/fbinop.S */ 4947 /* 4948 * Generic 32-bit floating-point operation. Provide an "instr" line that 4949 * specifies an instruction that performs "s2 = s0 op s1". Because we 4950 * use the "softfp" ABI, this must be an instruction, not a function call. 4951 * 4952 * For: add-float, sub-float, mul-float, div-float 4953 */ 4954 /* floatop vAA, vBB, vCC */ 4955 FETCH(r0, 1) @ r0<- CCBB 4956 mov r9, rINST, lsr #8 @ r9<- AA 4957 mov r3, r0, lsr #8 @ r3<- CC 4958 and r2, r0, #255 @ r2<- BB 4959 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4960 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4961 flds s1, [r3] @ s1<- vCC 4962 flds s0, [r2] @ s0<- vBB 4963 4964 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4965 fadds s2, s0, s1 @ s2<- op 4966 GET_INST_OPCODE(ip) @ extract opcode from rINST 4967 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4968 fsts s2, [r9] @ vAA<- s2 4969 GOTO_OPCODE(ip) @ jump to next instruction 4970 4971 4972/* ------------------------------ */ 4973 .balign 64 4974.L_OP_SUB_FLOAT: /* 0xa7 */ 4975/* File: arm-vfp/OP_SUB_FLOAT.S */ 4976/* File: arm-vfp/fbinop.S */ 4977 /* 4978 * Generic 32-bit floating-point operation. Provide an "instr" line that 4979 * specifies an instruction that performs "s2 = s0 op s1". Because we 4980 * use the "softfp" ABI, this must be an instruction, not a function call. 4981 * 4982 * For: add-float, sub-float, mul-float, div-float 4983 */ 4984 /* floatop vAA, vBB, vCC */ 4985 FETCH(r0, 1) @ r0<- CCBB 4986 mov r9, rINST, lsr #8 @ r9<- AA 4987 mov r3, r0, lsr #8 @ r3<- CC 4988 and r2, r0, #255 @ r2<- BB 4989 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4990 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4991 flds s1, [r3] @ s1<- vCC 4992 flds s0, [r2] @ s0<- vBB 4993 4994 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4995 fsubs s2, s0, s1 @ s2<- op 4996 GET_INST_OPCODE(ip) @ extract opcode from rINST 4997 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4998 fsts s2, [r9] @ vAA<- s2 4999 GOTO_OPCODE(ip) @ jump to next instruction 5000 5001 5002/* ------------------------------ */ 5003 .balign 64 5004.L_OP_MUL_FLOAT: /* 0xa8 */ 5005/* File: arm-vfp/OP_MUL_FLOAT.S */ 5006/* File: arm-vfp/fbinop.S */ 5007 /* 5008 * Generic 32-bit floating-point operation. Provide an "instr" line that 5009 * specifies an instruction that performs "s2 = s0 op s1". Because we 5010 * use the "softfp" ABI, this must be an instruction, not a function call. 5011 * 5012 * For: add-float, sub-float, mul-float, div-float 5013 */ 5014 /* floatop vAA, vBB, vCC */ 5015 FETCH(r0, 1) @ r0<- CCBB 5016 mov r9, rINST, lsr #8 @ r9<- AA 5017 mov r3, r0, lsr #8 @ r3<- CC 5018 and r2, r0, #255 @ r2<- BB 5019 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5020 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5021 flds s1, [r3] @ s1<- vCC 5022 flds s0, [r2] @ s0<- vBB 5023 5024 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5025 fmuls s2, s0, s1 @ s2<- op 5026 GET_INST_OPCODE(ip) @ extract opcode from rINST 5027 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5028 fsts s2, [r9] @ vAA<- s2 5029 GOTO_OPCODE(ip) @ jump to next instruction 5030 5031 5032/* ------------------------------ */ 5033 .balign 64 5034.L_OP_DIV_FLOAT: /* 0xa9 */ 5035/* File: arm-vfp/OP_DIV_FLOAT.S */ 5036/* File: arm-vfp/fbinop.S */ 5037 /* 5038 * Generic 32-bit floating-point operation. Provide an "instr" line that 5039 * specifies an instruction that performs "s2 = s0 op s1". Because we 5040 * use the "softfp" ABI, this must be an instruction, not a function call. 5041 * 5042 * For: add-float, sub-float, mul-float, div-float 5043 */ 5044 /* floatop vAA, vBB, vCC */ 5045 FETCH(r0, 1) @ r0<- CCBB 5046 mov r9, rINST, lsr #8 @ r9<- AA 5047 mov r3, r0, lsr #8 @ r3<- CC 5048 and r2, r0, #255 @ r2<- BB 5049 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5050 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5051 flds s1, [r3] @ s1<- vCC 5052 flds s0, [r2] @ s0<- vBB 5053 5054 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5055 fdivs s2, s0, s1 @ s2<- op 5056 GET_INST_OPCODE(ip) @ extract opcode from rINST 5057 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5058 fsts s2, [r9] @ vAA<- s2 5059 GOTO_OPCODE(ip) @ jump to next instruction 5060 5061 5062/* ------------------------------ */ 5063 .balign 64 5064.L_OP_REM_FLOAT: /* 0xaa */ 5065/* File: armv5te/OP_REM_FLOAT.S */ 5066/* EABI doesn't define a float remainder function, but libm does */ 5067/* File: armv5te/binop.S */ 5068 /* 5069 * Generic 32-bit binary operation. Provide an "instr" line that 5070 * specifies an instruction that performs "result = r0 op r1". 5071 * This could be an ARM instruction or a function call. (If the result 5072 * comes back in a register other than r0, you can override "result".) 5073 * 5074 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5075 * vCC (r1). Useful for integer division and modulus. Note that we 5076 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5077 * handles it correctly. 5078 * 5079 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5080 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5081 * mul-float, div-float, rem-float 5082 */ 5083 /* binop vAA, vBB, vCC */ 5084 FETCH(r0, 1) @ r0<- CCBB 5085 mov r9, rINST, lsr #8 @ r9<- AA 5086 mov r3, r0, lsr #8 @ r3<- CC 5087 and r2, r0, #255 @ r2<- BB 5088 GET_VREG(r1, r3) @ r1<- vCC 5089 GET_VREG(r0, r2) @ r0<- vBB 5090 .if 0 5091 cmp r1, #0 @ is second operand zero? 5092 beq common_errDivideByZero 5093 .endif 5094 5095 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5096 @ optional op; may set condition codes 5097 bl fmodf @ r0<- op, r0-r3 changed 5098 GET_INST_OPCODE(ip) @ extract opcode from rINST 5099 SET_VREG(r0, r9) @ vAA<- r0 5100 GOTO_OPCODE(ip) @ jump to next instruction 5101 /* 11-14 instructions */ 5102 5103 5104/* ------------------------------ */ 5105 .balign 64 5106.L_OP_ADD_DOUBLE: /* 0xab */ 5107/* File: arm-vfp/OP_ADD_DOUBLE.S */ 5108/* File: arm-vfp/fbinopWide.S */ 5109 /* 5110 * Generic 64-bit double-precision floating point binary operation. 5111 * Provide an "instr" line that specifies an instruction that performs 5112 * "d2 = d0 op d1". 5113 * 5114 * for: add-double, sub-double, mul-double, div-double 5115 */ 5116 /* doubleop vAA, vBB, vCC */ 5117 FETCH(r0, 1) @ r0<- CCBB 5118 mov r9, rINST, lsr #8 @ r9<- AA 5119 mov r3, r0, lsr #8 @ r3<- CC 5120 and r2, r0, #255 @ r2<- BB 5121 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5122 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5123 fldd d1, [r3] @ d1<- vCC 5124 fldd d0, [r2] @ d0<- vBB 5125 5126 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5127 faddd d2, d0, d1 @ s2<- op 5128 GET_INST_OPCODE(ip) @ extract opcode from rINST 5129 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5130 fstd d2, [r9] @ vAA<- d2 5131 GOTO_OPCODE(ip) @ jump to next instruction 5132 5133 5134/* ------------------------------ */ 5135 .balign 64 5136.L_OP_SUB_DOUBLE: /* 0xac */ 5137/* File: arm-vfp/OP_SUB_DOUBLE.S */ 5138/* File: arm-vfp/fbinopWide.S */ 5139 /* 5140 * Generic 64-bit double-precision floating point binary operation. 5141 * Provide an "instr" line that specifies an instruction that performs 5142 * "d2 = d0 op d1". 5143 * 5144 * for: add-double, sub-double, mul-double, div-double 5145 */ 5146 /* doubleop vAA, vBB, vCC */ 5147 FETCH(r0, 1) @ r0<- CCBB 5148 mov r9, rINST, lsr #8 @ r9<- AA 5149 mov r3, r0, lsr #8 @ r3<- CC 5150 and r2, r0, #255 @ r2<- BB 5151 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5152 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5153 fldd d1, [r3] @ d1<- vCC 5154 fldd d0, [r2] @ d0<- vBB 5155 5156 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5157 fsubd d2, d0, d1 @ s2<- op 5158 GET_INST_OPCODE(ip) @ extract opcode from rINST 5159 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5160 fstd d2, [r9] @ vAA<- d2 5161 GOTO_OPCODE(ip) @ jump to next instruction 5162 5163 5164/* ------------------------------ */ 5165 .balign 64 5166.L_OP_MUL_DOUBLE: /* 0xad */ 5167/* File: arm-vfp/OP_MUL_DOUBLE.S */ 5168/* File: arm-vfp/fbinopWide.S */ 5169 /* 5170 * Generic 64-bit double-precision floating point binary operation. 5171 * Provide an "instr" line that specifies an instruction that performs 5172 * "d2 = d0 op d1". 5173 * 5174 * for: add-double, sub-double, mul-double, div-double 5175 */ 5176 /* doubleop vAA, vBB, vCC */ 5177 FETCH(r0, 1) @ r0<- CCBB 5178 mov r9, rINST, lsr #8 @ r9<- AA 5179 mov r3, r0, lsr #8 @ r3<- CC 5180 and r2, r0, #255 @ r2<- BB 5181 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5182 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5183 fldd d1, [r3] @ d1<- vCC 5184 fldd d0, [r2] @ d0<- vBB 5185 5186 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5187 fmuld d2, d0, d1 @ s2<- op 5188 GET_INST_OPCODE(ip) @ extract opcode from rINST 5189 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5190 fstd d2, [r9] @ vAA<- d2 5191 GOTO_OPCODE(ip) @ jump to next instruction 5192 5193 5194/* ------------------------------ */ 5195 .balign 64 5196.L_OP_DIV_DOUBLE: /* 0xae */ 5197/* File: arm-vfp/OP_DIV_DOUBLE.S */ 5198/* File: arm-vfp/fbinopWide.S */ 5199 /* 5200 * Generic 64-bit double-precision floating point binary operation. 5201 * Provide an "instr" line that specifies an instruction that performs 5202 * "d2 = d0 op d1". 5203 * 5204 * for: add-double, sub-double, mul-double, div-double 5205 */ 5206 /* doubleop vAA, vBB, vCC */ 5207 FETCH(r0, 1) @ r0<- CCBB 5208 mov r9, rINST, lsr #8 @ r9<- AA 5209 mov r3, r0, lsr #8 @ r3<- CC 5210 and r2, r0, #255 @ r2<- BB 5211 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5212 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5213 fldd d1, [r3] @ d1<- vCC 5214 fldd d0, [r2] @ d0<- vBB 5215 5216 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5217 fdivd d2, d0, d1 @ s2<- op 5218 GET_INST_OPCODE(ip) @ extract opcode from rINST 5219 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5220 fstd d2, [r9] @ vAA<- d2 5221 GOTO_OPCODE(ip) @ jump to next instruction 5222 5223 5224/* ------------------------------ */ 5225 .balign 64 5226.L_OP_REM_DOUBLE: /* 0xaf */ 5227/* File: armv5te/OP_REM_DOUBLE.S */ 5228/* EABI doesn't define a double remainder function, but libm does */ 5229/* File: armv5te/binopWide.S */ 5230 /* 5231 * Generic 64-bit binary operation. Provide an "instr" line that 5232 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5233 * This could be an ARM instruction or a function call. (If the result 5234 * comes back in a register other than r0, you can override "result".) 5235 * 5236 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5237 * vCC (r1). Useful for integer division and modulus. 5238 * 5239 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5240 * xor-long, add-double, sub-double, mul-double, div-double, 5241 * rem-double 5242 * 5243 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5244 */ 5245 /* binop vAA, vBB, vCC */ 5246 FETCH(r0, 1) @ r0<- CCBB 5247 mov r9, rINST, lsr #8 @ r9<- AA 5248 and r2, r0, #255 @ r2<- BB 5249 mov r3, r0, lsr #8 @ r3<- CC 5250 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5251 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5252 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5253 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5254 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5255 .if 0 5256 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5257 beq common_errDivideByZero 5258 .endif 5259 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5260 5261 @ optional op; may set condition codes 5262 bl fmod @ result<- op, r0-r3 changed 5263 GET_INST_OPCODE(ip) @ extract opcode from rINST 5264 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5265 GOTO_OPCODE(ip) @ jump to next instruction 5266 /* 14-17 instructions */ 5267 5268 5269/* ------------------------------ */ 5270 .balign 64 5271.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5272/* File: armv5te/OP_ADD_INT_2ADDR.S */ 5273/* File: armv5te/binop2addr.S */ 5274 /* 5275 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5276 * that specifies an instruction that performs "result = r0 op r1". 5277 * This could be an ARM instruction or a function call. (If the result 5278 * comes back in a register other than r0, you can override "result".) 5279 * 5280 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5281 * vCC (r1). Useful for integer division and modulus. 5282 * 5283 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5284 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5285 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5286 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5287 */ 5288 /* binop/2addr vA, vB */ 5289 mov r9, rINST, lsr #8 @ r9<- A+ 5290 mov r3, rINST, lsr #12 @ r3<- B 5291 and r9, r9, #15 5292 GET_VREG(r1, r3) @ r1<- vB 5293 GET_VREG(r0, r9) @ r0<- vA 5294 .if 0 5295 cmp r1, #0 @ is second operand zero? 5296 beq common_errDivideByZero 5297 .endif 5298 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5299 5300 @ optional op; may set condition codes 5301 add r0, r0, r1 @ r0<- op, r0-r3 changed 5302 GET_INST_OPCODE(ip) @ extract opcode from rINST 5303 SET_VREG(r0, r9) @ vAA<- r0 5304 GOTO_OPCODE(ip) @ jump to next instruction 5305 /* 10-13 instructions */ 5306 5307 5308/* ------------------------------ */ 5309 .balign 64 5310.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5311/* File: armv5te/OP_SUB_INT_2ADDR.S */ 5312/* File: armv5te/binop2addr.S */ 5313 /* 5314 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5315 * that specifies an instruction that performs "result = r0 op r1". 5316 * This could be an ARM instruction or a function call. (If the result 5317 * comes back in a register other than r0, you can override "result".) 5318 * 5319 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5320 * vCC (r1). Useful for integer division and modulus. 5321 * 5322 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5323 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5324 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5325 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5326 */ 5327 /* binop/2addr vA, vB */ 5328 mov r9, rINST, lsr #8 @ r9<- A+ 5329 mov r3, rINST, lsr #12 @ r3<- B 5330 and r9, r9, #15 5331 GET_VREG(r1, r3) @ r1<- vB 5332 GET_VREG(r0, r9) @ r0<- vA 5333 .if 0 5334 cmp r1, #0 @ is second operand zero? 5335 beq common_errDivideByZero 5336 .endif 5337 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5338 5339 @ optional op; may set condition codes 5340 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5341 GET_INST_OPCODE(ip) @ extract opcode from rINST 5342 SET_VREG(r0, r9) @ vAA<- r0 5343 GOTO_OPCODE(ip) @ jump to next instruction 5344 /* 10-13 instructions */ 5345 5346 5347/* ------------------------------ */ 5348 .balign 64 5349.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5350/* File: armv5te/OP_MUL_INT_2ADDR.S */ 5351/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5352/* File: armv5te/binop2addr.S */ 5353 /* 5354 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5355 * that specifies an instruction that performs "result = r0 op r1". 5356 * This could be an ARM instruction or a function call. (If the result 5357 * comes back in a register other than r0, you can override "result".) 5358 * 5359 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5360 * vCC (r1). Useful for integer division and modulus. 5361 * 5362 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5363 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5364 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5365 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5366 */ 5367 /* binop/2addr vA, vB */ 5368 mov r9, rINST, lsr #8 @ r9<- A+ 5369 mov r3, rINST, lsr #12 @ r3<- B 5370 and r9, r9, #15 5371 GET_VREG(r1, r3) @ r1<- vB 5372 GET_VREG(r0, r9) @ r0<- vA 5373 .if 0 5374 cmp r1, #0 @ is second operand zero? 5375 beq common_errDivideByZero 5376 .endif 5377 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5378 5379 @ optional op; may set condition codes 5380 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5381 GET_INST_OPCODE(ip) @ extract opcode from rINST 5382 SET_VREG(r0, r9) @ vAA<- r0 5383 GOTO_OPCODE(ip) @ jump to next instruction 5384 /* 10-13 instructions */ 5385 5386 5387/* ------------------------------ */ 5388 .balign 64 5389.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5390/* File: armv5te/OP_DIV_INT_2ADDR.S */ 5391/* File: armv5te/binop2addr.S */ 5392 /* 5393 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5394 * that specifies an instruction that performs "result = r0 op r1". 5395 * This could be an ARM instruction or a function call. (If the result 5396 * comes back in a register other than r0, you can override "result".) 5397 * 5398 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5399 * vCC (r1). Useful for integer division and modulus. 5400 * 5401 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5402 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5403 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5404 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5405 */ 5406 /* binop/2addr vA, vB */ 5407 mov r9, rINST, lsr #8 @ r9<- A+ 5408 mov r3, rINST, lsr #12 @ r3<- B 5409 and r9, r9, #15 5410 GET_VREG(r1, r3) @ r1<- vB 5411 GET_VREG(r0, r9) @ r0<- vA 5412 .if 1 5413 cmp r1, #0 @ is second operand zero? 5414 beq common_errDivideByZero 5415 .endif 5416 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5417 5418 @ optional op; may set condition codes 5419 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5420 GET_INST_OPCODE(ip) @ extract opcode from rINST 5421 SET_VREG(r0, r9) @ vAA<- r0 5422 GOTO_OPCODE(ip) @ jump to next instruction 5423 /* 10-13 instructions */ 5424 5425 5426/* ------------------------------ */ 5427 .balign 64 5428.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5429/* File: armv5te/OP_REM_INT_2ADDR.S */ 5430/* idivmod returns quotient in r0 and remainder in r1 */ 5431/* File: armv5te/binop2addr.S */ 5432 /* 5433 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5434 * that specifies an instruction that performs "result = r0 op r1". 5435 * This could be an ARM instruction or a function call. (If the result 5436 * comes back in a register other than r0, you can override "result".) 5437 * 5438 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5439 * vCC (r1). Useful for integer division and modulus. 5440 * 5441 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5442 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5443 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5444 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5445 */ 5446 /* binop/2addr vA, vB */ 5447 mov r9, rINST, lsr #8 @ r9<- A+ 5448 mov r3, rINST, lsr #12 @ r3<- B 5449 and r9, r9, #15 5450 GET_VREG(r1, r3) @ r1<- vB 5451 GET_VREG(r0, r9) @ r0<- vA 5452 .if 1 5453 cmp r1, #0 @ is second operand zero? 5454 beq common_errDivideByZero 5455 .endif 5456 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5457 5458 @ optional op; may set condition codes 5459 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5460 GET_INST_OPCODE(ip) @ extract opcode from rINST 5461 SET_VREG(r1, r9) @ vAA<- r1 5462 GOTO_OPCODE(ip) @ jump to next instruction 5463 /* 10-13 instructions */ 5464 5465 5466/* ------------------------------ */ 5467 .balign 64 5468.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5469/* File: armv5te/OP_AND_INT_2ADDR.S */ 5470/* File: armv5te/binop2addr.S */ 5471 /* 5472 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5473 * that specifies an instruction that performs "result = r0 op r1". 5474 * This could be an ARM instruction or a function call. (If the result 5475 * comes back in a register other than r0, you can override "result".) 5476 * 5477 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5478 * vCC (r1). Useful for integer division and modulus. 5479 * 5480 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5481 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5482 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5483 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5484 */ 5485 /* binop/2addr vA, vB */ 5486 mov r9, rINST, lsr #8 @ r9<- A+ 5487 mov r3, rINST, lsr #12 @ r3<- B 5488 and r9, r9, #15 5489 GET_VREG(r1, r3) @ r1<- vB 5490 GET_VREG(r0, r9) @ r0<- vA 5491 .if 0 5492 cmp r1, #0 @ is second operand zero? 5493 beq common_errDivideByZero 5494 .endif 5495 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5496 5497 @ optional op; may set condition codes 5498 and r0, r0, r1 @ r0<- op, r0-r3 changed 5499 GET_INST_OPCODE(ip) @ extract opcode from rINST 5500 SET_VREG(r0, r9) @ vAA<- r0 5501 GOTO_OPCODE(ip) @ jump to next instruction 5502 /* 10-13 instructions */ 5503 5504 5505/* ------------------------------ */ 5506 .balign 64 5507.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5508/* File: armv5te/OP_OR_INT_2ADDR.S */ 5509/* File: armv5te/binop2addr.S */ 5510 /* 5511 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5512 * that specifies an instruction that performs "result = r0 op r1". 5513 * This could be an ARM instruction or a function call. (If the result 5514 * comes back in a register other than r0, you can override "result".) 5515 * 5516 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5517 * vCC (r1). Useful for integer division and modulus. 5518 * 5519 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5520 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5521 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5522 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5523 */ 5524 /* binop/2addr vA, vB */ 5525 mov r9, rINST, lsr #8 @ r9<- A+ 5526 mov r3, rINST, lsr #12 @ r3<- B 5527 and r9, r9, #15 5528 GET_VREG(r1, r3) @ r1<- vB 5529 GET_VREG(r0, r9) @ r0<- vA 5530 .if 0 5531 cmp r1, #0 @ is second operand zero? 5532 beq common_errDivideByZero 5533 .endif 5534 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5535 5536 @ optional op; may set condition codes 5537 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5538 GET_INST_OPCODE(ip) @ extract opcode from rINST 5539 SET_VREG(r0, r9) @ vAA<- r0 5540 GOTO_OPCODE(ip) @ jump to next instruction 5541 /* 10-13 instructions */ 5542 5543 5544/* ------------------------------ */ 5545 .balign 64 5546.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5547/* File: armv5te/OP_XOR_INT_2ADDR.S */ 5548/* File: armv5te/binop2addr.S */ 5549 /* 5550 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5551 * that specifies an instruction that performs "result = r0 op r1". 5552 * This could be an ARM instruction or a function call. (If the result 5553 * comes back in a register other than r0, you can override "result".) 5554 * 5555 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5556 * vCC (r1). Useful for integer division and modulus. 5557 * 5558 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5559 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5560 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5561 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5562 */ 5563 /* binop/2addr vA, vB */ 5564 mov r9, rINST, lsr #8 @ r9<- A+ 5565 mov r3, rINST, lsr #12 @ r3<- B 5566 and r9, r9, #15 5567 GET_VREG(r1, r3) @ r1<- vB 5568 GET_VREG(r0, r9) @ r0<- vA 5569 .if 0 5570 cmp r1, #0 @ is second operand zero? 5571 beq common_errDivideByZero 5572 .endif 5573 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5574 5575 @ optional op; may set condition codes 5576 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5577 GET_INST_OPCODE(ip) @ extract opcode from rINST 5578 SET_VREG(r0, r9) @ vAA<- r0 5579 GOTO_OPCODE(ip) @ jump to next instruction 5580 /* 10-13 instructions */ 5581 5582 5583/* ------------------------------ */ 5584 .balign 64 5585.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5586/* File: armv5te/OP_SHL_INT_2ADDR.S */ 5587/* File: armv5te/binop2addr.S */ 5588 /* 5589 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5590 * that specifies an instruction that performs "result = r0 op r1". 5591 * This could be an ARM instruction or a function call. (If the result 5592 * comes back in a register other than r0, you can override "result".) 5593 * 5594 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5595 * vCC (r1). Useful for integer division and modulus. 5596 * 5597 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5598 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5599 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5600 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5601 */ 5602 /* binop/2addr vA, vB */ 5603 mov r9, rINST, lsr #8 @ r9<- A+ 5604 mov r3, rINST, lsr #12 @ r3<- B 5605 and r9, r9, #15 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, asl 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_SHR_INT_2ADDR: /* 0xb9 */ 5625/* File: armv5te/OP_SHR_INT_2ADDR.S */ 5626/* File: armv5te/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 r9, rINST, lsr #8 @ r9<- A+ 5643 mov r3, rINST, lsr #12 @ r3<- B 5644 and r9, r9, #15 5645 GET_VREG(r1, r3) @ r1<- vB 5646 GET_VREG(r0, r9) @ r0<- vA 5647 .if 0 5648 cmp r1, #0 @ is second operand zero? 5649 beq common_errDivideByZero 5650 .endif 5651 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5652 5653 and r1, r1, #31 @ optional op; may set condition codes 5654 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5655 GET_INST_OPCODE(ip) @ extract opcode from rINST 5656 SET_VREG(r0, r9) @ vAA<- r0 5657 GOTO_OPCODE(ip) @ jump to next instruction 5658 /* 10-13 instructions */ 5659 5660 5661/* ------------------------------ */ 5662 .balign 64 5663.L_OP_USHR_INT_2ADDR: /* 0xba */ 5664/* File: armv5te/OP_USHR_INT_2ADDR.S */ 5665/* File: armv5te/binop2addr.S */ 5666 /* 5667 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5668 * that specifies an instruction that performs "result = r0 op r1". 5669 * This could be an ARM instruction or a function call. (If the result 5670 * comes back in a register other than r0, you can override "result".) 5671 * 5672 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5673 * vCC (r1). Useful for integer division and modulus. 5674 * 5675 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5676 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5677 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5678 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5679 */ 5680 /* binop/2addr vA, vB */ 5681 mov r9, rINST, lsr #8 @ r9<- A+ 5682 mov r3, rINST, lsr #12 @ r3<- B 5683 and r9, r9, #15 5684 GET_VREG(r1, r3) @ r1<- vB 5685 GET_VREG(r0, r9) @ r0<- vA 5686 .if 0 5687 cmp r1, #0 @ is second operand zero? 5688 beq common_errDivideByZero 5689 .endif 5690 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5691 5692 and r1, r1, #31 @ optional op; may set condition codes 5693 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5694 GET_INST_OPCODE(ip) @ extract opcode from rINST 5695 SET_VREG(r0, r9) @ vAA<- r0 5696 GOTO_OPCODE(ip) @ jump to next instruction 5697 /* 10-13 instructions */ 5698 5699 5700/* ------------------------------ */ 5701 .balign 64 5702.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5703/* File: armv5te/OP_ADD_LONG_2ADDR.S */ 5704/* File: armv5te/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 r9, rINST, lsr #8 @ r9<- A+ 5721 mov r1, rINST, lsr #12 @ r1<- B 5722 and r9, r9, #15 5723 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5724 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5725 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5726 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5727 .if 0 5728 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5729 beq common_errDivideByZero 5730 .endif 5731 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5732 5733 adds r0, r0, r2 @ optional op; may set condition codes 5734 adc r1, r1, r3 @ result<- op, r0-r3 changed 5735 GET_INST_OPCODE(ip) @ extract opcode from rINST 5736 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5737 GOTO_OPCODE(ip) @ jump to next instruction 5738 /* 12-15 instructions */ 5739 5740 5741/* ------------------------------ */ 5742 .balign 64 5743.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5744/* File: armv5te/OP_SUB_LONG_2ADDR.S */ 5745/* File: armv5te/binopWide2addr.S */ 5746 /* 5747 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5748 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5749 * This could be an ARM instruction or a function call. (If the result 5750 * comes back in a register other than r0, you can override "result".) 5751 * 5752 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5753 * vCC (r1). Useful for integer division and modulus. 5754 * 5755 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5756 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5757 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5758 * rem-double/2addr 5759 */ 5760 /* binop/2addr vA, vB */ 5761 mov r9, rINST, lsr #8 @ r9<- A+ 5762 mov r1, rINST, lsr #12 @ r1<- B 5763 and r9, r9, #15 5764 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5765 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5766 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5767 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5768 .if 0 5769 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5770 beq common_errDivideByZero 5771 .endif 5772 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5773 5774 subs r0, r0, r2 @ optional op; may set condition codes 5775 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5776 GET_INST_OPCODE(ip) @ extract opcode from rINST 5777 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5778 GOTO_OPCODE(ip) @ jump to next instruction 5779 /* 12-15 instructions */ 5780 5781 5782/* ------------------------------ */ 5783 .balign 64 5784.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 5785/* File: armv5te/OP_MUL_LONG_2ADDR.S */ 5786 /* 5787 * Signed 64-bit integer multiply, "/2addr" version. 5788 * 5789 * See OP_MUL_LONG for an explanation. 5790 * 5791 * We get a little tight on registers, so to avoid looking up &fp[A] 5792 * again we stuff it into rINST. 5793 */ 5794 /* mul-long/2addr vA, vB */ 5795 mov r9, rINST, lsr #8 @ r9<- A+ 5796 mov r1, rINST, lsr #12 @ r1<- B 5797 and r9, r9, #15 5798 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5799 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 5800 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5801 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 5802 mul ip, r2, r1 @ ip<- ZxW 5803 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 5804 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 5805 mov r0, rINST @ r0<- &fp[A] (free up rINST) 5806 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5807 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 5808 GET_INST_OPCODE(ip) @ extract opcode from rINST 5809 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 5810 GOTO_OPCODE(ip) @ jump to next instruction 5811 5812/* ------------------------------ */ 5813 .balign 64 5814.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 5815/* File: armv5te/OP_DIV_LONG_2ADDR.S */ 5816/* File: armv5te/binopWide2addr.S */ 5817 /* 5818 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5819 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5820 * This could be an ARM instruction or a function call. (If the result 5821 * comes back in a register other than r0, you can override "result".) 5822 * 5823 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5824 * vCC (r1). Useful for integer division and modulus. 5825 * 5826 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5827 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5828 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5829 * rem-double/2addr 5830 */ 5831 /* binop/2addr vA, vB */ 5832 mov r9, rINST, lsr #8 @ r9<- A+ 5833 mov r1, rINST, lsr #12 @ r1<- B 5834 and r9, r9, #15 5835 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5836 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5837 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5838 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5839 .if 1 5840 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5841 beq common_errDivideByZero 5842 .endif 5843 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5844 5845 @ optional op; may set condition codes 5846 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5847 GET_INST_OPCODE(ip) @ extract opcode from rINST 5848 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5849 GOTO_OPCODE(ip) @ jump to next instruction 5850 /* 12-15 instructions */ 5851 5852 5853/* ------------------------------ */ 5854 .balign 64 5855.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5856/* File: armv5te/OP_REM_LONG_2ADDR.S */ 5857/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 5858/* File: armv5te/binopWide2addr.S */ 5859 /* 5860 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5861 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5862 * This could be an ARM instruction or a function call. (If the result 5863 * comes back in a register other than r0, you can override "result".) 5864 * 5865 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5866 * vCC (r1). Useful for integer division and modulus. 5867 * 5868 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5869 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5870 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5871 * rem-double/2addr 5872 */ 5873 /* binop/2addr vA, vB */ 5874 mov r9, rINST, lsr #8 @ r9<- A+ 5875 mov r1, rINST, lsr #12 @ r1<- B 5876 and r9, r9, #15 5877 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5878 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5879 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5880 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5881 .if 1 5882 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5883 beq common_errDivideByZero 5884 .endif 5885 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5886 5887 @ optional op; may set condition codes 5888 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5889 GET_INST_OPCODE(ip) @ extract opcode from rINST 5890 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 5891 GOTO_OPCODE(ip) @ jump to next instruction 5892 /* 12-15 instructions */ 5893 5894 5895/* ------------------------------ */ 5896 .balign 64 5897.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 5898/* File: armv5te/OP_AND_LONG_2ADDR.S */ 5899/* File: armv5te/binopWide2addr.S */ 5900 /* 5901 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5902 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5903 * This could be an ARM instruction or a function call. (If the result 5904 * comes back in a register other than r0, you can override "result".) 5905 * 5906 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5907 * vCC (r1). Useful for integer division and modulus. 5908 * 5909 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5910 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5911 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5912 * rem-double/2addr 5913 */ 5914 /* binop/2addr vA, vB */ 5915 mov r9, rINST, lsr #8 @ r9<- A+ 5916 mov r1, rINST, lsr #12 @ r1<- B 5917 and r9, r9, #15 5918 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5919 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5920 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5921 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5922 .if 0 5923 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5924 beq common_errDivideByZero 5925 .endif 5926 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5927 5928 and r0, r0, r2 @ optional op; may set condition codes 5929 and r1, r1, r3 @ result<- op, r0-r3 changed 5930 GET_INST_OPCODE(ip) @ extract opcode from rINST 5931 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5932 GOTO_OPCODE(ip) @ jump to next instruction 5933 /* 12-15 instructions */ 5934 5935 5936/* ------------------------------ */ 5937 .balign 64 5938.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 5939/* File: armv5te/OP_OR_LONG_2ADDR.S */ 5940/* File: armv5te/binopWide2addr.S */ 5941 /* 5942 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5943 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5944 * This could be an ARM instruction or a function call. (If the result 5945 * comes back in a register other than r0, you can override "result".) 5946 * 5947 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5948 * vCC (r1). Useful for integer division and modulus. 5949 * 5950 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5951 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5952 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5953 * rem-double/2addr 5954 */ 5955 /* binop/2addr vA, vB */ 5956 mov r9, rINST, lsr #8 @ r9<- A+ 5957 mov r1, rINST, lsr #12 @ r1<- B 5958 and r9, r9, #15 5959 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5960 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5961 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5962 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5963 .if 0 5964 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5965 beq common_errDivideByZero 5966 .endif 5967 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5968 5969 orr r0, r0, r2 @ optional op; may set condition codes 5970 orr r1, r1, r3 @ result<- op, r0-r3 changed 5971 GET_INST_OPCODE(ip) @ extract opcode from rINST 5972 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5973 GOTO_OPCODE(ip) @ jump to next instruction 5974 /* 12-15 instructions */ 5975 5976 5977/* ------------------------------ */ 5978 .balign 64 5979.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 5980/* File: armv5te/OP_XOR_LONG_2ADDR.S */ 5981/* File: armv5te/binopWide2addr.S */ 5982 /* 5983 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5984 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5985 * This could be an ARM instruction or a function call. (If the result 5986 * comes back in a register other than r0, you can override "result".) 5987 * 5988 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5989 * vCC (r1). Useful for integer division and modulus. 5990 * 5991 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5992 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5993 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5994 * rem-double/2addr 5995 */ 5996 /* binop/2addr vA, vB */ 5997 mov r9, rINST, lsr #8 @ r9<- A+ 5998 mov r1, rINST, lsr #12 @ r1<- B 5999 and r9, r9, #15 6000 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6001 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6002 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6003 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6004 .if 0 6005 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6006 beq common_errDivideByZero 6007 .endif 6008 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6009 6010 eor r0, r0, r2 @ optional op; may set condition codes 6011 eor r1, r1, r3 @ result<- op, r0-r3 changed 6012 GET_INST_OPCODE(ip) @ extract opcode from rINST 6013 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6014 GOTO_OPCODE(ip) @ jump to next instruction 6015 /* 12-15 instructions */ 6016 6017 6018/* ------------------------------ */ 6019 .balign 64 6020.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 6021/* File: armv5te/OP_SHL_LONG_2ADDR.S */ 6022 /* 6023 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6024 * 32-bit shift distance. 6025 */ 6026 /* shl-long/2addr vA, vB */ 6027 mov r9, rINST, lsr #8 @ r9<- A+ 6028 mov r3, rINST, lsr #12 @ r3<- B 6029 and r9, r9, #15 6030 GET_VREG(r2, r3) @ r2<- vB 6031 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6032 and r2, r2, #63 @ r2<- r2 & 0x3f 6033 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6034 6035 mov r1, r1, asl r2 @ r1<- r1 << r2 6036 rsb r3, r2, #32 @ r3<- 32 - r2 6037 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 6038 subs ip, r2, #32 @ ip<- r2 - 32 6039 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6040 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 6041 mov r0, r0, asl r2 @ r0<- r0 << r2 6042 b .LOP_SHL_LONG_2ADDR_finish 6043 6044/* ------------------------------ */ 6045 .balign 64 6046.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 6047/* File: armv5te/OP_SHR_LONG_2ADDR.S */ 6048 /* 6049 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6050 * 32-bit shift distance. 6051 */ 6052 /* shr-long/2addr vA, vB */ 6053 mov r9, rINST, lsr #8 @ r9<- A+ 6054 mov r3, rINST, lsr #12 @ r3<- B 6055 and r9, r9, #15 6056 GET_VREG(r2, r3) @ r2<- vB 6057 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6058 and r2, r2, #63 @ r2<- r2 & 0x3f 6059 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6060 6061 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6062 rsb r3, r2, #32 @ r3<- 32 - r2 6063 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6064 subs ip, r2, #32 @ ip<- r2 - 32 6065 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6066 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6067 mov r1, r1, asr r2 @ r1<- r1 >> r2 6068 b .LOP_SHR_LONG_2ADDR_finish 6069 6070/* ------------------------------ */ 6071 .balign 64 6072.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6073/* File: armv5te/OP_USHR_LONG_2ADDR.S */ 6074 /* 6075 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6076 * 32-bit shift distance. 6077 */ 6078 /* ushr-long/2addr vA, vB */ 6079 mov r9, rINST, lsr #8 @ r9<- A+ 6080 mov r3, rINST, lsr #12 @ r3<- B 6081 and r9, r9, #15 6082 GET_VREG(r2, r3) @ r2<- vB 6083 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6084 and r2, r2, #63 @ r2<- r2 & 0x3f 6085 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6086 6087 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6088 rsb r3, r2, #32 @ r3<- 32 - r2 6089 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6090 subs ip, r2, #32 @ ip<- r2 - 32 6091 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6092 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6093 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6094 b .LOP_USHR_LONG_2ADDR_finish 6095 6096/* ------------------------------ */ 6097 .balign 64 6098.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6099/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */ 6100/* File: arm-vfp/fbinop2addr.S */ 6101 /* 6102 * Generic 32-bit floating point "/2addr" binary operation. Provide 6103 * an "instr" line that specifies an instruction that performs 6104 * "s2 = s0 op s1". 6105 * 6106 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6107 */ 6108 /* binop/2addr vA, vB */ 6109 mov r3, rINST, lsr #12 @ r3<- B 6110 mov r9, rINST, lsr #8 @ r9<- A+ 6111 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6112 and r9, r9, #15 @ r9<- A 6113 flds s1, [r3] @ s1<- vB 6114 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6115 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6116 flds s0, [r9] @ s0<- vA 6117 6118 fadds s2, s0, s1 @ s2<- op 6119 GET_INST_OPCODE(ip) @ extract opcode from rINST 6120 fsts s2, [r9] @ vAA<- s2 6121 GOTO_OPCODE(ip) @ jump to next instruction 6122 6123 6124/* ------------------------------ */ 6125 .balign 64 6126.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6127/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */ 6128/* File: arm-vfp/fbinop2addr.S */ 6129 /* 6130 * Generic 32-bit floating point "/2addr" binary operation. Provide 6131 * an "instr" line that specifies an instruction that performs 6132 * "s2 = s0 op s1". 6133 * 6134 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6135 */ 6136 /* binop/2addr vA, vB */ 6137 mov r3, rINST, lsr #12 @ r3<- B 6138 mov r9, rINST, lsr #8 @ r9<- A+ 6139 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6140 and r9, r9, #15 @ r9<- A 6141 flds s1, [r3] @ s1<- vB 6142 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6143 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6144 flds s0, [r9] @ s0<- vA 6145 6146 fsubs s2, s0, s1 @ s2<- op 6147 GET_INST_OPCODE(ip) @ extract opcode from rINST 6148 fsts s2, [r9] @ vAA<- s2 6149 GOTO_OPCODE(ip) @ jump to next instruction 6150 6151 6152/* ------------------------------ */ 6153 .balign 64 6154.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6155/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */ 6156/* File: arm-vfp/fbinop2addr.S */ 6157 /* 6158 * Generic 32-bit floating point "/2addr" binary operation. Provide 6159 * an "instr" line that specifies an instruction that performs 6160 * "s2 = s0 op s1". 6161 * 6162 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6163 */ 6164 /* binop/2addr vA, vB */ 6165 mov r3, rINST, lsr #12 @ r3<- B 6166 mov r9, rINST, lsr #8 @ r9<- A+ 6167 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6168 and r9, r9, #15 @ r9<- A 6169 flds s1, [r3] @ s1<- vB 6170 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6171 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6172 flds s0, [r9] @ s0<- vA 6173 6174 fmuls s2, s0, s1 @ s2<- op 6175 GET_INST_OPCODE(ip) @ extract opcode from rINST 6176 fsts s2, [r9] @ vAA<- s2 6177 GOTO_OPCODE(ip) @ jump to next instruction 6178 6179 6180/* ------------------------------ */ 6181 .balign 64 6182.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6183/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */ 6184/* File: arm-vfp/fbinop2addr.S */ 6185 /* 6186 * Generic 32-bit floating point "/2addr" binary operation. Provide 6187 * an "instr" line that specifies an instruction that performs 6188 * "s2 = s0 op s1". 6189 * 6190 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6191 */ 6192 /* binop/2addr vA, vB */ 6193 mov r3, rINST, lsr #12 @ r3<- B 6194 mov r9, rINST, lsr #8 @ r9<- A+ 6195 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6196 and r9, r9, #15 @ r9<- A 6197 flds s1, [r3] @ s1<- vB 6198 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6199 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6200 flds s0, [r9] @ s0<- vA 6201 6202 fdivs s2, s0, s1 @ s2<- op 6203 GET_INST_OPCODE(ip) @ extract opcode from rINST 6204 fsts s2, [r9] @ vAA<- s2 6205 GOTO_OPCODE(ip) @ jump to next instruction 6206 6207 6208/* ------------------------------ */ 6209 .balign 64 6210.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6211/* File: armv5te/OP_REM_FLOAT_2ADDR.S */ 6212/* EABI doesn't define a float remainder function, but libm does */ 6213/* File: armv5te/binop2addr.S */ 6214 /* 6215 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6216 * that specifies an instruction that performs "result = r0 op r1". 6217 * This could be an ARM instruction or a function call. (If the result 6218 * comes back in a register other than r0, you can override "result".) 6219 * 6220 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6221 * vCC (r1). Useful for integer division and modulus. 6222 * 6223 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6224 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6225 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6226 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6227 */ 6228 /* binop/2addr vA, vB */ 6229 mov r9, rINST, lsr #8 @ r9<- A+ 6230 mov r3, rINST, lsr #12 @ r3<- B 6231 and r9, r9, #15 6232 GET_VREG(r1, r3) @ r1<- vB 6233 GET_VREG(r0, r9) @ r0<- vA 6234 .if 0 6235 cmp r1, #0 @ is second operand zero? 6236 beq common_errDivideByZero 6237 .endif 6238 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6239 6240 @ optional op; may set condition codes 6241 bl fmodf @ r0<- op, r0-r3 changed 6242 GET_INST_OPCODE(ip) @ extract opcode from rINST 6243 SET_VREG(r0, r9) @ vAA<- r0 6244 GOTO_OPCODE(ip) @ jump to next instruction 6245 /* 10-13 instructions */ 6246 6247 6248/* ------------------------------ */ 6249 .balign 64 6250.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6251/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */ 6252/* File: arm-vfp/fbinopWide2addr.S */ 6253 /* 6254 * Generic 64-bit floating point "/2addr" binary operation. Provide 6255 * an "instr" line that specifies an instruction that performs 6256 * "d2 = d0 op d1". 6257 * 6258 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6259 * div-double/2addr 6260 */ 6261 /* binop/2addr vA, vB */ 6262 mov r3, rINST, lsr #12 @ r3<- B 6263 mov r9, rINST, lsr #8 @ r9<- A+ 6264 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6265 and r9, r9, #15 @ r9<- A 6266 fldd d1, [r3] @ d1<- vB 6267 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6268 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6269 fldd d0, [r9] @ d0<- vA 6270 6271 faddd d2, d0, d1 @ d2<- op 6272 GET_INST_OPCODE(ip) @ extract opcode from rINST 6273 fstd d2, [r9] @ vAA<- d2 6274 GOTO_OPCODE(ip) @ jump to next instruction 6275 6276 6277/* ------------------------------ */ 6278 .balign 64 6279.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6280/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */ 6281/* File: arm-vfp/fbinopWide2addr.S */ 6282 /* 6283 * Generic 64-bit floating point "/2addr" binary operation. Provide 6284 * an "instr" line that specifies an instruction that performs 6285 * "d2 = d0 op d1". 6286 * 6287 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6288 * div-double/2addr 6289 */ 6290 /* binop/2addr vA, vB */ 6291 mov r3, rINST, lsr #12 @ r3<- B 6292 mov r9, rINST, lsr #8 @ r9<- A+ 6293 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6294 and r9, r9, #15 @ r9<- A 6295 fldd d1, [r3] @ d1<- vB 6296 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6297 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6298 fldd d0, [r9] @ d0<- vA 6299 6300 fsubd d2, d0, d1 @ d2<- op 6301 GET_INST_OPCODE(ip) @ extract opcode from rINST 6302 fstd d2, [r9] @ vAA<- d2 6303 GOTO_OPCODE(ip) @ jump to next instruction 6304 6305 6306/* ------------------------------ */ 6307 .balign 64 6308.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6309/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */ 6310/* File: arm-vfp/fbinopWide2addr.S */ 6311 /* 6312 * Generic 64-bit floating point "/2addr" binary operation. Provide 6313 * an "instr" line that specifies an instruction that performs 6314 * "d2 = d0 op d1". 6315 * 6316 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6317 * div-double/2addr 6318 */ 6319 /* binop/2addr vA, vB */ 6320 mov r3, rINST, lsr #12 @ r3<- B 6321 mov r9, rINST, lsr #8 @ r9<- A+ 6322 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6323 and r9, r9, #15 @ r9<- A 6324 fldd d1, [r3] @ d1<- vB 6325 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6326 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6327 fldd d0, [r9] @ d0<- vA 6328 6329 fmuld d2, d0, d1 @ d2<- op 6330 GET_INST_OPCODE(ip) @ extract opcode from rINST 6331 fstd d2, [r9] @ vAA<- d2 6332 GOTO_OPCODE(ip) @ jump to next instruction 6333 6334 6335/* ------------------------------ */ 6336 .balign 64 6337.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6338/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */ 6339/* File: arm-vfp/fbinopWide2addr.S */ 6340 /* 6341 * Generic 64-bit floating point "/2addr" binary operation. Provide 6342 * an "instr" line that specifies an instruction that performs 6343 * "d2 = d0 op d1". 6344 * 6345 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6346 * div-double/2addr 6347 */ 6348 /* binop/2addr vA, vB */ 6349 mov r3, rINST, lsr #12 @ r3<- B 6350 mov r9, rINST, lsr #8 @ r9<- A+ 6351 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6352 and r9, r9, #15 @ r9<- A 6353 fldd d1, [r3] @ d1<- vB 6354 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6355 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6356 fldd d0, [r9] @ d0<- vA 6357 6358 fdivd d2, d0, d1 @ d2<- op 6359 GET_INST_OPCODE(ip) @ extract opcode from rINST 6360 fstd d2, [r9] @ vAA<- d2 6361 GOTO_OPCODE(ip) @ jump to next instruction 6362 6363 6364/* ------------------------------ */ 6365 .balign 64 6366.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6367/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */ 6368/* EABI doesn't define a double remainder function, but libm does */ 6369/* File: armv5te/binopWide2addr.S */ 6370 /* 6371 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6372 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6373 * This could be an ARM instruction or a function call. (If the result 6374 * comes back in a register other than r0, you can override "result".) 6375 * 6376 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6377 * vCC (r1). Useful for integer division and modulus. 6378 * 6379 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6380 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6381 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6382 * rem-double/2addr 6383 */ 6384 /* binop/2addr vA, vB */ 6385 mov r9, rINST, lsr #8 @ r9<- A+ 6386 mov r1, rINST, lsr #12 @ r1<- B 6387 and r9, r9, #15 6388 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6389 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6390 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6391 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6392 .if 0 6393 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6394 beq common_errDivideByZero 6395 .endif 6396 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6397 6398 @ optional op; may set condition codes 6399 bl fmod @ result<- op, r0-r3 changed 6400 GET_INST_OPCODE(ip) @ extract opcode from rINST 6401 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6402 GOTO_OPCODE(ip) @ jump to next instruction 6403 /* 12-15 instructions */ 6404 6405 6406/* ------------------------------ */ 6407 .balign 64 6408.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6409/* File: armv5te/OP_ADD_INT_LIT16.S */ 6410/* File: armv5te/binopLit16.S */ 6411 /* 6412 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6413 * that specifies an instruction that performs "result = r0 op r1". 6414 * This could be an ARM instruction or a function call. (If the result 6415 * comes back in a register other than r0, you can override "result".) 6416 * 6417 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6418 * vCC (r1). Useful for integer division and modulus. 6419 * 6420 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6421 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6422 */ 6423 /* binop/lit16 vA, vB, #+CCCC */ 6424 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6425 mov r2, rINST, lsr #12 @ r2<- B 6426 mov r9, rINST, lsr #8 @ r9<- A+ 6427 GET_VREG(r0, r2) @ r0<- vB 6428 and r9, r9, #15 6429 .if 0 6430 cmp r1, #0 @ is second operand zero? 6431 beq common_errDivideByZero 6432 .endif 6433 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6434 6435 add r0, r0, r1 @ r0<- op, r0-r3 changed 6436 GET_INST_OPCODE(ip) @ extract opcode from rINST 6437 SET_VREG(r0, r9) @ vAA<- r0 6438 GOTO_OPCODE(ip) @ jump to next instruction 6439 /* 10-13 instructions */ 6440 6441 6442/* ------------------------------ */ 6443 .balign 64 6444.L_OP_RSUB_INT: /* 0xd1 */ 6445/* File: armv5te/OP_RSUB_INT.S */ 6446/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6447/* File: armv5te/binopLit16.S */ 6448 /* 6449 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6450 * that specifies an instruction that performs "result = r0 op r1". 6451 * This could be an ARM instruction or a function call. (If the result 6452 * comes back in a register other than r0, you can override "result".) 6453 * 6454 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6455 * vCC (r1). Useful for integer division and modulus. 6456 * 6457 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6458 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6459 */ 6460 /* binop/lit16 vA, vB, #+CCCC */ 6461 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6462 mov r2, rINST, lsr #12 @ r2<- B 6463 mov r9, rINST, lsr #8 @ r9<- A+ 6464 GET_VREG(r0, r2) @ r0<- vB 6465 and r9, r9, #15 6466 .if 0 6467 cmp r1, #0 @ is second operand zero? 6468 beq common_errDivideByZero 6469 .endif 6470 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6471 6472 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6473 GET_INST_OPCODE(ip) @ extract opcode from rINST 6474 SET_VREG(r0, r9) @ vAA<- r0 6475 GOTO_OPCODE(ip) @ jump to next instruction 6476 /* 10-13 instructions */ 6477 6478 6479/* ------------------------------ */ 6480 .balign 64 6481.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6482/* File: armv5te/OP_MUL_INT_LIT16.S */ 6483/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6484/* File: armv5te/binopLit16.S */ 6485 /* 6486 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6487 * that specifies an instruction that performs "result = r0 op r1". 6488 * This could be an ARM instruction or a function call. (If the result 6489 * comes back in a register other than r0, you can override "result".) 6490 * 6491 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6492 * vCC (r1). Useful for integer division and modulus. 6493 * 6494 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6495 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6496 */ 6497 /* binop/lit16 vA, vB, #+CCCC */ 6498 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6499 mov r2, rINST, lsr #12 @ r2<- B 6500 mov r9, rINST, lsr #8 @ r9<- A+ 6501 GET_VREG(r0, r2) @ r0<- vB 6502 and r9, r9, #15 6503 .if 0 6504 cmp r1, #0 @ is second operand zero? 6505 beq common_errDivideByZero 6506 .endif 6507 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6508 6509 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6510 GET_INST_OPCODE(ip) @ extract opcode from rINST 6511 SET_VREG(r0, r9) @ vAA<- r0 6512 GOTO_OPCODE(ip) @ jump to next instruction 6513 /* 10-13 instructions */ 6514 6515 6516/* ------------------------------ */ 6517 .balign 64 6518.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6519/* File: armv5te/OP_DIV_INT_LIT16.S */ 6520/* File: armv5te/binopLit16.S */ 6521 /* 6522 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6523 * that specifies an instruction that performs "result = r0 op r1". 6524 * This could be an ARM instruction or a function call. (If the result 6525 * comes back in a register other than r0, you can override "result".) 6526 * 6527 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6528 * vCC (r1). Useful for integer division and modulus. 6529 * 6530 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6531 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6532 */ 6533 /* binop/lit16 vA, vB, #+CCCC */ 6534 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6535 mov r2, rINST, lsr #12 @ r2<- B 6536 mov r9, rINST, lsr #8 @ r9<- A+ 6537 GET_VREG(r0, r2) @ r0<- vB 6538 and r9, r9, #15 6539 .if 1 6540 cmp r1, #0 @ is second operand zero? 6541 beq common_errDivideByZero 6542 .endif 6543 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6544 6545 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6546 GET_INST_OPCODE(ip) @ extract opcode from rINST 6547 SET_VREG(r0, r9) @ vAA<- r0 6548 GOTO_OPCODE(ip) @ jump to next instruction 6549 /* 10-13 instructions */ 6550 6551 6552/* ------------------------------ */ 6553 .balign 64 6554.L_OP_REM_INT_LIT16: /* 0xd4 */ 6555/* File: armv5te/OP_REM_INT_LIT16.S */ 6556/* idivmod returns quotient in r0 and remainder in r1 */ 6557/* File: armv5te/binopLit16.S */ 6558 /* 6559 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6560 * that specifies an instruction that performs "result = r0 op r1". 6561 * This could be an ARM instruction or a function call. (If the result 6562 * comes back in a register other than r0, you can override "result".) 6563 * 6564 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6565 * vCC (r1). Useful for integer division and modulus. 6566 * 6567 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6568 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6569 */ 6570 /* binop/lit16 vA, vB, #+CCCC */ 6571 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6572 mov r2, rINST, lsr #12 @ r2<- B 6573 mov r9, rINST, lsr #8 @ r9<- A+ 6574 GET_VREG(r0, r2) @ r0<- vB 6575 and r9, r9, #15 6576 .if 1 6577 cmp r1, #0 @ is second operand zero? 6578 beq common_errDivideByZero 6579 .endif 6580 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6581 6582 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6583 GET_INST_OPCODE(ip) @ extract opcode from rINST 6584 SET_VREG(r1, r9) @ vAA<- r1 6585 GOTO_OPCODE(ip) @ jump to next instruction 6586 /* 10-13 instructions */ 6587 6588 6589/* ------------------------------ */ 6590 .balign 64 6591.L_OP_AND_INT_LIT16: /* 0xd5 */ 6592/* File: armv5te/OP_AND_INT_LIT16.S */ 6593/* File: armv5te/binopLit16.S */ 6594 /* 6595 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6596 * that specifies an instruction that performs "result = r0 op r1". 6597 * This could be an ARM instruction or a function call. (If the result 6598 * comes back in a register other than r0, you can override "result".) 6599 * 6600 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6601 * vCC (r1). Useful for integer division and modulus. 6602 * 6603 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6604 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6605 */ 6606 /* binop/lit16 vA, vB, #+CCCC */ 6607 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6608 mov r2, rINST, lsr #12 @ r2<- B 6609 mov r9, rINST, lsr #8 @ r9<- A+ 6610 GET_VREG(r0, r2) @ r0<- vB 6611 and r9, r9, #15 6612 .if 0 6613 cmp r1, #0 @ is second operand zero? 6614 beq common_errDivideByZero 6615 .endif 6616 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6617 6618 and r0, r0, r1 @ r0<- op, r0-r3 changed 6619 GET_INST_OPCODE(ip) @ extract opcode from rINST 6620 SET_VREG(r0, r9) @ vAA<- r0 6621 GOTO_OPCODE(ip) @ jump to next instruction 6622 /* 10-13 instructions */ 6623 6624 6625/* ------------------------------ */ 6626 .balign 64 6627.L_OP_OR_INT_LIT16: /* 0xd6 */ 6628/* File: armv5te/OP_OR_INT_LIT16.S */ 6629/* File: armv5te/binopLit16.S */ 6630 /* 6631 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6632 * that specifies an instruction that performs "result = r0 op r1". 6633 * This could be an ARM instruction or a function call. (If the result 6634 * comes back in a register other than r0, you can override "result".) 6635 * 6636 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6637 * vCC (r1). Useful for integer division and modulus. 6638 * 6639 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6640 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6641 */ 6642 /* binop/lit16 vA, vB, #+CCCC */ 6643 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6644 mov r2, rINST, lsr #12 @ r2<- B 6645 mov r9, rINST, lsr #8 @ r9<- A+ 6646 GET_VREG(r0, r2) @ r0<- vB 6647 and r9, r9, #15 6648 .if 0 6649 cmp r1, #0 @ is second operand zero? 6650 beq common_errDivideByZero 6651 .endif 6652 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6653 6654 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6655 GET_INST_OPCODE(ip) @ extract opcode from rINST 6656 SET_VREG(r0, r9) @ vAA<- r0 6657 GOTO_OPCODE(ip) @ jump to next instruction 6658 /* 10-13 instructions */ 6659 6660 6661/* ------------------------------ */ 6662 .balign 64 6663.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6664/* File: armv5te/OP_XOR_INT_LIT16.S */ 6665/* File: armv5te/binopLit16.S */ 6666 /* 6667 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6668 * that specifies an instruction that performs "result = r0 op r1". 6669 * This could be an ARM instruction or a function call. (If the result 6670 * comes back in a register other than r0, you can override "result".) 6671 * 6672 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6673 * vCC (r1). Useful for integer division and modulus. 6674 * 6675 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6676 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6677 */ 6678 /* binop/lit16 vA, vB, #+CCCC */ 6679 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6680 mov r2, rINST, lsr #12 @ r2<- B 6681 mov r9, rINST, lsr #8 @ r9<- A+ 6682 GET_VREG(r0, r2) @ r0<- vB 6683 and r9, r9, #15 6684 .if 0 6685 cmp r1, #0 @ is second operand zero? 6686 beq common_errDivideByZero 6687 .endif 6688 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6689 6690 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6691 GET_INST_OPCODE(ip) @ extract opcode from rINST 6692 SET_VREG(r0, r9) @ vAA<- r0 6693 GOTO_OPCODE(ip) @ jump to next instruction 6694 /* 10-13 instructions */ 6695 6696 6697/* ------------------------------ */ 6698 .balign 64 6699.L_OP_ADD_INT_LIT8: /* 0xd8 */ 6700/* File: armv5te/OP_ADD_INT_LIT8.S */ 6701/* File: armv5te/binopLit8.S */ 6702 /* 6703 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6704 * that specifies an instruction that performs "result = r0 op r1". 6705 * This could be an ARM instruction or a function call. (If the result 6706 * comes back in a register other than r0, you can override "result".) 6707 * 6708 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6709 * vCC (r1). Useful for integer division and modulus. 6710 * 6711 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6712 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6713 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6714 */ 6715 /* binop/lit8 vAA, vBB, #+CC */ 6716 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6717 mov r9, rINST, lsr #8 @ r9<- AA 6718 and r2, r3, #255 @ r2<- BB 6719 GET_VREG(r0, r2) @ r0<- vBB 6720 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6721 .if 0 6722 @cmp r1, #0 @ is second operand zero? 6723 beq common_errDivideByZero 6724 .endif 6725 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6726 6727 @ optional op; may set condition codes 6728 add r0, r0, r1 @ r0<- op, r0-r3 changed 6729 GET_INST_OPCODE(ip) @ extract opcode from rINST 6730 SET_VREG(r0, r9) @ vAA<- r0 6731 GOTO_OPCODE(ip) @ jump to next instruction 6732 /* 10-12 instructions */ 6733 6734 6735/* ------------------------------ */ 6736 .balign 64 6737.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 6738/* File: armv5te/OP_RSUB_INT_LIT8.S */ 6739/* File: armv5te/binopLit8.S */ 6740 /* 6741 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6742 * that specifies an instruction that performs "result = r0 op r1". 6743 * This could be an ARM instruction or a function call. (If the result 6744 * comes back in a register other than r0, you can override "result".) 6745 * 6746 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6747 * vCC (r1). Useful for integer division and modulus. 6748 * 6749 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6750 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6751 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6752 */ 6753 /* binop/lit8 vAA, vBB, #+CC */ 6754 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6755 mov r9, rINST, lsr #8 @ r9<- AA 6756 and r2, r3, #255 @ r2<- BB 6757 GET_VREG(r0, r2) @ r0<- vBB 6758 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6759 .if 0 6760 @cmp r1, #0 @ is second operand zero? 6761 beq common_errDivideByZero 6762 .endif 6763 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6764 6765 @ optional op; may set condition codes 6766 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6767 GET_INST_OPCODE(ip) @ extract opcode from rINST 6768 SET_VREG(r0, r9) @ vAA<- r0 6769 GOTO_OPCODE(ip) @ jump to next instruction 6770 /* 10-12 instructions */ 6771 6772 6773/* ------------------------------ */ 6774 .balign 64 6775.L_OP_MUL_INT_LIT8: /* 0xda */ 6776/* File: armv5te/OP_MUL_INT_LIT8.S */ 6777/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6778/* File: armv5te/binopLit8.S */ 6779 /* 6780 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6781 * that specifies an instruction that performs "result = r0 op r1". 6782 * This could be an ARM instruction or a function call. (If the result 6783 * comes back in a register other than r0, you can override "result".) 6784 * 6785 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6786 * vCC (r1). Useful for integer division and modulus. 6787 * 6788 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6789 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6790 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6791 */ 6792 /* binop/lit8 vAA, vBB, #+CC */ 6793 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6794 mov r9, rINST, lsr #8 @ r9<- AA 6795 and r2, r3, #255 @ r2<- BB 6796 GET_VREG(r0, r2) @ r0<- vBB 6797 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6798 .if 0 6799 @cmp r1, #0 @ is second operand zero? 6800 beq common_errDivideByZero 6801 .endif 6802 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6803 6804 @ optional op; may set condition codes 6805 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6806 GET_INST_OPCODE(ip) @ extract opcode from rINST 6807 SET_VREG(r0, r9) @ vAA<- r0 6808 GOTO_OPCODE(ip) @ jump to next instruction 6809 /* 10-12 instructions */ 6810 6811 6812/* ------------------------------ */ 6813 .balign 64 6814.L_OP_DIV_INT_LIT8: /* 0xdb */ 6815/* File: armv5te/OP_DIV_INT_LIT8.S */ 6816/* File: armv5te/binopLit8.S */ 6817 /* 6818 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6819 * that specifies an instruction that performs "result = r0 op r1". 6820 * This could be an ARM instruction or a function call. (If the result 6821 * comes back in a register other than r0, you can override "result".) 6822 * 6823 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6824 * vCC (r1). Useful for integer division and modulus. 6825 * 6826 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6827 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6828 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6829 */ 6830 /* binop/lit8 vAA, vBB, #+CC */ 6831 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6832 mov r9, rINST, lsr #8 @ r9<- AA 6833 and r2, r3, #255 @ r2<- BB 6834 GET_VREG(r0, r2) @ r0<- vBB 6835 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6836 .if 1 6837 @cmp r1, #0 @ is second operand zero? 6838 beq common_errDivideByZero 6839 .endif 6840 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6841 6842 @ optional op; may set condition codes 6843 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6844 GET_INST_OPCODE(ip) @ extract opcode from rINST 6845 SET_VREG(r0, r9) @ vAA<- r0 6846 GOTO_OPCODE(ip) @ jump to next instruction 6847 /* 10-12 instructions */ 6848 6849 6850/* ------------------------------ */ 6851 .balign 64 6852.L_OP_REM_INT_LIT8: /* 0xdc */ 6853/* File: armv5te/OP_REM_INT_LIT8.S */ 6854/* idivmod returns quotient in r0 and remainder in r1 */ 6855/* File: armv5te/binopLit8.S */ 6856 /* 6857 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6858 * that specifies an instruction that performs "result = r0 op r1". 6859 * This could be an ARM instruction or a function call. (If the result 6860 * comes back in a register other than r0, you can override "result".) 6861 * 6862 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6863 * vCC (r1). Useful for integer division and modulus. 6864 * 6865 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6866 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6867 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6868 */ 6869 /* binop/lit8 vAA, vBB, #+CC */ 6870 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6871 mov r9, rINST, lsr #8 @ r9<- AA 6872 and r2, r3, #255 @ r2<- BB 6873 GET_VREG(r0, r2) @ r0<- vBB 6874 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6875 .if 1 6876 @cmp r1, #0 @ is second operand zero? 6877 beq common_errDivideByZero 6878 .endif 6879 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6880 6881 @ optional op; may set condition codes 6882 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6883 GET_INST_OPCODE(ip) @ extract opcode from rINST 6884 SET_VREG(r1, r9) @ vAA<- r1 6885 GOTO_OPCODE(ip) @ jump to next instruction 6886 /* 10-12 instructions */ 6887 6888 6889/* ------------------------------ */ 6890 .balign 64 6891.L_OP_AND_INT_LIT8: /* 0xdd */ 6892/* File: armv5te/OP_AND_INT_LIT8.S */ 6893/* File: armv5te/binopLit8.S */ 6894 /* 6895 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6896 * that specifies an instruction that performs "result = r0 op r1". 6897 * This could be an ARM instruction or a function call. (If the result 6898 * comes back in a register other than r0, you can override "result".) 6899 * 6900 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6901 * vCC (r1). Useful for integer division and modulus. 6902 * 6903 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6904 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6905 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6906 */ 6907 /* binop/lit8 vAA, vBB, #+CC */ 6908 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6909 mov r9, rINST, lsr #8 @ r9<- AA 6910 and r2, r3, #255 @ r2<- BB 6911 GET_VREG(r0, r2) @ r0<- vBB 6912 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6913 .if 0 6914 @cmp r1, #0 @ is second operand zero? 6915 beq common_errDivideByZero 6916 .endif 6917 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6918 6919 @ optional op; may set condition codes 6920 and r0, r0, r1 @ r0<- op, r0-r3 changed 6921 GET_INST_OPCODE(ip) @ extract opcode from rINST 6922 SET_VREG(r0, r9) @ vAA<- r0 6923 GOTO_OPCODE(ip) @ jump to next instruction 6924 /* 10-12 instructions */ 6925 6926 6927/* ------------------------------ */ 6928 .balign 64 6929.L_OP_OR_INT_LIT8: /* 0xde */ 6930/* File: armv5te/OP_OR_INT_LIT8.S */ 6931/* File: armv5te/binopLit8.S */ 6932 /* 6933 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6934 * that specifies an instruction that performs "result = r0 op r1". 6935 * This could be an ARM instruction or a function call. (If the result 6936 * comes back in a register other than r0, you can override "result".) 6937 * 6938 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6939 * vCC (r1). Useful for integer division and modulus. 6940 * 6941 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6942 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6943 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6944 */ 6945 /* binop/lit8 vAA, vBB, #+CC */ 6946 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6947 mov r9, rINST, lsr #8 @ r9<- AA 6948 and r2, r3, #255 @ r2<- BB 6949 GET_VREG(r0, r2) @ r0<- vBB 6950 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6951 .if 0 6952 @cmp r1, #0 @ is second operand zero? 6953 beq common_errDivideByZero 6954 .endif 6955 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6956 6957 @ optional op; may set condition codes 6958 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6959 GET_INST_OPCODE(ip) @ extract opcode from rINST 6960 SET_VREG(r0, r9) @ vAA<- r0 6961 GOTO_OPCODE(ip) @ jump to next instruction 6962 /* 10-12 instructions */ 6963 6964 6965/* ------------------------------ */ 6966 .balign 64 6967.L_OP_XOR_INT_LIT8: /* 0xdf */ 6968/* File: armv5te/OP_XOR_INT_LIT8.S */ 6969/* File: armv5te/binopLit8.S */ 6970 /* 6971 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6972 * that specifies an instruction that performs "result = r0 op r1". 6973 * This could be an ARM instruction or a function call. (If the result 6974 * comes back in a register other than r0, you can override "result".) 6975 * 6976 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6977 * vCC (r1). Useful for integer division and modulus. 6978 * 6979 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6980 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6981 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6982 */ 6983 /* binop/lit8 vAA, vBB, #+CC */ 6984 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6985 mov r9, rINST, lsr #8 @ r9<- AA 6986 and r2, r3, #255 @ r2<- BB 6987 GET_VREG(r0, r2) @ r0<- vBB 6988 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6989 .if 0 6990 @cmp r1, #0 @ is second operand zero? 6991 beq common_errDivideByZero 6992 .endif 6993 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6994 6995 @ optional op; may set condition codes 6996 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6997 GET_INST_OPCODE(ip) @ extract opcode from rINST 6998 SET_VREG(r0, r9) @ vAA<- r0 6999 GOTO_OPCODE(ip) @ jump to next instruction 7000 /* 10-12 instructions */ 7001 7002 7003/* ------------------------------ */ 7004 .balign 64 7005.L_OP_SHL_INT_LIT8: /* 0xe0 */ 7006/* File: armv5te/OP_SHL_INT_LIT8.S */ 7007/* File: armv5te/binopLit8.S */ 7008 /* 7009 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7010 * that specifies an instruction that performs "result = r0 op r1". 7011 * This could be an ARM instruction or a function call. (If the result 7012 * comes back in a register other than r0, you can override "result".) 7013 * 7014 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7015 * vCC (r1). Useful for integer division and modulus. 7016 * 7017 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7018 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7019 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7020 */ 7021 /* binop/lit8 vAA, vBB, #+CC */ 7022 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7023 mov r9, rINST, lsr #8 @ r9<- AA 7024 and r2, r3, #255 @ r2<- BB 7025 GET_VREG(r0, r2) @ r0<- vBB 7026 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7027 .if 0 7028 @cmp r1, #0 @ is second operand zero? 7029 beq common_errDivideByZero 7030 .endif 7031 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7032 7033 and r1, r1, #31 @ optional op; may set condition codes 7034 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 7035 GET_INST_OPCODE(ip) @ extract opcode from rINST 7036 SET_VREG(r0, r9) @ vAA<- r0 7037 GOTO_OPCODE(ip) @ jump to next instruction 7038 /* 10-12 instructions */ 7039 7040 7041/* ------------------------------ */ 7042 .balign 64 7043.L_OP_SHR_INT_LIT8: /* 0xe1 */ 7044/* File: armv5te/OP_SHR_INT_LIT8.S */ 7045/* File: armv5te/binopLit8.S */ 7046 /* 7047 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7048 * that specifies an instruction that performs "result = r0 op r1". 7049 * This could be an ARM instruction or a function call. (If the result 7050 * comes back in a register other than r0, you can override "result".) 7051 * 7052 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7053 * vCC (r1). Useful for integer division and modulus. 7054 * 7055 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7056 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7057 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7058 */ 7059 /* binop/lit8 vAA, vBB, #+CC */ 7060 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7061 mov r9, rINST, lsr #8 @ r9<- AA 7062 and r2, r3, #255 @ r2<- BB 7063 GET_VREG(r0, r2) @ r0<- vBB 7064 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7065 .if 0 7066 @cmp r1, #0 @ is second operand zero? 7067 beq common_errDivideByZero 7068 .endif 7069 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7070 7071 and r1, r1, #31 @ optional op; may set condition codes 7072 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7073 GET_INST_OPCODE(ip) @ extract opcode from rINST 7074 SET_VREG(r0, r9) @ vAA<- r0 7075 GOTO_OPCODE(ip) @ jump to next instruction 7076 /* 10-12 instructions */ 7077 7078 7079/* ------------------------------ */ 7080 .balign 64 7081.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7082/* File: armv5te/OP_USHR_INT_LIT8.S */ 7083/* File: armv5te/binopLit8.S */ 7084 /* 7085 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7086 * that specifies an instruction that performs "result = r0 op r1". 7087 * This could be an ARM instruction or a function call. (If the result 7088 * comes back in a register other than r0, you can override "result".) 7089 * 7090 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7091 * vCC (r1). Useful for integer division and modulus. 7092 * 7093 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7094 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7095 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7096 */ 7097 /* binop/lit8 vAA, vBB, #+CC */ 7098 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7099 mov r9, rINST, lsr #8 @ r9<- AA 7100 and r2, r3, #255 @ r2<- BB 7101 GET_VREG(r0, r2) @ r0<- vBB 7102 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7103 .if 0 7104 @cmp r1, #0 @ is second operand zero? 7105 beq common_errDivideByZero 7106 .endif 7107 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7108 7109 and r1, r1, #31 @ optional op; may set condition codes 7110 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7111 GET_INST_OPCODE(ip) @ extract opcode from rINST 7112 SET_VREG(r0, r9) @ vAA<- r0 7113 GOTO_OPCODE(ip) @ jump to next instruction 7114 /* 10-12 instructions */ 7115 7116 7117/* ------------------------------ */ 7118 .balign 64 7119.L_OP_IGET_VOLATILE: /* 0xe3 */ 7120/* File: armv5te/OP_IGET_VOLATILE.S */ 7121/* File: armv5te/OP_IGET.S */ 7122 /* 7123 * General 32-bit instance field get. 7124 * 7125 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7126 */ 7127 /* op vA, vB, field@CCCC */ 7128 mov r0, rINST, lsr #12 @ r0<- B 7129 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7130 FETCH(r1, 1) @ r1<- field ref CCCC 7131 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7132 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7133 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7134 cmp r0, #0 @ is resolved entry null? 7135 bne .LOP_IGET_VOLATILE_finish @ no, already resolved 71368: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7137 EXPORT_PC() @ resolve() could throw 7138 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7139 bl dvmResolveInstField @ r0<- resolved InstField ptr 7140 cmp r0, #0 7141 bne .LOP_IGET_VOLATILE_finish 7142 b common_exceptionThrown 7143 7144 7145/* ------------------------------ */ 7146 .balign 64 7147.L_OP_IPUT_VOLATILE: /* 0xe4 */ 7148/* File: armv5te/OP_IPUT_VOLATILE.S */ 7149/* File: armv5te/OP_IPUT.S */ 7150 /* 7151 * General 32-bit instance field put. 7152 * 7153 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 7154 */ 7155 /* op vA, vB, field@CCCC */ 7156 mov r0, rINST, lsr #12 @ r0<- B 7157 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7158 FETCH(r1, 1) @ r1<- field ref CCCC 7159 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7160 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7161 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7162 cmp r0, #0 @ is resolved entry null? 7163 bne .LOP_IPUT_VOLATILE_finish @ no, already resolved 71648: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7165 EXPORT_PC() @ resolve() could throw 7166 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7167 bl dvmResolveInstField @ r0<- resolved InstField ptr 7168 cmp r0, #0 @ success? 7169 bne .LOP_IPUT_VOLATILE_finish @ yes, finish up 7170 b common_exceptionThrown 7171 7172 7173/* ------------------------------ */ 7174 .balign 64 7175.L_OP_SGET_VOLATILE: /* 0xe5 */ 7176/* File: armv5te/OP_SGET_VOLATILE.S */ 7177/* File: armv5te/OP_SGET.S */ 7178 /* 7179 * General 32-bit SGET handler. 7180 * 7181 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7182 */ 7183 /* op vAA, field@BBBB */ 7184 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7185 FETCH(r1, 1) @ r1<- field ref BBBB 7186 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7187 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7188 cmp r0, #0 @ is resolved entry null? 7189 beq .LOP_SGET_VOLATILE_resolve @ yes, do resolve 7190.LOP_SGET_VOLATILE_finish: @ field ptr in r0 7191 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7192 SMP_DMB @ acquiring load 7193 mov r2, rINST, lsr #8 @ r2<- AA 7194 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7195 SET_VREG(r1, r2) @ fp[AA]<- r1 7196 GET_INST_OPCODE(ip) @ extract opcode from rINST 7197 GOTO_OPCODE(ip) @ jump to next instruction 7198 7199 7200/* ------------------------------ */ 7201 .balign 64 7202.L_OP_SPUT_VOLATILE: /* 0xe6 */ 7203/* File: armv5te/OP_SPUT_VOLATILE.S */ 7204/* File: armv5te/OP_SPUT.S */ 7205 /* 7206 * General 32-bit SPUT handler. 7207 * 7208 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 7209 */ 7210 /* op vAA, field@BBBB */ 7211 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7212 FETCH(r1, 1) @ r1<- field ref BBBB 7213 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7214 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7215 cmp r0, #0 @ is resolved entry null? 7216 beq .LOP_SPUT_VOLATILE_resolve @ yes, do resolve 7217.LOP_SPUT_VOLATILE_finish: @ field ptr in r0 7218 mov r2, rINST, lsr #8 @ r2<- AA 7219 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7220 GET_VREG(r1, r2) @ r1<- fp[AA] 7221 GET_INST_OPCODE(ip) @ extract opcode from rINST 7222 SMP_DMB @ releasing store 7223 str r1, [r0, #offStaticField_value] @ field<- vAA 7224 GOTO_OPCODE(ip) @ jump to next instruction 7225 7226 7227/* ------------------------------ */ 7228 .balign 64 7229.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ 7230/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */ 7231/* File: armv5te/OP_IGET.S */ 7232 /* 7233 * General 32-bit instance field get. 7234 * 7235 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7236 */ 7237 /* op vA, vB, field@CCCC */ 7238 mov r0, rINST, lsr #12 @ r0<- B 7239 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7240 FETCH(r1, 1) @ r1<- field ref CCCC 7241 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7242 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7243 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7244 cmp r0, #0 @ is resolved entry null? 7245 bne .LOP_IGET_OBJECT_VOLATILE_finish @ no, already resolved 72468: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7247 EXPORT_PC() @ resolve() could throw 7248 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7249 bl dvmResolveInstField @ r0<- resolved InstField ptr 7250 cmp r0, #0 7251 bne .LOP_IGET_OBJECT_VOLATILE_finish 7252 b common_exceptionThrown 7253 7254 7255/* ------------------------------ */ 7256 .balign 64 7257.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */ 7258/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */ 7259/* File: armv5te/OP_IGET_WIDE.S */ 7260 /* 7261 * Wide 32-bit instance field get. 7262 */ 7263 /* iget-wide vA, vB, field@CCCC */ 7264 mov r0, rINST, lsr #12 @ r0<- B 7265 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7266 FETCH(r1, 1) @ r1<- field ref CCCC 7267 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7268 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7269 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7270 cmp r0, #0 @ is resolved entry null? 7271 bne .LOP_IGET_WIDE_VOLATILE_finish @ no, already resolved 72728: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7273 EXPORT_PC() @ resolve() could throw 7274 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7275 bl dvmResolveInstField @ r0<- resolved InstField ptr 7276 cmp r0, #0 7277 bne .LOP_IGET_WIDE_VOLATILE_finish 7278 b common_exceptionThrown 7279 7280 7281/* ------------------------------ */ 7282 .balign 64 7283.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */ 7284/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */ 7285/* File: armv5te/OP_IPUT_WIDE.S */ 7286 /* iput-wide vA, vB, field@CCCC */ 7287 mov r0, rINST, lsr #12 @ r0<- B 7288 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7289 FETCH(r1, 1) @ r1<- field ref CCCC 7290 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7291 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7292 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7293 cmp r0, #0 @ is resolved entry null? 7294 bne .LOP_IPUT_WIDE_VOLATILE_finish @ no, already resolved 72958: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7296 EXPORT_PC() @ resolve() could throw 7297 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7298 bl dvmResolveInstField @ r0<- resolved InstField ptr 7299 cmp r0, #0 @ success? 7300 bne .LOP_IPUT_WIDE_VOLATILE_finish @ yes, finish up 7301 b common_exceptionThrown 7302 7303 7304/* ------------------------------ */ 7305 .balign 64 7306.L_OP_SGET_WIDE_VOLATILE: /* 0xea */ 7307/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */ 7308/* File: armv5te/OP_SGET_WIDE.S */ 7309 /* 7310 * 64-bit SGET handler. 7311 */ 7312 /* sget-wide vAA, field@BBBB */ 7313 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7314 FETCH(r1, 1) @ r1<- field ref BBBB 7315 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7316 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7317 cmp r0, #0 @ is resolved entry null? 7318 beq .LOP_SGET_WIDE_VOLATILE_resolve @ yes, do resolve 7319.LOP_SGET_WIDE_VOLATILE_finish: 7320 mov r9, rINST, lsr #8 @ r9<- AA 7321 .if 1 7322 add r0, r0, #offStaticField_value @ r0<- pointer to data 7323 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 7324 .else 7325 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 7326 .endif 7327 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7328 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7329 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 7330 GET_INST_OPCODE(ip) @ extract opcode from rINST 7331 GOTO_OPCODE(ip) @ jump to next instruction 7332 7333 7334/* ------------------------------ */ 7335 .balign 64 7336.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */ 7337/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */ 7338/* File: armv5te/OP_SPUT_WIDE.S */ 7339 /* 7340 * 64-bit SPUT handler. 7341 */ 7342 /* sput-wide vAA, field@BBBB */ 7343 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 7344 FETCH(r1, 1) @ r1<- field ref BBBB 7345 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 7346 mov r9, rINST, lsr #8 @ r9<- AA 7347 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 7348 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7349 cmp r2, #0 @ is resolved entry null? 7350 beq .LOP_SPUT_WIDE_VOLATILE_resolve @ yes, do resolve 7351.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9 7352 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7353 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 7354 GET_INST_OPCODE(r10) @ extract opcode from rINST 7355 .if 1 7356 add r2, r2, #offStaticField_value @ r2<- pointer to data 7357 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 7358 .else 7359 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 7360 .endif 7361 GOTO_OPCODE(r10) @ jump to next instruction 7362 7363 7364/* ------------------------------ */ 7365 .balign 64 7366.L_OP_BREAKPOINT: /* 0xec */ 7367/* File: armv5te/OP_BREAKPOINT.S */ 7368/* File: armv5te/unused.S */ 7369 bl common_abort 7370 7371 7372/* ------------------------------ */ 7373 .balign 64 7374.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7375/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7376 /* 7377 * Handle a throw-verification-error instruction. This throws an 7378 * exception for an error discovered during verification. The 7379 * exception is indicated by AA, with some detail provided by BBBB. 7380 */ 7381 /* op AA, ref@BBBB */ 7382 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7383 FETCH(r2, 1) @ r2<- BBBB 7384 EXPORT_PC() @ export the PC 7385 mov r1, rINST, lsr #8 @ r1<- AA 7386 bl dvmThrowVerificationError @ always throws 7387 b common_exceptionThrown @ handle exception 7388 7389/* ------------------------------ */ 7390 .balign 64 7391.L_OP_EXECUTE_INLINE: /* 0xee */ 7392/* File: armv5te/OP_EXECUTE_INLINE.S */ 7393 /* 7394 * Execute a "native inline" instruction. 7395 * 7396 * We need to call an InlineOp4Func: 7397 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7398 * 7399 * The first four args are in r0-r3, pointer to return value storage 7400 * is on the stack. The function's return value is a flag that tells 7401 * us if an exception was thrown. 7402 */ 7403 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7404 FETCH(r10, 1) @ r10<- BBBB 7405 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7406 EXPORT_PC() @ can throw 7407 sub sp, sp, #8 @ make room for arg, +64 bit align 7408 mov r0, rINST, lsr #12 @ r0<- B 7409 str r1, [sp] @ push &glue->retval 7410 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7411 add sp, sp, #8 @ pop stack 7412 cmp r0, #0 @ test boolean result of inline 7413 beq common_exceptionThrown @ returned false, handle exception 7414 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7415 GET_INST_OPCODE(ip) @ extract opcode from rINST 7416 GOTO_OPCODE(ip) @ jump to next instruction 7417 7418/* ------------------------------ */ 7419 .balign 64 7420.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ 7421/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */ 7422 /* 7423 * Execute a "native inline" instruction, using "/range" semantics. 7424 * Same idea as execute-inline, but we get the args differently. 7425 * 7426 * We need to call an InlineOp4Func: 7427 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7428 * 7429 * The first four args are in r0-r3, pointer to return value storage 7430 * is on the stack. The function's return value is a flag that tells 7431 * us if an exception was thrown. 7432 */ 7433 /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */ 7434 FETCH(r10, 1) @ r10<- BBBB 7435 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7436 EXPORT_PC() @ can throw 7437 sub sp, sp, #8 @ make room for arg, +64 bit align 7438 mov r0, rINST, lsr #8 @ r0<- AA 7439 str r1, [sp] @ push &glue->retval 7440 bl .LOP_EXECUTE_INLINE_RANGE_continue @ make call; will return after 7441 add sp, sp, #8 @ pop stack 7442 cmp r0, #0 @ test boolean result of inline 7443 beq common_exceptionThrown @ returned false, handle exception 7444 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7445 GET_INST_OPCODE(ip) @ extract opcode from rINST 7446 GOTO_OPCODE(ip) @ jump to next instruction 7447 7448/* ------------------------------ */ 7449 .balign 64 7450.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7451/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7452 /* 7453 * invoke-direct-empty is a no-op in a "standard" interpreter. 7454 */ 7455 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7456 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7457 GOTO_OPCODE(ip) @ execute it 7458 7459/* ------------------------------ */ 7460 .balign 64 7461.L_OP_RETURN_VOID_BARRIER: /* 0xf1 */ 7462/* File: armv5te/OP_RETURN_VOID_BARRIER.S */ 7463 SMP_DMB_ST 7464 b common_returnFromMethod 7465 7466/* ------------------------------ */ 7467 .balign 64 7468.L_OP_IGET_QUICK: /* 0xf2 */ 7469/* File: armv5te/OP_IGET_QUICK.S */ 7470 /* For: iget-quick, iget-object-quick */ 7471 /* op vA, vB, offset@CCCC */ 7472 mov r2, rINST, lsr #12 @ r2<- B 7473 GET_VREG(r3, r2) @ r3<- object we're operating on 7474 FETCH(r1, 1) @ r1<- field byte offset 7475 cmp r3, #0 @ check object for null 7476 mov r2, rINST, lsr #8 @ r2<- A(+) 7477 beq common_errNullObject @ object was null 7478 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7479 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7480 and r2, r2, #15 7481 GET_INST_OPCODE(ip) @ extract opcode from rINST 7482 SET_VREG(r0, r2) @ fp[A]<- r0 7483 GOTO_OPCODE(ip) @ jump to next instruction 7484 7485/* ------------------------------ */ 7486 .balign 64 7487.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7488/* File: armv5te/OP_IGET_WIDE_QUICK.S */ 7489 /* iget-wide-quick vA, vB, offset@CCCC */ 7490 mov r2, rINST, lsr #12 @ r2<- B 7491 GET_VREG(r3, r2) @ r3<- object we're operating on 7492 FETCH(ip, 1) @ ip<- field byte offset 7493 cmp r3, #0 @ check object for null 7494 mov r2, rINST, lsr #8 @ r2<- A(+) 7495 beq common_errNullObject @ object was null 7496 ldrd r0, [r3, ip] @ r0<- obj.field (64 bits, aligned) 7497 and r2, r2, #15 7498 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7499 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7500 GET_INST_OPCODE(ip) @ extract opcode from rINST 7501 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7502 GOTO_OPCODE(ip) @ jump to next instruction 7503 7504/* ------------------------------ */ 7505 .balign 64 7506.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7507/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7508/* File: armv5te/OP_IGET_QUICK.S */ 7509 /* For: iget-quick, iget-object-quick */ 7510 /* op vA, vB, offset@CCCC */ 7511 mov r2, rINST, lsr #12 @ r2<- B 7512 GET_VREG(r3, r2) @ r3<- object we're operating on 7513 FETCH(r1, 1) @ r1<- field byte offset 7514 cmp r3, #0 @ check object for null 7515 mov r2, rINST, lsr #8 @ r2<- A(+) 7516 beq common_errNullObject @ object was null 7517 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7518 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7519 and r2, r2, #15 7520 GET_INST_OPCODE(ip) @ extract opcode from rINST 7521 SET_VREG(r0, r2) @ fp[A]<- r0 7522 GOTO_OPCODE(ip) @ jump to next instruction 7523 7524 7525/* ------------------------------ */ 7526 .balign 64 7527.L_OP_IPUT_QUICK: /* 0xf5 */ 7528/* File: armv5te/OP_IPUT_QUICK.S */ 7529 /* For: iput-quick */ 7530 /* op vA, vB, offset@CCCC */ 7531 mov r2, rINST, lsr #12 @ r2<- B 7532 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7533 FETCH(r1, 1) @ r1<- field byte offset 7534 cmp r3, #0 @ check object for null 7535 mov r2, rINST, lsr #8 @ r2<- A(+) 7536 beq common_errNullObject @ object was null 7537 and r2, r2, #15 7538 GET_VREG(r0, r2) @ r0<- fp[A] 7539 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7540 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7541 GET_INST_OPCODE(ip) @ extract opcode from rINST 7542 GOTO_OPCODE(ip) @ jump to next instruction 7543 7544/* ------------------------------ */ 7545 .balign 64 7546.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7547/* File: armv5te/OP_IPUT_WIDE_QUICK.S */ 7548 /* iput-wide-quick vA, vB, offset@CCCC */ 7549 mov r0, rINST, lsr #8 @ r0<- A(+) 7550 mov r1, rINST, lsr #12 @ r1<- B 7551 and r0, r0, #15 7552 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7553 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7554 cmp r2, #0 @ check object for null 7555 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7556 beq common_errNullObject @ object was null 7557 FETCH(r3, 1) @ r3<- field byte offset 7558 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7559 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7560 GET_INST_OPCODE(ip) @ extract opcode from rINST 7561 GOTO_OPCODE(ip) @ jump to next instruction 7562 7563/* ------------------------------ */ 7564 .balign 64 7565.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7566/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7567 /* For: iput-object-quick */ 7568 /* op vA, vB, offset@CCCC */ 7569 mov r2, rINST, lsr #12 @ r2<- B 7570 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7571 FETCH(r1, 1) @ r1<- field byte offset 7572 cmp r3, #0 @ check object for null 7573 mov r2, rINST, lsr #8 @ r2<- A(+) 7574 beq common_errNullObject @ object was null 7575 and r2, r2, #15 7576 GET_VREG(r0, r2) @ r0<- fp[A] 7577 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 7578 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7579 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7580 cmp r0, #0 7581 strneb r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head 7582 GET_INST_OPCODE(ip) @ extract opcode from rINST 7583 GOTO_OPCODE(ip) @ jump to next instruction 7584 7585/* ------------------------------ */ 7586 .balign 64 7587.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7588/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7589 /* 7590 * Handle an optimized virtual method call. 7591 * 7592 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7593 */ 7594 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7595 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7596 FETCH(r3, 2) @ r3<- FEDC or CCCC 7597 FETCH(r1, 1) @ r1<- BBBB 7598 .if (!0) 7599 and r3, r3, #15 @ r3<- C (or stays CCCC) 7600 .endif 7601 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7602 cmp r2, #0 @ is "this" null? 7603 beq common_errNullObject @ null "this", throw exception 7604 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7605 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7606 EXPORT_PC() @ invoke must export 7607 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7608 bl common_invokeMethodNoRange @ continue on 7609 7610/* ------------------------------ */ 7611 .balign 64 7612.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7613/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7614/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7615 /* 7616 * Handle an optimized virtual method call. 7617 * 7618 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7619 */ 7620 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7621 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7622 FETCH(r3, 2) @ r3<- FEDC or CCCC 7623 FETCH(r1, 1) @ r1<- BBBB 7624 .if (!1) 7625 and r3, r3, #15 @ r3<- C (or stays CCCC) 7626 .endif 7627 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7628 cmp r2, #0 @ is "this" null? 7629 beq common_errNullObject @ null "this", throw exception 7630 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7631 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7632 EXPORT_PC() @ invoke must export 7633 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7634 bl common_invokeMethodRange @ continue on 7635 7636 7637/* ------------------------------ */ 7638 .balign 64 7639.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7640/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7641 /* 7642 * Handle an optimized "super" method call. 7643 * 7644 * for: [opt] invoke-super-quick, invoke-super-quick/range 7645 */ 7646 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7647 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7648 FETCH(r10, 2) @ r10<- GFED or CCCC 7649 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7650 .if (!0) 7651 and r10, r10, #15 @ r10<- D (or stays CCCC) 7652 .endif 7653 FETCH(r1, 1) @ r1<- BBBB 7654 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7655 EXPORT_PC() @ must export for invoke 7656 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7657 GET_VREG(r3, r10) @ r3<- "this" 7658 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7659 cmp r3, #0 @ null "this" ref? 7660 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7661 beq common_errNullObject @ "this" is null, throw exception 7662 bl common_invokeMethodNoRange @ continue on 7663 7664/* ------------------------------ */ 7665 .balign 64 7666.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7667/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7668/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7669 /* 7670 * Handle an optimized "super" method call. 7671 * 7672 * for: [opt] invoke-super-quick, invoke-super-quick/range 7673 */ 7674 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7675 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7676 FETCH(r10, 2) @ r10<- GFED or CCCC 7677 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7678 .if (!1) 7679 and r10, r10, #15 @ r10<- D (or stays CCCC) 7680 .endif 7681 FETCH(r1, 1) @ r1<- BBBB 7682 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7683 EXPORT_PC() @ must export for invoke 7684 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7685 GET_VREG(r3, r10) @ r3<- "this" 7686 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7687 cmp r3, #0 @ null "this" ref? 7688 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7689 beq common_errNullObject @ "this" is null, throw exception 7690 bl common_invokeMethodRange @ continue on 7691 7692 7693/* ------------------------------ */ 7694 .balign 64 7695.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ 7696/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */ 7697/* File: armv5te/OP_IPUT_OBJECT.S */ 7698 /* 7699 * 32-bit instance field put. 7700 * 7701 * for: iput-object, iput-object-volatile 7702 */ 7703 /* op vA, vB, field@CCCC */ 7704 mov r0, rINST, lsr #12 @ r0<- B 7705 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7706 FETCH(r1, 1) @ r1<- field ref CCCC 7707 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7708 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7709 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7710 cmp r0, #0 @ is resolved entry null? 7711 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ no, already resolved 77128: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7713 EXPORT_PC() @ resolve() could throw 7714 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7715 bl dvmResolveInstField @ r0<- resolved InstField ptr 7716 cmp r0, #0 @ success? 7717 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ yes, finish up 7718 b common_exceptionThrown 7719 7720 7721/* ------------------------------ */ 7722 .balign 64 7723.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ 7724/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */ 7725/* File: armv5te/OP_SGET.S */ 7726 /* 7727 * General 32-bit SGET handler. 7728 * 7729 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7730 */ 7731 /* op vAA, field@BBBB */ 7732 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7733 FETCH(r1, 1) @ r1<- field ref BBBB 7734 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7735 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7736 cmp r0, #0 @ is resolved entry null? 7737 beq .LOP_SGET_OBJECT_VOLATILE_resolve @ yes, do resolve 7738.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0 7739 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7740 SMP_DMB @ acquiring load 7741 mov r2, rINST, lsr #8 @ r2<- AA 7742 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7743 SET_VREG(r1, r2) @ fp[AA]<- r1 7744 GET_INST_OPCODE(ip) @ extract opcode from rINST 7745 GOTO_OPCODE(ip) @ jump to next instruction 7746 7747 7748/* ------------------------------ */ 7749 .balign 64 7750.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ 7751/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */ 7752/* File: armv5te/OP_SPUT_OBJECT.S */ 7753 /* 7754 * 32-bit SPUT handler for objects 7755 * 7756 * for: sput-object, sput-object-volatile 7757 */ 7758 /* op vAA, field@BBBB */ 7759 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7760 FETCH(r1, 1) @ r1<- field ref BBBB 7761 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7762 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7763 cmp r0, #0 @ is resolved entry null? 7764 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ no, continue 7765 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 7766 EXPORT_PC() @ resolve() could throw, so export now 7767 ldr r0, [r9, #offMethod_clazz] @ r0<- method->clazz 7768 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 7769 cmp r0, #0 @ success? 7770 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish 7771 b common_exceptionThrown @ no, handle exception 7772 7773 7774 7775/* ------------------------------ */ 7776 .balign 64 7777.L_OP_UNUSED_FF: /* 0xff */ 7778/* File: armv5te/OP_UNUSED_FF.S */ 7779/* File: armv5te/unused.S */ 7780 bl common_abort 7781 7782 7783 7784 .balign 64 7785 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7786 .global dvmAsmInstructionEnd 7787dvmAsmInstructionEnd: 7788 7789/* 7790 * =========================================================================== 7791 * Sister implementations 7792 * =========================================================================== 7793 */ 7794 .global dvmAsmSisterStart 7795 .type dvmAsmSisterStart, %function 7796 .text 7797 .balign 4 7798dvmAsmSisterStart: 7799 7800/* continuation for OP_CONST_STRING */ 7801 7802 /* 7803 * Continuation if the String has not yet been resolved. 7804 * r1: BBBB (String ref) 7805 * r9: target register 7806 */ 7807.LOP_CONST_STRING_resolve: 7808 EXPORT_PC() 7809 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7810 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7811 bl dvmResolveString @ r0<- String reference 7812 cmp r0, #0 @ failed? 7813 beq common_exceptionThrown @ yup, handle the exception 7814 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7815 GET_INST_OPCODE(ip) @ extract opcode from rINST 7816 SET_VREG(r0, r9) @ vAA<- r0 7817 GOTO_OPCODE(ip) @ jump to next instruction 7818 7819/* continuation for OP_CONST_STRING_JUMBO */ 7820 7821 /* 7822 * Continuation if the String has not yet been resolved. 7823 * r1: BBBBBBBB (String ref) 7824 * r9: target register 7825 */ 7826.LOP_CONST_STRING_JUMBO_resolve: 7827 EXPORT_PC() 7828 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7829 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7830 bl dvmResolveString @ r0<- String reference 7831 cmp r0, #0 @ failed? 7832 beq common_exceptionThrown @ yup, handle the exception 7833 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7834 GET_INST_OPCODE(ip) @ extract opcode from rINST 7835 SET_VREG(r0, r9) @ vAA<- r0 7836 GOTO_OPCODE(ip) @ jump to next instruction 7837 7838/* continuation for OP_CONST_CLASS */ 7839 7840 /* 7841 * Continuation if the Class has not yet been resolved. 7842 * r1: BBBB (Class ref) 7843 * r9: target register 7844 */ 7845.LOP_CONST_CLASS_resolve: 7846 EXPORT_PC() 7847 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7848 mov r2, #1 @ r2<- true 7849 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7850 bl dvmResolveClass @ r0<- Class reference 7851 cmp r0, #0 @ failed? 7852 beq common_exceptionThrown @ yup, handle the exception 7853 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7854 GET_INST_OPCODE(ip) @ extract opcode from rINST 7855 SET_VREG(r0, r9) @ vAA<- r0 7856 GOTO_OPCODE(ip) @ jump to next instruction 7857 7858/* continuation for OP_CHECK_CAST */ 7859 7860 /* 7861 * Trivial test failed, need to perform full check. This is common. 7862 * r0 holds obj->clazz 7863 * r1 holds class resolved from BBBB 7864 * r9 holds object 7865 */ 7866.LOP_CHECK_CAST_fullcheck: 7867 bl dvmInstanceofNonTrivial @ r0<- boolean result 7868 cmp r0, #0 @ failed? 7869 bne .LOP_CHECK_CAST_okay @ no, success 7870 7871 @ A cast has failed. We need to throw a ClassCastException with the 7872 @ class of the object that failed to be cast. 7873 EXPORT_PC() @ about to throw 7874 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 7875 ldr r0, .LstrClassCastExceptionPtr 7876 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 7877 bl dvmThrowExceptionWithClassMessage 7878 b common_exceptionThrown 7879 7880 /* 7881 * Resolution required. This is the least-likely path. 7882 * 7883 * r2 holds BBBB 7884 * r9 holds object 7885 */ 7886.LOP_CHECK_CAST_resolve: 7887 EXPORT_PC() @ resolve() could throw 7888 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7889 mov r1, r2 @ r1<- BBBB 7890 mov r2, #0 @ r2<- false 7891 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7892 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7893 cmp r0, #0 @ got null? 7894 beq common_exceptionThrown @ yes, handle exception 7895 mov r1, r0 @ r1<- class resolved from BBB 7896 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7897 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7898 7899.LstrClassCastExceptionPtr: 7900 .word .LstrClassCastException 7901 7902/* continuation for OP_INSTANCE_OF */ 7903 7904 /* 7905 * Trivial test failed, need to perform full check. This is common. 7906 * r0 holds obj->clazz 7907 * r1 holds class resolved from BBBB 7908 * r9 holds A 7909 */ 7910.LOP_INSTANCE_OF_fullcheck: 7911 bl dvmInstanceofNonTrivial @ r0<- boolean result 7912 @ fall through to OP_INSTANCE_OF_store 7913 7914 /* 7915 * r0 holds boolean result 7916 * r9 holds A 7917 */ 7918.LOP_INSTANCE_OF_store: 7919 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7920 SET_VREG(r0, r9) @ vA<- r0 7921 GET_INST_OPCODE(ip) @ extract opcode from rINST 7922 GOTO_OPCODE(ip) @ jump to next instruction 7923 7924 /* 7925 * Trivial test succeeded, save and bail. 7926 * r9 holds A 7927 */ 7928.LOP_INSTANCE_OF_trivial: 7929 mov r0, #1 @ indicate success 7930 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7931 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7932 SET_VREG(r0, r9) @ vA<- r0 7933 GET_INST_OPCODE(ip) @ extract opcode from rINST 7934 GOTO_OPCODE(ip) @ jump to next instruction 7935 7936 /* 7937 * Resolution required. This is the least-likely path. 7938 * 7939 * r3 holds BBBB 7940 * r9 holds A 7941 */ 7942.LOP_INSTANCE_OF_resolve: 7943 EXPORT_PC() @ resolve() could throw 7944 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7945 mov r1, r3 @ r1<- BBBB 7946 mov r2, #1 @ r2<- true 7947 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7948 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7949 cmp r0, #0 @ got null? 7950 beq common_exceptionThrown @ yes, handle exception 7951 mov r1, r0 @ r1<- class resolved from BBB 7952 mov r3, rINST, lsr #12 @ r3<- B 7953 GET_VREG(r0, r3) @ r0<- vB (object) 7954 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7955 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7956 7957/* continuation for OP_NEW_INSTANCE */ 7958 7959 .balign 32 @ minimize cache lines 7960.LOP_NEW_INSTANCE_finish: @ r0=new object 7961 mov r3, rINST, lsr #8 @ r3<- AA 7962 cmp r0, #0 @ failed? 7963 beq common_exceptionThrown @ yes, handle the exception 7964 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7965 GET_INST_OPCODE(ip) @ extract opcode from rINST 7966 SET_VREG(r0, r3) @ vAA<- r0 7967 GOTO_OPCODE(ip) @ jump to next instruction 7968 7969 /* 7970 * Class initialization required. 7971 * 7972 * r0 holds class object 7973 */ 7974.LOP_NEW_INSTANCE_needinit: 7975 mov r9, r0 @ save r0 7976 bl dvmInitClass @ initialize class 7977 cmp r0, #0 @ check boolean result 7978 mov r0, r9 @ restore r0 7979 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7980 b common_exceptionThrown @ failed, deal with init exception 7981 7982 /* 7983 * Resolution required. This is the least-likely path. 7984 * 7985 * r1 holds BBBB 7986 */ 7987.LOP_NEW_INSTANCE_resolve: 7988 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7989 mov r2, #0 @ r2<- false 7990 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7991 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7992 cmp r0, #0 @ got null? 7993 bne .LOP_NEW_INSTANCE_resolved @ no, continue 7994 b common_exceptionThrown @ yes, handle exception 7995 7996.LstrInstantiationErrorPtr: 7997 .word .LstrInstantiationError 7998 7999/* continuation for OP_NEW_ARRAY */ 8000 8001 8002 /* 8003 * Resolve class. (This is an uncommon case.) 8004 * 8005 * r1 holds array length 8006 * r2 holds class ref CCCC 8007 */ 8008.LOP_NEW_ARRAY_resolve: 8009 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8010 mov r9, r1 @ r9<- length (save) 8011 mov r1, r2 @ r1<- CCCC 8012 mov r2, #0 @ r2<- false 8013 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8014 bl dvmResolveClass @ r0<- call(clazz, ref) 8015 cmp r0, #0 @ got null? 8016 mov r1, r9 @ r1<- length (restore) 8017 beq common_exceptionThrown @ yes, handle exception 8018 @ fall through to OP_NEW_ARRAY_finish 8019 8020 /* 8021 * Finish allocation. 8022 * 8023 * r0 holds class 8024 * r1 holds array length 8025 */ 8026.LOP_NEW_ARRAY_finish: 8027 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 8028 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 8029 cmp r0, #0 @ failed? 8030 mov r2, rINST, lsr #8 @ r2<- A+ 8031 beq common_exceptionThrown @ yes, handle the exception 8032 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8033 and r2, r2, #15 @ r2<- A 8034 GET_INST_OPCODE(ip) @ extract opcode from rINST 8035 SET_VREG(r0, r2) @ vA<- r0 8036 GOTO_OPCODE(ip) @ jump to next instruction 8037 8038/* continuation for OP_FILLED_NEW_ARRAY */ 8039 8040 /* 8041 * On entry: 8042 * r0 holds array class 8043 * r10 holds AA or BA 8044 */ 8045.LOP_FILLED_NEW_ARRAY_continue: 8046 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8047 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8048 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 8049 .if 0 8050 mov r1, r10 @ r1<- AA (length) 8051 .else 8052 mov r1, r10, lsr #4 @ r1<- B (length) 8053 .endif 8054 cmp rINST, #'I' @ array of ints? 8055 cmpne rINST, #'L' @ array of objects? 8056 cmpne rINST, #'[' @ array of arrays? 8057 mov r9, r1 @ save length in r9 8058 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 8059 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8060 cmp r0, #0 @ null return? 8061 beq common_exceptionThrown @ alloc failed, handle exception 8062 8063 FETCH(r1, 2) @ r1<- FEDC or CCCC 8064 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8065 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 8066 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8067 subs r9, r9, #1 @ length--, check for neg 8068 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8069 bmi 2f @ was zero, bail 8070 8071 @ copy values from registers into the array 8072 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8073 .if 0 8074 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 80751: ldr r3, [r2], #4 @ r3<- *r2++ 8076 subs r9, r9, #1 @ count-- 8077 str r3, [r0], #4 @ *contents++ = vX 8078 bpl 1b 8079 @ continue at 2 8080 .else 8081 cmp r9, #4 @ length was initially 5? 8082 and r2, r10, #15 @ r2<- A 8083 bne 1f @ <= 4 args, branch 8084 GET_VREG(r3, r2) @ r3<- vA 8085 sub r9, r9, #1 @ count-- 8086 str r3, [r0, #16] @ contents[4] = vA 80871: and r2, r1, #15 @ r2<- F/E/D/C 8088 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8089 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8090 subs r9, r9, #1 @ count-- 8091 str r3, [r0], #4 @ *contents++ = vX 8092 bpl 1b 8093 @ continue at 2 8094 .endif 8095 80962: 8097 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 8098 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 8099 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8100 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8101 cmp r1, #'I' @ Is int array? 8102 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 8103 GOTO_OPCODE(ip) @ execute it 8104 8105 /* 8106 * Throw an exception indicating that we have not implemented this 8107 * mode of filled-new-array. 8108 */ 8109.LOP_FILLED_NEW_ARRAY_notimpl: 8110 ldr r0, .L_strInternalError 8111 ldr r1, .L_strFilledNewArrayNotImpl 8112 bl dvmThrowException 8113 b common_exceptionThrown 8114 8115 .if (!0) @ define in one or the other, not both 8116.L_strFilledNewArrayNotImpl: 8117 .word .LstrFilledNewArrayNotImpl 8118.L_strInternalError: 8119 .word .LstrInternalError 8120 .endif 8121 8122/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 8123 8124 /* 8125 * On entry: 8126 * r0 holds array class 8127 * r10 holds AA or BA 8128 */ 8129.LOP_FILLED_NEW_ARRAY_RANGE_continue: 8130 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8131 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8132 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 8133 .if 1 8134 mov r1, r10 @ r1<- AA (length) 8135 .else 8136 mov r1, r10, lsr #4 @ r1<- B (length) 8137 .endif 8138 cmp rINST, #'I' @ array of ints? 8139 cmpne rINST, #'L' @ array of objects? 8140 cmpne rINST, #'[' @ array of arrays? 8141 mov r9, r1 @ save length in r9 8142 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 8143 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8144 cmp r0, #0 @ null return? 8145 beq common_exceptionThrown @ alloc failed, handle exception 8146 8147 FETCH(r1, 2) @ r1<- FEDC or CCCC 8148 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8149 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 8150 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8151 subs r9, r9, #1 @ length--, check for neg 8152 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8153 bmi 2f @ was zero, bail 8154 8155 @ copy values from registers into the array 8156 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8157 .if 1 8158 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 81591: ldr r3, [r2], #4 @ r3<- *r2++ 8160 subs r9, r9, #1 @ count-- 8161 str r3, [r0], #4 @ *contents++ = vX 8162 bpl 1b 8163 @ continue at 2 8164 .else 8165 cmp r9, #4 @ length was initially 5? 8166 and r2, r10, #15 @ r2<- A 8167 bne 1f @ <= 4 args, branch 8168 GET_VREG(r3, r2) @ r3<- vA 8169 sub r9, r9, #1 @ count-- 8170 str r3, [r0, #16] @ contents[4] = vA 81711: and r2, r1, #15 @ r2<- F/E/D/C 8172 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8173 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8174 subs r9, r9, #1 @ count-- 8175 str r3, [r0], #4 @ *contents++ = vX 8176 bpl 1b 8177 @ continue at 2 8178 .endif 8179 81802: 8181 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 8182 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 8183 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8184 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8185 cmp r1, #'I' @ Is int array? 8186 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 8187 GOTO_OPCODE(ip) @ execute it 8188 8189 /* 8190 * Throw an exception indicating that we have not implemented this 8191 * mode of filled-new-array. 8192 */ 8193.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8194 ldr r0, .L_strInternalError 8195 ldr r1, .L_strFilledNewArrayNotImpl 8196 bl dvmThrowException 8197 b common_exceptionThrown 8198 8199 .if (!1) @ define in one or the other, not both 8200.L_strFilledNewArrayNotImpl: 8201 .word .LstrFilledNewArrayNotImpl 8202.L_strInternalError: 8203 .word .LstrInternalError 8204 .endif 8205 8206/* continuation for OP_CMPL_FLOAT */ 8207.LOP_CMPL_FLOAT_finish: 8208 SET_VREG(r0, r9) @ vAA<- r0 8209 GOTO_OPCODE(ip) @ jump to next instruction 8210 8211/* continuation for OP_CMPG_FLOAT */ 8212.LOP_CMPG_FLOAT_finish: 8213 SET_VREG(r0, r9) @ vAA<- r0 8214 GOTO_OPCODE(ip) @ jump to next instruction 8215 8216/* continuation for OP_CMPL_DOUBLE */ 8217.LOP_CMPL_DOUBLE_finish: 8218 SET_VREG(r0, r9) @ vAA<- r0 8219 GOTO_OPCODE(ip) @ jump to next instruction 8220 8221/* continuation for OP_CMPG_DOUBLE */ 8222.LOP_CMPG_DOUBLE_finish: 8223 SET_VREG(r0, r9) @ vAA<- r0 8224 GOTO_OPCODE(ip) @ jump to next instruction 8225 8226/* continuation for OP_CMP_LONG */ 8227 8228.LOP_CMP_LONG_less: 8229 mvn r1, #0 @ r1<- -1 8230 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8231 @ instead, we just replicate the tail end. 8232 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8233 SET_VREG(r1, r9) @ vAA<- r1 8234 GET_INST_OPCODE(ip) @ extract opcode from rINST 8235 GOTO_OPCODE(ip) @ jump to next instruction 8236 8237.LOP_CMP_LONG_greater: 8238 mov r1, #1 @ r1<- 1 8239 @ fall through to _finish 8240 8241.LOP_CMP_LONG_finish: 8242 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8243 SET_VREG(r1, r9) @ vAA<- r1 8244 GET_INST_OPCODE(ip) @ extract opcode from rINST 8245 GOTO_OPCODE(ip) @ jump to next instruction 8246 8247/* continuation for OP_AGET_WIDE */ 8248 8249.LOP_AGET_WIDE_finish: 8250 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8251 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8252 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8253 GET_INST_OPCODE(ip) @ extract opcode from rINST 8254 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8255 GOTO_OPCODE(ip) @ jump to next instruction 8256 8257/* continuation for OP_APUT_WIDE */ 8258 8259.LOP_APUT_WIDE_finish: 8260 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8261 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8262 GET_INST_OPCODE(ip) @ extract opcode from rINST 8263 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8264 GOTO_OPCODE(ip) @ jump to next instruction 8265 8266/* continuation for OP_APUT_OBJECT */ 8267 /* 8268 * On entry: 8269 * rINST = vBB (arrayObj) 8270 * r9 = vAA (obj) 8271 * r10 = offset into array (vBB + vCC * width) 8272 */ 8273.LOP_APUT_OBJECT_finish: 8274 cmp r9, #0 @ storing null reference? 8275 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8276 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8277 ldr r1, [rINST, #offObject_clazz] @ r1<- arrayObj->clazz 8278 bl dvmCanPutArrayElement @ test object type vs. array type 8279 cmp r0, #0 @ okay? 8280 beq common_errArrayStore @ no 8281 mov r1, rINST @ r1<- arrayObj 8282 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8283 ldr r2, [rGLUE, #offGlue_cardTable] @ get biased CT base 8284 add r10, #offArrayObject_contents @ r0<- pointer to slot 8285 GET_INST_OPCODE(ip) @ extract opcode from rINST 8286 str r9, [r10] @ vBB[vCC]<- vAA 8287 strb r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head 8288 GOTO_OPCODE(ip) @ jump to next instruction 8289.LOP_APUT_OBJECT_skip_check: 8290 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8291 GET_INST_OPCODE(ip) @ extract opcode from rINST 8292 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8293 GOTO_OPCODE(ip) @ jump to next instruction 8294 8295/* continuation for OP_IGET */ 8296 8297 /* 8298 * Currently: 8299 * r0 holds resolved field 8300 * r9 holds object 8301 */ 8302.LOP_IGET_finish: 8303 @bl common_squeak0 8304 cmp r9, #0 @ check object for null 8305 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8306 beq common_errNullObject @ object was null 8307 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8308 @ no-op @ acquiring load 8309 mov r2, rINST, lsr #8 @ r2<- A+ 8310 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8311 and r2, r2, #15 @ r2<- A 8312 GET_INST_OPCODE(ip) @ extract opcode from rINST 8313 SET_VREG(r0, r2) @ fp[A]<- r0 8314 GOTO_OPCODE(ip) @ jump to next instruction 8315 8316/* continuation for OP_IGET_WIDE */ 8317 8318 /* 8319 * Currently: 8320 * r0 holds resolved field 8321 * r9 holds object 8322 */ 8323.LOP_IGET_WIDE_finish: 8324 cmp r9, #0 @ check object for null 8325 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8326 beq common_errNullObject @ object was null 8327 .if 0 8328 add r0, r9, r3 @ r0<- address of field 8329 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 8330 .else 8331 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8332 .endif 8333 mov r2, rINST, lsr #8 @ r2<- A+ 8334 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8335 and r2, r2, #15 @ r2<- A 8336 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8337 GET_INST_OPCODE(ip) @ extract opcode from rINST 8338 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8339 GOTO_OPCODE(ip) @ jump to next instruction 8340 8341/* continuation for OP_IGET_OBJECT */ 8342 8343 /* 8344 * Currently: 8345 * r0 holds resolved field 8346 * r9 holds object 8347 */ 8348.LOP_IGET_OBJECT_finish: 8349 @bl common_squeak0 8350 cmp r9, #0 @ check object for null 8351 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8352 beq common_errNullObject @ object was null 8353 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8354 @ no-op @ acquiring load 8355 mov r2, rINST, lsr #8 @ r2<- A+ 8356 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8357 and r2, r2, #15 @ r2<- A 8358 GET_INST_OPCODE(ip) @ extract opcode from rINST 8359 SET_VREG(r0, r2) @ fp[A]<- r0 8360 GOTO_OPCODE(ip) @ jump to next instruction 8361 8362/* continuation for OP_IGET_BOOLEAN */ 8363 8364 /* 8365 * Currently: 8366 * r0 holds resolved field 8367 * r9 holds object 8368 */ 8369.LOP_IGET_BOOLEAN_finish: 8370 @bl common_squeak1 8371 cmp r9, #0 @ check object for null 8372 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8373 beq common_errNullObject @ object was null 8374 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8375 @ no-op @ acquiring load 8376 mov r2, rINST, lsr #8 @ r2<- A+ 8377 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8378 and r2, r2, #15 @ r2<- A 8379 GET_INST_OPCODE(ip) @ extract opcode from rINST 8380 SET_VREG(r0, r2) @ fp[A]<- r0 8381 GOTO_OPCODE(ip) @ jump to next instruction 8382 8383/* continuation for OP_IGET_BYTE */ 8384 8385 /* 8386 * Currently: 8387 * r0 holds resolved field 8388 * r9 holds object 8389 */ 8390.LOP_IGET_BYTE_finish: 8391 @bl common_squeak2 8392 cmp r9, #0 @ check object for null 8393 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8394 beq common_errNullObject @ object was null 8395 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8396 @ no-op @ acquiring load 8397 mov r2, rINST, lsr #8 @ r2<- A+ 8398 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8399 and r2, r2, #15 @ r2<- A 8400 GET_INST_OPCODE(ip) @ extract opcode from rINST 8401 SET_VREG(r0, r2) @ fp[A]<- r0 8402 GOTO_OPCODE(ip) @ jump to next instruction 8403 8404/* continuation for OP_IGET_CHAR */ 8405 8406 /* 8407 * Currently: 8408 * r0 holds resolved field 8409 * r9 holds object 8410 */ 8411.LOP_IGET_CHAR_finish: 8412 @bl common_squeak3 8413 cmp r9, #0 @ check object for null 8414 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8415 beq common_errNullObject @ object was null 8416 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8417 @ no-op @ acquiring load 8418 mov r2, rINST, lsr #8 @ r2<- A+ 8419 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8420 and r2, r2, #15 @ r2<- A 8421 GET_INST_OPCODE(ip) @ extract opcode from rINST 8422 SET_VREG(r0, r2) @ fp[A]<- r0 8423 GOTO_OPCODE(ip) @ jump to next instruction 8424 8425/* continuation for OP_IGET_SHORT */ 8426 8427 /* 8428 * Currently: 8429 * r0 holds resolved field 8430 * r9 holds object 8431 */ 8432.LOP_IGET_SHORT_finish: 8433 @bl common_squeak4 8434 cmp r9, #0 @ check object for null 8435 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8436 beq common_errNullObject @ object was null 8437 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8438 @ no-op @ acquiring load 8439 mov r2, rINST, lsr #8 @ r2<- A+ 8440 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8441 and r2, r2, #15 @ r2<- A 8442 GET_INST_OPCODE(ip) @ extract opcode from rINST 8443 SET_VREG(r0, r2) @ fp[A]<- r0 8444 GOTO_OPCODE(ip) @ jump to next instruction 8445 8446/* continuation for OP_IPUT */ 8447 8448 /* 8449 * Currently: 8450 * r0 holds resolved field 8451 * r9 holds object 8452 */ 8453.LOP_IPUT_finish: 8454 @bl common_squeak0 8455 mov r1, rINST, lsr #8 @ r1<- A+ 8456 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8457 and r1, r1, #15 @ r1<- A 8458 cmp r9, #0 @ check object for null 8459 GET_VREG(r0, r1) @ r0<- fp[A] 8460 beq common_errNullObject @ object was null 8461 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8462 GET_INST_OPCODE(ip) @ extract opcode from rINST 8463 @ no-op @ releasing store 8464 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8465 GOTO_OPCODE(ip) @ jump to next instruction 8466 8467/* continuation for OP_IPUT_WIDE */ 8468 8469 /* 8470 * Currently: 8471 * r0 holds resolved field 8472 * r9 holds object 8473 */ 8474.LOP_IPUT_WIDE_finish: 8475 mov r2, rINST, lsr #8 @ r2<- A+ 8476 cmp r9, #0 @ check object for null 8477 and r2, r2, #15 @ r2<- A 8478 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8479 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8480 beq common_errNullObject @ object was null 8481 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8482 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8483 GET_INST_OPCODE(r10) @ extract opcode from rINST 8484 .if 0 8485 add r2, r9, r3 @ r2<- target address 8486 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 8487 .else 8488 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 8489 .endif 8490 GOTO_OPCODE(r10) @ jump to next instruction 8491 8492/* continuation for OP_IPUT_OBJECT */ 8493 8494 /* 8495 * Currently: 8496 * r0 holds resolved field 8497 * r9 holds object 8498 */ 8499.LOP_IPUT_OBJECT_finish: 8500 @bl common_squeak0 8501 mov r1, rINST, lsr #8 @ r1<- A+ 8502 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8503 and r1, r1, #15 @ r1<- A 8504 cmp r9, #0 @ check object for null 8505 GET_VREG(r0, r1) @ r0<- fp[A] 8506 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8507 beq common_errNullObject @ object was null 8508 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8509 GET_INST_OPCODE(ip) @ extract opcode from rINST 8510 @ no-op @ releasing store 8511 str r0, [r9, r3] @ obj.field (32 bits)<- r0 8512 cmp r0, #0 @ stored a null reference? 8513 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 8514 GOTO_OPCODE(ip) @ jump to next instruction 8515 8516/* continuation for OP_IPUT_BOOLEAN */ 8517 8518 /* 8519 * Currently: 8520 * r0 holds resolved field 8521 * r9 holds object 8522 */ 8523.LOP_IPUT_BOOLEAN_finish: 8524 @bl common_squeak1 8525 mov r1, rINST, lsr #8 @ r1<- A+ 8526 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8527 and r1, r1, #15 @ r1<- A 8528 cmp r9, #0 @ check object for null 8529 GET_VREG(r0, r1) @ r0<- fp[A] 8530 beq common_errNullObject @ object was null 8531 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8532 GET_INST_OPCODE(ip) @ extract opcode from rINST 8533 @ no-op @ releasing store 8534 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8535 GOTO_OPCODE(ip) @ jump to next instruction 8536 8537/* continuation for OP_IPUT_BYTE */ 8538 8539 /* 8540 * Currently: 8541 * r0 holds resolved field 8542 * r9 holds object 8543 */ 8544.LOP_IPUT_BYTE_finish: 8545 @bl common_squeak2 8546 mov r1, rINST, lsr #8 @ r1<- A+ 8547 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8548 and r1, r1, #15 @ r1<- A 8549 cmp r9, #0 @ check object for null 8550 GET_VREG(r0, r1) @ r0<- fp[A] 8551 beq common_errNullObject @ object was null 8552 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8553 GET_INST_OPCODE(ip) @ extract opcode from rINST 8554 @ no-op @ releasing store 8555 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8556 GOTO_OPCODE(ip) @ jump to next instruction 8557 8558/* continuation for OP_IPUT_CHAR */ 8559 8560 /* 8561 * Currently: 8562 * r0 holds resolved field 8563 * r9 holds object 8564 */ 8565.LOP_IPUT_CHAR_finish: 8566 @bl common_squeak3 8567 mov r1, rINST, lsr #8 @ r1<- A+ 8568 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8569 and r1, r1, #15 @ r1<- A 8570 cmp r9, #0 @ check object for null 8571 GET_VREG(r0, r1) @ r0<- fp[A] 8572 beq common_errNullObject @ object was null 8573 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8574 GET_INST_OPCODE(ip) @ extract opcode from rINST 8575 @ no-op @ releasing store 8576 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8577 GOTO_OPCODE(ip) @ jump to next instruction 8578 8579/* continuation for OP_IPUT_SHORT */ 8580 8581 /* 8582 * Currently: 8583 * r0 holds resolved field 8584 * r9 holds object 8585 */ 8586.LOP_IPUT_SHORT_finish: 8587 @bl common_squeak4 8588 mov r1, rINST, lsr #8 @ r1<- A+ 8589 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8590 and r1, r1, #15 @ r1<- A 8591 cmp r9, #0 @ check object for null 8592 GET_VREG(r0, r1) @ r0<- fp[A] 8593 beq common_errNullObject @ object was null 8594 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8595 GET_INST_OPCODE(ip) @ extract opcode from rINST 8596 @ no-op @ releasing store 8597 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8598 GOTO_OPCODE(ip) @ jump to next instruction 8599 8600/* continuation for OP_SGET */ 8601 8602 /* 8603 * Continuation if the field has not yet been resolved. 8604 * r1: BBBB field ref 8605 */ 8606.LOP_SGET_resolve: 8607 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8608 EXPORT_PC() @ resolve() could throw, so export now 8609 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8610 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8611 cmp r0, #0 @ success? 8612 bne .LOP_SGET_finish @ yes, finish 8613 b common_exceptionThrown @ no, handle exception 8614 8615/* continuation for OP_SGET_WIDE */ 8616 8617 /* 8618 * Continuation if the field has not yet been resolved. 8619 * r1: BBBB field ref 8620 * 8621 * Returns StaticField pointer in r0. 8622 */ 8623.LOP_SGET_WIDE_resolve: 8624 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8625 EXPORT_PC() @ resolve() could throw, so export now 8626 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8627 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8628 cmp r0, #0 @ success? 8629 bne .LOP_SGET_WIDE_finish @ yes, finish 8630 b common_exceptionThrown @ no, handle exception 8631 8632/* continuation for OP_SGET_OBJECT */ 8633 8634 /* 8635 * Continuation if the field has not yet been resolved. 8636 * r1: BBBB field ref 8637 */ 8638.LOP_SGET_OBJECT_resolve: 8639 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8640 EXPORT_PC() @ resolve() could throw, so export now 8641 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8642 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8643 cmp r0, #0 @ success? 8644 bne .LOP_SGET_OBJECT_finish @ yes, finish 8645 b common_exceptionThrown @ no, handle exception 8646 8647/* continuation for OP_SGET_BOOLEAN */ 8648 8649 /* 8650 * Continuation if the field has not yet been resolved. 8651 * r1: BBBB field ref 8652 */ 8653.LOP_SGET_BOOLEAN_resolve: 8654 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8655 EXPORT_PC() @ resolve() could throw, so export now 8656 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8657 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8658 cmp r0, #0 @ success? 8659 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8660 b common_exceptionThrown @ no, handle exception 8661 8662/* continuation for OP_SGET_BYTE */ 8663 8664 /* 8665 * Continuation if the field has not yet been resolved. 8666 * r1: BBBB field ref 8667 */ 8668.LOP_SGET_BYTE_resolve: 8669 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8670 EXPORT_PC() @ resolve() could throw, so export now 8671 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8672 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8673 cmp r0, #0 @ success? 8674 bne .LOP_SGET_BYTE_finish @ yes, finish 8675 b common_exceptionThrown @ no, handle exception 8676 8677/* continuation for OP_SGET_CHAR */ 8678 8679 /* 8680 * Continuation if the field has not yet been resolved. 8681 * r1: BBBB field ref 8682 */ 8683.LOP_SGET_CHAR_resolve: 8684 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8685 EXPORT_PC() @ resolve() could throw, so export now 8686 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8687 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8688 cmp r0, #0 @ success? 8689 bne .LOP_SGET_CHAR_finish @ yes, finish 8690 b common_exceptionThrown @ no, handle exception 8691 8692/* continuation for OP_SGET_SHORT */ 8693 8694 /* 8695 * Continuation if the field has not yet been resolved. 8696 * r1: BBBB field ref 8697 */ 8698.LOP_SGET_SHORT_resolve: 8699 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8700 EXPORT_PC() @ resolve() could throw, so export now 8701 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8702 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8703 cmp r0, #0 @ success? 8704 bne .LOP_SGET_SHORT_finish @ yes, finish 8705 b common_exceptionThrown @ no, handle exception 8706 8707/* continuation for OP_SPUT */ 8708 8709 /* 8710 * Continuation if the field has not yet been resolved. 8711 * r1: BBBB field ref 8712 */ 8713.LOP_SPUT_resolve: 8714 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8715 EXPORT_PC() @ resolve() could throw, so export now 8716 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8717 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8718 cmp r0, #0 @ success? 8719 bne .LOP_SPUT_finish @ yes, finish 8720 b common_exceptionThrown @ no, handle exception 8721 8722/* continuation for OP_SPUT_WIDE */ 8723 8724 /* 8725 * Continuation if the field has not yet been resolved. 8726 * r1: BBBB field ref 8727 * r9: &fp[AA] 8728 * 8729 * Returns StaticField pointer in r2. 8730 */ 8731.LOP_SPUT_WIDE_resolve: 8732 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8733 EXPORT_PC() @ resolve() could throw, so export now 8734 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8735 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8736 cmp r0, #0 @ success? 8737 mov r2, r0 @ copy to r2 8738 bne .LOP_SPUT_WIDE_finish @ yes, finish 8739 b common_exceptionThrown @ no, handle exception 8740 8741/* continuation for OP_SPUT_OBJECT */ 8742.LOP_SPUT_OBJECT_finish: @ field ptr in r0 8743 mov r2, rINST, lsr #8 @ r2<- AA 8744 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8745 GET_VREG(r1, r2) @ r1<- fp[AA] 8746 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8747 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz 8748 GET_INST_OPCODE(ip) @ extract opcode from rINST 8749 @ no-op @ releasing store 8750 str r1, [r0, #offStaticField_value] @ field<- vAA 8751 cmp r1, #0 @ stored a null object? 8752 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 8753 GOTO_OPCODE(ip) @ jump to next instruction 8754 8755/* continuation for OP_SPUT_BOOLEAN */ 8756 8757 /* 8758 * Continuation if the field has not yet been resolved. 8759 * r1: BBBB field ref 8760 */ 8761.LOP_SPUT_BOOLEAN_resolve: 8762 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8763 EXPORT_PC() @ resolve() could throw, so export now 8764 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8765 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8766 cmp r0, #0 @ success? 8767 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 8768 b common_exceptionThrown @ no, handle exception 8769 8770/* continuation for OP_SPUT_BYTE */ 8771 8772 /* 8773 * Continuation if the field has not yet been resolved. 8774 * r1: BBBB field ref 8775 */ 8776.LOP_SPUT_BYTE_resolve: 8777 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8778 EXPORT_PC() @ resolve() could throw, so export now 8779 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8780 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8781 cmp r0, #0 @ success? 8782 bne .LOP_SPUT_BYTE_finish @ yes, finish 8783 b common_exceptionThrown @ no, handle exception 8784 8785/* continuation for OP_SPUT_CHAR */ 8786 8787 /* 8788 * Continuation if the field has not yet been resolved. 8789 * r1: BBBB field ref 8790 */ 8791.LOP_SPUT_CHAR_resolve: 8792 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8793 EXPORT_PC() @ resolve() could throw, so export now 8794 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8795 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8796 cmp r0, #0 @ success? 8797 bne .LOP_SPUT_CHAR_finish @ yes, finish 8798 b common_exceptionThrown @ no, handle exception 8799 8800/* continuation for OP_SPUT_SHORT */ 8801 8802 /* 8803 * Continuation if the field has not yet been resolved. 8804 * r1: BBBB field ref 8805 */ 8806.LOP_SPUT_SHORT_resolve: 8807 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8808 EXPORT_PC() @ resolve() could throw, so export now 8809 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8810 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8811 cmp r0, #0 @ success? 8812 bne .LOP_SPUT_SHORT_finish @ yes, finish 8813 b common_exceptionThrown @ no, handle exception 8814 8815/* continuation for OP_INVOKE_VIRTUAL */ 8816 8817 /* 8818 * At this point: 8819 * r0 = resolved base method 8820 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8821 */ 8822.LOP_INVOKE_VIRTUAL_continue: 8823 GET_VREG(r1, r10) @ r1<- "this" ptr 8824 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8825 cmp r1, #0 @ is "this" null? 8826 beq common_errNullObject @ null "this", throw exception 8827 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8828 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8829 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8830 bl common_invokeMethodNoRange @ continue on 8831 8832/* continuation for OP_INVOKE_SUPER */ 8833 8834 /* 8835 * At this point: 8836 * r0 = resolved base method 8837 * r9 = method->clazz 8838 */ 8839.LOP_INVOKE_SUPER_continue: 8840 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8841 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8842 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8843 EXPORT_PC() @ must export for invoke 8844 cmp r2, r3 @ compare (methodIndex, vtableCount) 8845 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 8846 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8847 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8848 bl common_invokeMethodNoRange @ continue on 8849 8850.LOP_INVOKE_SUPER_resolve: 8851 mov r0, r9 @ r0<- method->clazz 8852 mov r2, #METHOD_VIRTUAL @ resolver method type 8853 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8854 cmp r0, #0 @ got null? 8855 bne .LOP_INVOKE_SUPER_continue @ no, continue 8856 b common_exceptionThrown @ yes, handle exception 8857 8858 /* 8859 * Throw a NoSuchMethodError with the method name as the message. 8860 * r0 = resolved base method 8861 */ 8862.LOP_INVOKE_SUPER_nsm: 8863 ldr r1, [r0, #offMethod_name] @ r1<- method name 8864 b common_errNoSuchMethod 8865 8866/* continuation for OP_INVOKE_DIRECT */ 8867 8868 /* 8869 * On entry: 8870 * r1 = reference (BBBB or CCCC) 8871 * r10 = "this" register 8872 */ 8873.LOP_INVOKE_DIRECT_resolve: 8874 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8875 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8876 mov r2, #METHOD_DIRECT @ resolver method type 8877 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8878 cmp r0, #0 @ got null? 8879 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8880 bne .LOP_INVOKE_DIRECT_finish @ no, continue 8881 b common_exceptionThrown @ yes, handle exception 8882 8883/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 8884 8885 /* 8886 * At this point: 8887 * r0 = resolved base method 8888 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8889 */ 8890.LOP_INVOKE_VIRTUAL_RANGE_continue: 8891 GET_VREG(r1, r10) @ r1<- "this" ptr 8892 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8893 cmp r1, #0 @ is "this" null? 8894 beq common_errNullObject @ null "this", throw exception 8895 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8896 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8897 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8898 bl common_invokeMethodRange @ continue on 8899 8900/* continuation for OP_INVOKE_SUPER_RANGE */ 8901 8902 /* 8903 * At this point: 8904 * r0 = resolved base method 8905 * r9 = method->clazz 8906 */ 8907.LOP_INVOKE_SUPER_RANGE_continue: 8908 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8909 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8910 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8911 EXPORT_PC() @ must export for invoke 8912 cmp r2, r3 @ compare (methodIndex, vtableCount) 8913 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 8914 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8915 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8916 bl common_invokeMethodRange @ continue on 8917 8918.LOP_INVOKE_SUPER_RANGE_resolve: 8919 mov r0, r9 @ r0<- method->clazz 8920 mov r2, #METHOD_VIRTUAL @ resolver method type 8921 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8922 cmp r0, #0 @ got null? 8923 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 8924 b common_exceptionThrown @ yes, handle exception 8925 8926 /* 8927 * Throw a NoSuchMethodError with the method name as the message. 8928 * r0 = resolved base method 8929 */ 8930.LOP_INVOKE_SUPER_RANGE_nsm: 8931 ldr r1, [r0, #offMethod_name] @ r1<- method name 8932 b common_errNoSuchMethod 8933 8934/* continuation for OP_INVOKE_DIRECT_RANGE */ 8935 8936 /* 8937 * On entry: 8938 * r1 = reference (BBBB or CCCC) 8939 * r10 = "this" register 8940 */ 8941.LOP_INVOKE_DIRECT_RANGE_resolve: 8942 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8943 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8944 mov r2, #METHOD_DIRECT @ resolver method type 8945 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8946 cmp r0, #0 @ got null? 8947 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8948 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 8949 b common_exceptionThrown @ yes, handle exception 8950 8951/* continuation for OP_FLOAT_TO_LONG */ 8952/* 8953 * Convert the float in r0 to a long in r0/r1. 8954 * 8955 * We have to clip values to long min/max per the specification. The 8956 * expected common case is a "reasonable" value that converts directly 8957 * to modest integer. The EABI convert function isn't doing this for us. 8958 */ 8959f2l_doconv: 8960 stmfd sp!, {r4, lr} 8961 mov r1, #0x5f000000 @ (float)maxlong 8962 mov r4, r0 8963 bl __aeabi_fcmpge @ is arg >= maxlong? 8964 cmp r0, #0 @ nonzero == yes 8965 mvnne r0, #0 @ return maxlong (7fffffff) 8966 mvnne r1, #0x80000000 8967 ldmnefd sp!, {r4, pc} 8968 8969 mov r0, r4 @ recover arg 8970 mov r1, #0xdf000000 @ (float)minlong 8971 bl __aeabi_fcmple @ is arg <= minlong? 8972 cmp r0, #0 @ nonzero == yes 8973 movne r0, #0 @ return minlong (80000000) 8974 movne r1, #0x80000000 8975 ldmnefd sp!, {r4, pc} 8976 8977 mov r0, r4 @ recover arg 8978 mov r1, r4 8979 bl __aeabi_fcmpeq @ is arg == self? 8980 cmp r0, #0 @ zero == no 8981 moveq r1, #0 @ return zero for NaN 8982 ldmeqfd sp!, {r4, pc} 8983 8984 mov r0, r4 @ recover arg 8985 bl __aeabi_f2lz @ convert float to long 8986 ldmfd sp!, {r4, pc} 8987 8988/* continuation for OP_DOUBLE_TO_LONG */ 8989/* 8990 * Convert the double in r0/r1 to a long in r0/r1. 8991 * 8992 * We have to clip values to long min/max per the specification. The 8993 * expected common case is a "reasonable" value that converts directly 8994 * to modest integer. The EABI convert function isn't doing this for us. 8995 */ 8996d2l_doconv: 8997 stmfd sp!, {r4, r5, lr} @ save regs 8998 mov r3, #0x43000000 @ maxlong, as a double (high word) 8999 add r3, #0x00e00000 @ 0x43e00000 9000 mov r2, #0 @ maxlong, as a double (low word) 9001 sub sp, sp, #4 @ align for EABI 9002 mov r4, r0 @ save a copy of r0 9003 mov r5, r1 @ and r1 9004 bl __aeabi_dcmpge @ is arg >= maxlong? 9005 cmp r0, #0 @ nonzero == yes 9006 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 9007 mvnne r1, #0x80000000 9008 bne 1f 9009 9010 mov r0, r4 @ recover arg 9011 mov r1, r5 9012 mov r3, #0xc3000000 @ minlong, as a double (high word) 9013 add r3, #0x00e00000 @ 0xc3e00000 9014 mov r2, #0 @ minlong, as a double (low word) 9015 bl __aeabi_dcmple @ is arg <= minlong? 9016 cmp r0, #0 @ nonzero == yes 9017 movne r0, #0 @ return minlong (8000000000000000) 9018 movne r1, #0x80000000 9019 bne 1f 9020 9021 mov r0, r4 @ recover arg 9022 mov r1, r5 9023 mov r2, r4 @ compare against self 9024 mov r3, r5 9025 bl __aeabi_dcmpeq @ is arg == self? 9026 cmp r0, #0 @ zero == no 9027 moveq r1, #0 @ return zero for NaN 9028 beq 1f 9029 9030 mov r0, r4 @ recover arg 9031 mov r1, r5 9032 bl __aeabi_d2lz @ convert double to long 9033 90341: 9035 add sp, sp, #4 9036 ldmfd sp!, {r4, r5, pc} 9037 9038/* continuation for OP_MUL_LONG */ 9039 9040.LOP_MUL_LONG_finish: 9041 GET_INST_OPCODE(ip) @ extract opcode from rINST 9042 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 9043 GOTO_OPCODE(ip) @ jump to next instruction 9044 9045/* continuation for OP_SHL_LONG */ 9046 9047.LOP_SHL_LONG_finish: 9048 mov r0, r0, asl r2 @ r0<- r0 << r2 9049 GET_INST_OPCODE(ip) @ extract opcode from rINST 9050 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9051 GOTO_OPCODE(ip) @ jump to next instruction 9052 9053/* continuation for OP_SHR_LONG */ 9054 9055.LOP_SHR_LONG_finish: 9056 mov r1, r1, asr r2 @ r1<- r1 >> r2 9057 GET_INST_OPCODE(ip) @ extract opcode from rINST 9058 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9059 GOTO_OPCODE(ip) @ jump to next instruction 9060 9061/* continuation for OP_USHR_LONG */ 9062 9063.LOP_USHR_LONG_finish: 9064 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 9065 GET_INST_OPCODE(ip) @ extract opcode from rINST 9066 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9067 GOTO_OPCODE(ip) @ jump to next instruction 9068 9069/* continuation for OP_SHL_LONG_2ADDR */ 9070 9071.LOP_SHL_LONG_2ADDR_finish: 9072 GET_INST_OPCODE(ip) @ extract opcode from rINST 9073 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9074 GOTO_OPCODE(ip) @ jump to next instruction 9075 9076/* continuation for OP_SHR_LONG_2ADDR */ 9077 9078.LOP_SHR_LONG_2ADDR_finish: 9079 GET_INST_OPCODE(ip) @ extract opcode from rINST 9080 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9081 GOTO_OPCODE(ip) @ jump to next instruction 9082 9083/* continuation for OP_USHR_LONG_2ADDR */ 9084 9085.LOP_USHR_LONG_2ADDR_finish: 9086 GET_INST_OPCODE(ip) @ extract opcode from rINST 9087 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9088 GOTO_OPCODE(ip) @ jump to next instruction 9089 9090/* continuation for OP_IGET_VOLATILE */ 9091 9092 /* 9093 * Currently: 9094 * r0 holds resolved field 9095 * r9 holds object 9096 */ 9097.LOP_IGET_VOLATILE_finish: 9098 @bl common_squeak0 9099 cmp r9, #0 @ check object for null 9100 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9101 beq common_errNullObject @ object was null 9102 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9103 SMP_DMB @ acquiring load 9104 mov r2, rINST, lsr #8 @ r2<- A+ 9105 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9106 and r2, r2, #15 @ r2<- A 9107 GET_INST_OPCODE(ip) @ extract opcode from rINST 9108 SET_VREG(r0, r2) @ fp[A]<- r0 9109 GOTO_OPCODE(ip) @ jump to next instruction 9110 9111/* continuation for OP_IPUT_VOLATILE */ 9112 9113 /* 9114 * Currently: 9115 * r0 holds resolved field 9116 * r9 holds object 9117 */ 9118.LOP_IPUT_VOLATILE_finish: 9119 @bl common_squeak0 9120 mov r1, rINST, lsr #8 @ r1<- A+ 9121 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9122 and r1, r1, #15 @ r1<- A 9123 cmp r9, #0 @ check object for null 9124 GET_VREG(r0, r1) @ r0<- fp[A] 9125 beq common_errNullObject @ object was null 9126 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9127 GET_INST_OPCODE(ip) @ extract opcode from rINST 9128 SMP_DMB @ releasing store 9129 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 9130 GOTO_OPCODE(ip) @ jump to next instruction 9131 9132/* continuation for OP_SGET_VOLATILE */ 9133 9134 /* 9135 * Continuation if the field has not yet been resolved. 9136 * r1: BBBB field ref 9137 */ 9138.LOP_SGET_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_VOLATILE_finish @ yes, finish 9145 b common_exceptionThrown @ no, handle exception 9146 9147/* continuation for OP_SPUT_VOLATILE */ 9148 9149 /* 9150 * Continuation if the field has not yet been resolved. 9151 * r1: BBBB field ref 9152 */ 9153.LOP_SPUT_VOLATILE_resolve: 9154 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9155 EXPORT_PC() @ resolve() could throw, so export now 9156 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9157 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9158 cmp r0, #0 @ success? 9159 bne .LOP_SPUT_VOLATILE_finish @ yes, finish 9160 b common_exceptionThrown @ no, handle exception 9161 9162/* continuation for OP_IGET_OBJECT_VOLATILE */ 9163 9164 /* 9165 * Currently: 9166 * r0 holds resolved field 9167 * r9 holds object 9168 */ 9169.LOP_IGET_OBJECT_VOLATILE_finish: 9170 @bl common_squeak0 9171 cmp r9, #0 @ check object for null 9172 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9173 beq common_errNullObject @ object was null 9174 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9175 SMP_DMB @ acquiring load 9176 mov r2, rINST, lsr #8 @ r2<- A+ 9177 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9178 and r2, r2, #15 @ r2<- A 9179 GET_INST_OPCODE(ip) @ extract opcode from rINST 9180 SET_VREG(r0, r2) @ fp[A]<- r0 9181 GOTO_OPCODE(ip) @ jump to next instruction 9182 9183/* continuation for OP_IGET_WIDE_VOLATILE */ 9184 9185 /* 9186 * Currently: 9187 * r0 holds resolved field 9188 * r9 holds object 9189 */ 9190.LOP_IGET_WIDE_VOLATILE_finish: 9191 cmp r9, #0 @ check object for null 9192 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9193 beq common_errNullObject @ object was null 9194 .if 1 9195 add r0, r9, r3 @ r0<- address of field 9196 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 9197 .else 9198 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 9199 .endif 9200 mov r2, rINST, lsr #8 @ r2<- A+ 9201 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9202 and r2, r2, #15 @ r2<- A 9203 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 9204 GET_INST_OPCODE(ip) @ extract opcode from rINST 9205 stmia r3, {r0-r1} @ fp[A]<- r0/r1 9206 GOTO_OPCODE(ip) @ jump to next instruction 9207 9208/* continuation for OP_IPUT_WIDE_VOLATILE */ 9209 9210 /* 9211 * Currently: 9212 * r0 holds resolved field 9213 * r9 holds object 9214 */ 9215.LOP_IPUT_WIDE_VOLATILE_finish: 9216 mov r2, rINST, lsr #8 @ r2<- A+ 9217 cmp r9, #0 @ check object for null 9218 and r2, r2, #15 @ r2<- A 9219 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9220 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 9221 beq common_errNullObject @ object was null 9222 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9223 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 9224 GET_INST_OPCODE(r10) @ extract opcode from rINST 9225 .if 1 9226 add r2, r9, r3 @ r2<- target address 9227 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 9228 .else 9229 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 9230 .endif 9231 GOTO_OPCODE(r10) @ jump to next instruction 9232 9233/* continuation for OP_SGET_WIDE_VOLATILE */ 9234 9235 /* 9236 * Continuation if the field has not yet been resolved. 9237 * r1: BBBB field ref 9238 * 9239 * Returns StaticField pointer in r0. 9240 */ 9241.LOP_SGET_WIDE_VOLATILE_resolve: 9242 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9243 EXPORT_PC() @ resolve() could throw, so export now 9244 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9245 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9246 cmp r0, #0 @ success? 9247 bne .LOP_SGET_WIDE_VOLATILE_finish @ yes, finish 9248 b common_exceptionThrown @ no, handle exception 9249 9250/* continuation for OP_SPUT_WIDE_VOLATILE */ 9251 9252 /* 9253 * Continuation if the field has not yet been resolved. 9254 * r1: BBBB field ref 9255 * r9: &fp[AA] 9256 * 9257 * Returns StaticField pointer in r2. 9258 */ 9259.LOP_SPUT_WIDE_VOLATILE_resolve: 9260 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9261 EXPORT_PC() @ resolve() could throw, so export now 9262 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9263 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9264 cmp r0, #0 @ success? 9265 mov r2, r0 @ copy to r2 9266 bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish 9267 b common_exceptionThrown @ no, handle exception 9268 9269/* continuation for OP_EXECUTE_INLINE */ 9270 9271 /* 9272 * Extract args, call function. 9273 * r0 = #of args (0-4) 9274 * r10 = call index 9275 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9276 * 9277 * Other ideas: 9278 * - Use a jump table from the main piece to jump directly into the 9279 * AND/LDR pairs. Costs a data load, saves a branch. 9280 * - Have five separate pieces that do the loading, so we can work the 9281 * interleave a little better. Increases code size. 9282 */ 9283.LOP_EXECUTE_INLINE_continue: 9284 rsb r0, r0, #4 @ r0<- 4-r0 9285 FETCH(r9, 2) @ r9<- FEDC 9286 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9287 bl common_abort @ (skipped due to ARM prefetch) 92884: and ip, r9, #0xf000 @ isolate F 9289 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 92903: and ip, r9, #0x0f00 @ isolate E 9291 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 92922: and ip, r9, #0x00f0 @ isolate D 9293 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 92941: and ip, r9, #0x000f @ isolate C 9295 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 92960: 9297 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 9298 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9299 @ (not reached) 9300 9301.LOP_EXECUTE_INLINE_table: 9302 .word gDvmInlineOpsTable 9303 9304/* continuation for OP_EXECUTE_INLINE_RANGE */ 9305 9306 /* 9307 * Extract args, call function. 9308 * r0 = #of args (0-4) 9309 * r10 = call index 9310 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9311 */ 9312.LOP_EXECUTE_INLINE_RANGE_continue: 9313 rsb r0, r0, #4 @ r0<- 4-r0 9314 FETCH(r9, 2) @ r9<- CCCC 9315 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9316 bl common_abort @ (skipped due to ARM prefetch) 93174: add ip, r9, #3 @ base+3 9318 GET_VREG(r3, ip) @ r3<- vBase[3] 93193: add ip, r9, #2 @ base+2 9320 GET_VREG(r2, ip) @ r2<- vBase[2] 93212: add ip, r9, #1 @ base+1 9322 GET_VREG(r1, ip) @ r1<- vBase[1] 93231: add ip, r9, #0 @ (nop) 9324 GET_VREG(r0, ip) @ r0<- vBase[0] 93250: 9326 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation 9327 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9328 @ (not reached) 9329 9330.LOP_EXECUTE_INLINE_RANGE_table: 9331 .word gDvmInlineOpsTable 9332 9333/* continuation for OP_IPUT_OBJECT_VOLATILE */ 9334 9335 /* 9336 * Currently: 9337 * r0 holds resolved field 9338 * r9 holds object 9339 */ 9340.LOP_IPUT_OBJECT_VOLATILE_finish: 9341 @bl common_squeak0 9342 mov r1, rINST, lsr #8 @ r1<- A+ 9343 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9344 and r1, r1, #15 @ r1<- A 9345 cmp r9, #0 @ check object for null 9346 GET_VREG(r0, r1) @ r0<- fp[A] 9347 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 9348 beq common_errNullObject @ object was null 9349 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9350 GET_INST_OPCODE(ip) @ extract opcode from rINST 9351 SMP_DMB @ releasing store 9352 str r0, [r9, r3] @ obj.field (32 bits)<- r0 9353 cmp r0, #0 @ stored a null reference? 9354 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 9355 GOTO_OPCODE(ip) @ jump to next instruction 9356 9357/* continuation for OP_SGET_OBJECT_VOLATILE */ 9358 9359 /* 9360 * Continuation if the field has not yet been resolved. 9361 * r1: BBBB field ref 9362 */ 9363.LOP_SGET_OBJECT_VOLATILE_resolve: 9364 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9365 EXPORT_PC() @ resolve() could throw, so export now 9366 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9367 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9368 cmp r0, #0 @ success? 9369 bne .LOP_SGET_OBJECT_VOLATILE_finish @ yes, finish 9370 b common_exceptionThrown @ no, handle exception 9371 9372/* continuation for OP_SPUT_OBJECT_VOLATILE */ 9373.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0 9374 mov r2, rINST, lsr #8 @ r2<- AA 9375 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9376 GET_VREG(r1, r2) @ r1<- fp[AA] 9377 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 9378 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz 9379 GET_INST_OPCODE(ip) @ extract opcode from rINST 9380 SMP_DMB @ releasing store 9381 str r1, [r0, #offStaticField_value] @ field<- vAA 9382 cmp r1, #0 @ stored a null object? 9383 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 9384 GOTO_OPCODE(ip) @ jump to next instruction 9385 9386 .size dvmAsmSisterStart, .-dvmAsmSisterStart 9387 .global dvmAsmSisterEnd 9388dvmAsmSisterEnd: 9389 9390/* File: armv5te/footer.S */ 9391 9392/* 9393 * =========================================================================== 9394 * Common subroutines and data 9395 * =========================================================================== 9396 */ 9397 9398 9399 9400 .text 9401 .align 2 9402 9403#if defined(WITH_JIT) 9404#if defined(WITH_SELF_VERIFICATION) 9405 .global dvmJitToInterpPunt 9406dvmJitToInterpPunt: 9407 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9408 mov r2,#kSVSPunt @ r2<- interpreter entry point 9409 mov r3, #0 9410 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9411 b jitSVShadowRunEnd @ doesn't return 9412 9413 .global dvmJitToInterpSingleStep 9414dvmJitToInterpSingleStep: 9415 str lr,[rGLUE,#offGlue_jitResumeNPC] 9416 str r1,[rGLUE,#offGlue_jitResumeDPC] 9417 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 9418 b jitSVShadowRunEnd @ doesn't return 9419 9420 .global dvmJitToInterpNoChainNoProfile 9421dvmJitToInterpNoChainNoProfile: 9422 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9423 mov r0,rPC @ pass our target PC 9424 mov r2,#kSVSNoProfile @ r2<- interpreter entry point 9425 mov r3, #0 @ 0 means !inJitCodeCache 9426 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land 9427 b jitSVShadowRunEnd @ doesn't return 9428 9429 .global dvmJitToInterpTraceSelectNoChain 9430dvmJitToInterpTraceSelectNoChain: 9431 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9432 mov r0,rPC @ pass our target PC 9433 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9434 mov r3, #0 @ 0 means !inJitCodeCache 9435 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9436 b jitSVShadowRunEnd @ doesn't return 9437 9438 .global dvmJitToInterpTraceSelect 9439dvmJitToInterpTraceSelect: 9440 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9441 ldr r0,[lr, #-1] @ pass our target PC 9442 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9443 mov r3, #0 @ 0 means !inJitCodeCache 9444 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9445 b jitSVShadowRunEnd @ doesn't return 9446 9447 .global dvmJitToInterpBackwardBranch 9448dvmJitToInterpBackwardBranch: 9449 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9450 ldr r0,[lr, #-1] @ pass our target PC 9451 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 9452 mov r3, #0 @ 0 means !inJitCodeCache 9453 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9454 b jitSVShadowRunEnd @ doesn't return 9455 9456 .global dvmJitToInterpNormal 9457dvmJitToInterpNormal: 9458 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9459 ldr r0,[lr, #-1] @ pass our target PC 9460 mov r2,#kSVSNormal @ r2<- interpreter entry point 9461 mov r3, #0 @ 0 means !inJitCodeCache 9462 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9463 b jitSVShadowRunEnd @ doesn't return 9464 9465 .global dvmJitToInterpNoChain 9466dvmJitToInterpNoChain: 9467 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9468 mov r0,rPC @ pass our target PC 9469 mov r2,#kSVSNoChain @ r2<- interpreter entry point 9470 mov r3, #0 @ 0 means !inJitCodeCache 9471 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9472 b jitSVShadowRunEnd @ doesn't return 9473#else 9474/* 9475 * Return from the translation cache to the interpreter when the compiler is 9476 * having issues translating/executing a Dalvik instruction. We have to skip 9477 * the code cache lookup otherwise it is possible to indefinitely bouce 9478 * between the interpreter and the code cache if the instruction that fails 9479 * to be compiled happens to be at a trace start. 9480 */ 9481 .global dvmJitToInterpPunt 9482dvmJitToInterpPunt: 9483 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9484 mov rPC, r0 9485#if defined(WITH_JIT_TUNING) 9486 mov r0,lr 9487 bl dvmBumpPunt; 9488#endif 9489 EXPORT_PC() 9490 mov r0, #0 9491 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9492 adrl rIBASE, dvmAsmInstructionStart 9493 FETCH_INST() 9494 GET_INST_OPCODE(ip) 9495 GOTO_OPCODE(ip) 9496 9497/* 9498 * Return to the interpreter to handle a single instruction. 9499 * On entry: 9500 * r0 <= PC 9501 * r1 <= PC of resume instruction 9502 * lr <= resume point in translation 9503 */ 9504 .global dvmJitToInterpSingleStep 9505dvmJitToInterpSingleStep: 9506 str lr,[rGLUE,#offGlue_jitResumeNPC] 9507 str r1,[rGLUE,#offGlue_jitResumeDPC] 9508 mov r1,#kInterpEntryInstr 9509 @ enum is 4 byte in aapcs-EABI 9510 str r1, [rGLUE, #offGlue_entryPoint] 9511 mov rPC,r0 9512 EXPORT_PC() 9513 9514 adrl rIBASE, dvmAsmInstructionStart 9515 mov r2,#kJitSingleStep @ Ask for single step and then revert 9516 str r2,[rGLUE,#offGlue_jitState] 9517 mov r1,#1 @ set changeInterp to bail to debug interp 9518 b common_gotoBail 9519 9520/* 9521 * Return from the translation cache and immediately request 9522 * a translation for the exit target. Commonly used for callees. 9523 */ 9524 .global dvmJitToInterpTraceSelectNoChain 9525dvmJitToInterpTraceSelectNoChain: 9526#if defined(WITH_JIT_TUNING) 9527 bl dvmBumpNoChain 9528#endif 9529 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9530 mov r0,rPC 9531 bl dvmJitGetCodeAddr @ Is there a translation? 9532 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9533 mov r1, rPC @ arg1 of translation may need this 9534 mov lr, #0 @ in case target is HANDLER_INTERPRET 9535 cmp r0,#0 @ !0 means translation exists 9536 bxne r0 @ continue native execution if so 9537 b 2f @ branch over to use the interpreter 9538 9539/* 9540 * Return from the translation cache and immediately request 9541 * a translation for the exit target. Commonly used following 9542 * invokes. 9543 */ 9544 .global dvmJitToInterpTraceSelect 9545dvmJitToInterpTraceSelect: 9546 ldr rPC,[lr, #-1] @ get our target PC 9547 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9548 add rINST,lr,#-5 @ save start of chain branch 9549 add rINST, #-4 @ .. which is 9 bytes back 9550 mov r0,rPC 9551 bl dvmJitGetCodeAddr @ Is there a translation? 9552 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9553 cmp r0,#0 9554 beq 2f 9555 mov r1,rINST 9556 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9557 mov r1, rPC @ arg1 of translation may need this 9558 mov lr, #0 @ in case target is HANDLER_INTERPRET 9559 cmp r0,#0 @ successful chain? 9560 bxne r0 @ continue native execution 9561 b toInterpreter @ didn't chain - resume with interpreter 9562 9563/* No translation, so request one if profiling isn't disabled*/ 95642: 9565 adrl rIBASE, dvmAsmInstructionStart 9566 GET_JIT_PROF_TABLE(r0) 9567 FETCH_INST() 9568 cmp r0, #0 9569 movne r2,#kJitTSelectRequestHot @ ask for trace selection 9570 bne common_selectTrace 9571 GET_INST_OPCODE(ip) 9572 GOTO_OPCODE(ip) 9573 9574/* 9575 * Return from the translation cache to the interpreter. 9576 * The return was done with a BLX from thumb mode, and 9577 * the following 32-bit word contains the target rPC value. 9578 * Note that lr (r14) will have its low-order bit set to denote 9579 * its thumb-mode origin. 9580 * 9581 * We'll need to stash our lr origin away, recover the new 9582 * target and then check to see if there is a translation available 9583 * for our new target. If so, we do a translation chain and 9584 * go back to native execution. Otherwise, it's back to the 9585 * interpreter (after treating this entry as a potential 9586 * trace start). 9587 */ 9588 .global dvmJitToInterpNormal 9589dvmJitToInterpNormal: 9590 ldr rPC,[lr, #-1] @ get our target PC 9591 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9592 add rINST,lr,#-5 @ save start of chain branch 9593 add rINST,#-4 @ .. which is 9 bytes back 9594#if defined(WITH_JIT_TUNING) 9595 bl dvmBumpNormal 9596#endif 9597 mov r0,rPC 9598 bl dvmJitGetCodeAddr @ Is there a translation? 9599 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9600 cmp r0,#0 9601 beq toInterpreter @ go if not, otherwise do chain 9602 mov r1,rINST 9603 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9604 mov r1, rPC @ arg1 of translation may need this 9605 mov lr, #0 @ in case target is HANDLER_INTERPRET 9606 cmp r0,#0 @ successful chain? 9607 bxne r0 @ continue native execution 9608 b toInterpreter @ didn't chain - resume with interpreter 9609 9610/* 9611 * Return from the translation cache to the interpreter to do method invocation. 9612 * Check if translation exists for the callee, but don't chain to it. 9613 */ 9614 .global dvmJitToInterpNoChainNoProfile 9615dvmJitToInterpNoChainNoProfile: 9616#if defined(WITH_JIT_TUNING) 9617 bl dvmBumpNoChain 9618#endif 9619 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9620 mov r0,rPC 9621 bl dvmJitGetCodeAddr @ Is there a translation? 9622 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9623 mov r1, rPC @ arg1 of translation may need this 9624 mov lr, #0 @ in case target is HANDLER_INTERPRET 9625 cmp r0,#0 9626 bxne r0 @ continue native execution if so 9627 EXPORT_PC() 9628 adrl rIBASE, dvmAsmInstructionStart 9629 FETCH_INST() 9630 GET_INST_OPCODE(ip) @ extract opcode from rINST 9631 GOTO_OPCODE(ip) @ jump to next instruction 9632 9633/* 9634 * Return from the translation cache to the interpreter to do method invocation. 9635 * Check if translation exists for the callee, but don't chain to it. 9636 */ 9637 .global dvmJitToInterpNoChain 9638dvmJitToInterpNoChain: 9639#if defined(WITH_JIT_TUNING) 9640 bl dvmBumpNoChain 9641#endif 9642 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9643 mov r0,rPC 9644 bl dvmJitGetCodeAddr @ Is there a translation? 9645 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9646 mov r1, rPC @ arg1 of translation may need this 9647 mov lr, #0 @ in case target is HANDLER_INTERPRET 9648 cmp r0,#0 9649 bxne r0 @ continue native execution if so 9650#endif 9651 9652/* 9653 * No translation, restore interpreter regs and start interpreting. 9654 * rGLUE & rFP were preserved in the translated code, and rPC has 9655 * already been restored by the time we get here. We'll need to set 9656 * up rIBASE & rINST, and load the address of the JitTable into r0. 9657 */ 9658toInterpreter: 9659 EXPORT_PC() 9660 adrl rIBASE, dvmAsmInstructionStart 9661 FETCH_INST() 9662 GET_JIT_PROF_TABLE(r0) 9663 @ NOTE: intended fallthrough 9664 9665/* 9666 * Common code to update potential trace start counter, and initiate 9667 * a trace-build if appropriate. On entry, rPC should point to the 9668 * next instruction to execute, and rINST should be already loaded with 9669 * the next opcode word, and r0 holds a pointer to the jit profile 9670 * table (pJitProfTable). 9671 */ 9672common_testUpdateProfile: 9673 cmp r0,#0 9674 GET_INST_OPCODE(ip) 9675 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 9676 9677common_updateProfile: 9678 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 9679 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits 9680 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter 9681 GET_INST_OPCODE(ip) 9682 subs r1,r1,#1 @ decrement counter 9683 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it 9684 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 9685 9686/* 9687 * Here, we switch to the debug interpreter to request 9688 * trace selection. First, though, check to see if there 9689 * is already a native translation in place (and, if so, 9690 * jump to it now). 9691 */ 9692 GET_JIT_THRESHOLD(r1) 9693 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9694 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter 9695 EXPORT_PC() 9696 mov r0,rPC 9697 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC) 9698 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9699 mov r1, rPC @ arg1 of translation may need this 9700 mov lr, #0 @ in case target is HANDLER_INTERPRET 9701 cmp r0,#0 9702#if !defined(WITH_SELF_VERIFICATION) 9703 bxne r0 @ jump to the translation 9704 mov r2,#kJitTSelectRequest @ ask for trace selection 9705 @ fall-through to common_selectTrace 9706#else 9707 moveq r2,#kJitTSelectRequest @ ask for trace selection 9708 beq common_selectTrace 9709 /* 9710 * At this point, we have a target translation. However, if 9711 * that translation is actually the interpret-only pseudo-translation 9712 * we want to treat it the same as no translation. 9713 */ 9714 mov r10, r0 @ save target 9715 bl dvmCompilerGetInterpretTemplate 9716 cmp r0, r10 @ special case? 9717 bne jitSVShadowRunStart @ set up self verification shadow space 9718 @ Need to clear the inJitCodeCache flag 9719 ldr r10, [rGLUE, #offGlue_self] @ r10 <- glue->self 9720 mov r3, #0 @ 0 means not in the JIT code cache 9721 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land 9722 GET_INST_OPCODE(ip) 9723 GOTO_OPCODE(ip) 9724 /* no return */ 9725#endif 9726 9727/* 9728 * On entry: 9729 * r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot 9730 */ 9731common_selectTrace: 9732 str r2,[rGLUE,#offGlue_jitState] 9733 mov r2,#kInterpEntryInstr @ normal entry reason 9734 str r2,[rGLUE,#offGlue_entryPoint] 9735 mov r1,#1 @ set changeInterp 9736 b common_gotoBail 9737 9738#if defined(WITH_SELF_VERIFICATION) 9739/* 9740 * Save PC and registers to shadow memory for self verification mode 9741 * before jumping to native translation. 9742 * On entry: 9743 * rPC, rFP, rGLUE: the values that they should contain 9744 * r10: the address of the target translation. 9745 */ 9746jitSVShadowRunStart: 9747 mov r0,rPC @ r0<- program counter 9748 mov r1,rFP @ r1<- frame pointer 9749 mov r2,rGLUE @ r2<- InterpState pointer 9750 mov r3,r10 @ r3<- target translation 9751 bl dvmSelfVerificationSaveState @ save registers to shadow space 9752 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 9753 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 9754 bx r10 @ jump to the translation 9755 9756/* 9757 * Restore PC, registers, and interpState to original values 9758 * before jumping back to the interpreter. 9759 */ 9760jitSVShadowRunEnd: 9761 mov r1,rFP @ pass ending fp 9762 bl dvmSelfVerificationRestoreState @ restore pc and fp values 9763 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 9764 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 9765 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 9766 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 9767 cmp r1,#0 @ check for punt condition 9768 beq 1f 9769 mov r2,#kJitSelfVerification @ ask for self verification 9770 str r2,[rGLUE,#offGlue_jitState] 9771 mov r2,#kInterpEntryInstr @ normal entry reason 9772 str r2,[rGLUE,#offGlue_entryPoint] 9773 mov r1,#1 @ set changeInterp 9774 b common_gotoBail 9775 97761: @ exit to interpreter without check 9777 EXPORT_PC() 9778 adrl rIBASE, dvmAsmInstructionStart 9779 FETCH_INST() 9780 GET_INST_OPCODE(ip) 9781 GOTO_OPCODE(ip) 9782#endif 9783 9784#endif 9785 9786/* 9787 * Common code when a backward branch is taken. 9788 * 9789 * TODO: we could avoid a branch by just setting r0 and falling through 9790 * into the common_periodicChecks code, and having a test on r0 at the 9791 * end determine if we should return to the caller or update & branch to 9792 * the next instr. 9793 * 9794 * On entry: 9795 * r9 is PC adjustment *in bytes* 9796 */ 9797common_backwardBranch: 9798 mov r0, #kInterpEntryInstr 9799 bl common_periodicChecks 9800#if defined(WITH_JIT) 9801 GET_JIT_PROF_TABLE(r0) 9802 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9803 cmp r0,#0 9804 bne common_updateProfile 9805 GET_INST_OPCODE(ip) 9806 GOTO_OPCODE(ip) 9807#else 9808 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9809 GET_INST_OPCODE(ip) @ extract opcode from rINST 9810 GOTO_OPCODE(ip) @ jump to next instruction 9811#endif 9812 9813 9814/* 9815 * Need to see if the thread needs to be suspended or debugger/profiler 9816 * activity has begun. If so, we suspend the thread or side-exit to 9817 * the debug interpreter as appropriate. 9818 * 9819 * The common case is no activity on any of these, so we want to figure 9820 * that out quickly. If something is up, we can then sort out what. 9821 * 9822 * We want to be fast if the VM was built without debugger or profiler 9823 * support, but we also need to recognize that the system is usually 9824 * shipped with both of these enabled. 9825 * 9826 * TODO: reduce this so we're just checking a single location. 9827 * 9828 * On entry: 9829 * r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling) 9830 * r9 is trampoline PC adjustment *in bytes* 9831 */ 9832common_periodicChecks: 9833 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9834 9835 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9836 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9837 9838 ldr ip, [r3] @ ip<- suspendCount (int) 9839 9840 cmp r1, #0 @ debugger enabled? 9841#if defined(WORKAROUND_CORTEX_A9_745320) 9842 /* Don't use conditional loads if the HW defect exists */ 9843 beq 101f 9844 ldrb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9845101: 9846#else 9847 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9848#endif 9849 ldr r2, [r2] @ r2<- activeProfilers (int) 9850 orrnes ip, ip, r1 @ ip<- suspendCount | debuggerActive 9851 /* 9852 * Don't switch the interpreter in the libdvm_traceview build even if the 9853 * profiler is active. 9854 * The code here is opted for less intrusion instead of performance. 9855 * That is, *pActiveProfilers is still loaded into r2 even though it is not 9856 * used when WITH_INLINE_PROFILING is defined. 9857 */ 9858#if !defined(WITH_INLINE_PROFILING) 9859 orrs ip, ip, r2 @ ip<- suspend|debugger|profiler; set Z 9860#endif 9861 9862 9863 bxeq lr @ all zero, return 9864 9865 /* 9866 * One or more interesting events have happened. Figure out what. 9867 * 9868 * If debugging or profiling are compiled in, we need to disambiguate. 9869 * 9870 * r0 still holds the reentry type. 9871 */ 9872 ldr ip, [r3] @ ip<- suspendCount (int) 9873 cmp ip, #0 @ want suspend? 9874 beq 1f @ no, must be debugger/profiler 9875 9876 stmfd sp!, {r0, lr} @ preserve r0 and lr 9877#if defined(WITH_JIT) 9878 /* 9879 * Refresh the Jit's cached copy of profile table pointer. This pointer 9880 * doubles as the Jit's on/off switch. 9881 */ 9882 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable 9883 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9884 ldr r3, [r3] @ r3 <- pJitProfTable 9885 EXPORT_PC() @ need for precise GC 9886 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch 9887#else 9888 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9889 EXPORT_PC() @ need for precise GC 9890#endif 9891 bl dvmCheckSuspendPending @ do full check, suspend if necessary 9892 ldmfd sp!, {r0, lr} @ restore r0 and lr 9893 9894 /* 9895 * Reload the debugger/profiler enable flags. We're checking to see 9896 * if either of these got set while we were suspended. 9897 * 9898 * If WITH_INLINE_PROFILING is configured, don't check whether the profiler 9899 * is enabled or not as the profiling will be done inline. 9900 */ 9901 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9902 cmp r1, #0 @ debugger enabled? 9903#if defined(WORKAROUND_CORTEX_A9_745320) 9904 /* Don't use conditional loads if the HW defect exists */ 9905 beq 101f 9906 ldrb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9907101: 9908#else 9909 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9910#endif 9911 9912#if !defined(WITH_INLINE_PROFILING) 9913 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9914 ldr r2, [r2] @ r2<- activeProfilers (int) 9915 orrs r1, r1, r2 9916#else 9917 cmp r1, #0 @ only consult the debuggerActive flag 9918#endif 9919 9920 beq 2f 9921 99221: @ debugger/profiler enabled, bail out; glue->entryPoint was set above 9923 str r0, [rGLUE, #offGlue_entryPoint] @ store r0, need for debug/prof 9924 add rPC, rPC, r9 @ update rPC 9925 mov r1, #1 @ "want switch" = true 9926 b common_gotoBail @ side exit 9927 99282: 9929 bx lr @ nothing to do, return 9930 9931 9932/* 9933 * The equivalent of "goto bail", this calls through the "bail handler". 9934 * 9935 * State registers will be saved to the "glue" area before bailing. 9936 * 9937 * On entry: 9938 * r1 is "bool changeInterp", indicating if we want to switch to the 9939 * other interpreter or just bail all the way out 9940 */ 9941common_gotoBail: 9942 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9943 mov r0, rGLUE @ r0<- glue ptr 9944 b dvmMterpStdBail @ call(glue, changeInterp) 9945 9946 @add r1, r1, #1 @ using (boolean+1) 9947 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9948 @bl _longjmp @ does not return 9949 @bl common_abort 9950 9951 9952/* 9953 * Common code for method invocation with range. 9954 * 9955 * On entry: 9956 * r0 is "Method* methodToCall", the method we're trying to call 9957 */ 9958common_invokeMethodRange: 9959.LinvokeNewRange: 9960 @ prepare to copy args to "outs" area of current frame 9961 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9962 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9963 beq .LinvokeArgsDone @ if no args, skip the rest 9964 FETCH(r1, 2) @ r1<- CCCC 9965 9966 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9967 @ (very few methods have > 10 args; could unroll for common cases) 9968 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9969 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9970 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 99711: ldr r1, [r3], #4 @ val = *fp++ 9972 subs r2, r2, #1 @ count-- 9973 str r1, [r10], #4 @ *outs++ = val 9974 bne 1b @ ...while count != 0 9975 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9976 b .LinvokeArgsDone 9977 9978/* 9979 * Common code for method invocation without range. 9980 * 9981 * On entry: 9982 * r0 is "Method* methodToCall", the method we're trying to call 9983 */ 9984common_invokeMethodNoRange: 9985.LinvokeNewNoRange: 9986 @ prepare to copy args to "outs" area of current frame 9987 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9988 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9989 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9990 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9991 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9992 beq .LinvokeArgsDone 9993 9994 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9995.LinvokeNonRange: 9996 rsb r2, r2, #5 @ r2<- 5-r2 9997 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9998 bl common_abort @ (skipped due to ARM prefetch) 99995: and ip, rINST, #0x0f00 @ isolate A 10000 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 10001 mov r0, r0 @ nop 10002 str r2, [r10, #-4]! @ *--outs = vA 100034: and ip, r1, #0xf000 @ isolate G 10004 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 10005 mov r0, r0 @ nop 10006 str r2, [r10, #-4]! @ *--outs = vG 100073: and ip, r1, #0x0f00 @ isolate F 10008 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 10009 mov r0, r0 @ nop 10010 str r2, [r10, #-4]! @ *--outs = vF 100112: and ip, r1, #0x00f0 @ isolate E 10012 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 10013 mov r0, r0 @ nop 10014 str r2, [r10, #-4]! @ *--outs = vE 100151: and ip, r1, #0x000f @ isolate D 10016 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 10017 mov r0, r0 @ nop 10018 str r2, [r10, #-4]! @ *--outs = vD 100190: @ fall through to .LinvokeArgsDone 10020 10021.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 10022 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 10023 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 10024 @ find space for the new stack frame, check for overflow 10025 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 10026 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 10027 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 10028@ bl common_dumpRegs 10029 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 10030 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 10031 cmp r3, r9 @ bottom < interpStackEnd? 10032 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 10033 blo .LstackOverflow @ yes, this frame will overflow stack 10034 10035 @ set up newSaveArea 10036#ifdef EASY_GDB 10037 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 10038 str ip, [r10, #offStackSaveArea_prevSave] 10039#endif 10040 str rFP, [r10, #offStackSaveArea_prevFrame] 10041 str rPC, [r10, #offStackSaveArea_savedPc] 10042#if defined(WITH_JIT) 10043 mov r9, #0 10044 str r9, [r10, #offStackSaveArea_returnAddr] 10045#endif 10046#if defined(WITH_INLINE_PROFILING) 10047 stmfd sp!, {r0-r3} @ preserve r0-r3 10048 mov r1, r6 10049 @ r0=methodToCall, r1=rGlue 10050 bl dvmFastMethodTraceEnter 10051 ldmfd sp!, {r0-r3} @ restore r0-r3 10052#endif 10053 str r0, [r10, #offStackSaveArea_method] 10054 tst r3, #ACC_NATIVE 10055 bne .LinvokeNative 10056 10057 /* 10058 stmfd sp!, {r0-r3} 10059 bl common_printNewline 10060 mov r0, rFP 10061 mov r1, #0 10062 bl dvmDumpFp 10063 ldmfd sp!, {r0-r3} 10064 stmfd sp!, {r0-r3} 10065 mov r0, r1 10066 mov r1, r10 10067 bl dvmDumpFp 10068 bl common_printNewline 10069 ldmfd sp!, {r0-r3} 10070 */ 10071 10072 ldrh r9, [r2] @ r9 <- load INST from new PC 10073 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 10074 mov rPC, r2 @ publish new rPC 10075 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 10076 10077 @ Update "glue" values for the new method 10078 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 10079 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 10080 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 10081#if defined(WITH_JIT) 10082 GET_JIT_PROF_TABLE(r0) 10083 mov rFP, r1 @ fp = newFp 10084 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 10085 mov rINST, r9 @ publish new rINST 10086 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 10087 cmp r0,#0 10088 bne common_updateProfile 10089 GOTO_OPCODE(ip) @ jump to next instruction 10090#else 10091 mov rFP, r1 @ fp = newFp 10092 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 10093 mov rINST, r9 @ publish new rINST 10094 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 10095 GOTO_OPCODE(ip) @ jump to next instruction 10096#endif 10097 10098.LinvokeNative: 10099 @ Prep for the native call 10100 @ r0=methodToCall, r1=newFp, r10=newSaveArea 10101 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10102 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 10103 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 10104 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 10105 mov r9, r3 @ r9<- glue->self (preserve) 10106 10107 mov r2, r0 @ r2<- methodToCall 10108 mov r0, r1 @ r0<- newFp (points to args) 10109 add r1, rGLUE, #offGlue_retval @ r1<- &retval 10110 10111#ifdef ASSIST_DEBUGGER 10112 /* insert fake function header to help gdb find the stack frame */ 10113 b .Lskip 10114 .type dalvik_mterp, %function 10115dalvik_mterp: 10116 .fnstart 10117 MTERP_ENTRY1 10118 MTERP_ENTRY2 10119.Lskip: 10120#endif 10121 10122#if defined(WITH_INLINE_PROFILING) 10123 @ r2=JNIMethod, r6=rGLUE 10124 stmfd sp!, {r2,r6} 10125#endif 10126 10127 @mov lr, pc @ set return addr 10128 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 10129 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 10130 10131#if defined(WITH_INLINE_PROFILING) 10132 @ r0=JNIMethod, r1=rGLUE 10133 ldmfd sp!, {r0-r1} 10134 bl dvmFastNativeMethodTraceExit 10135#endif 10136 10137#if defined(WITH_JIT) 10138 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status 10139#endif 10140 10141 @ native return; r9=self, r10=newSaveArea 10142 @ equivalent to dvmPopJniLocals 10143 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 10144 ldr r1, [r9, #offThread_exception] @ check for exception 10145#if defined(WITH_JIT) 10146 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable 10147#endif 10148 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 10149 cmp r1, #0 @ null? 10150 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 10151#if defined(WITH_JIT) 10152 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch 10153#endif 10154 bne common_exceptionThrown @ no, handle exception 10155 10156 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 10157 GET_INST_OPCODE(ip) @ extract opcode from rINST 10158 GOTO_OPCODE(ip) @ jump to next instruction 10159 10160.LstackOverflow: @ r0=methodToCall 10161 mov r1, r0 @ r1<- methodToCall 10162 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 10163 bl dvmHandleStackOverflow 10164 b common_exceptionThrown 10165#ifdef ASSIST_DEBUGGER 10166 .fnend 10167#endif 10168 10169 10170 /* 10171 * Common code for method invocation, calling through "glue code". 10172 * 10173 * TODO: now that we have range and non-range invoke handlers, this 10174 * needs to be split into two. Maybe just create entry points 10175 * that set r9 and jump here? 10176 * 10177 * On entry: 10178 * r0 is "Method* methodToCall", the method we're trying to call 10179 * r9 is "bool methodCallRange", indicating if this is a /range variant 10180 */ 10181 .if 0 10182.LinvokeOld: 10183 sub sp, sp, #8 @ space for args + pad 10184 FETCH(ip, 2) @ ip<- FEDC or CCCC 10185 mov r2, r0 @ A2<- methodToCall 10186 mov r0, rGLUE @ A0<- glue 10187 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 10188 mov r1, r9 @ A1<- methodCallRange 10189 mov r3, rINST, lsr #8 @ A3<- AA 10190 str ip, [sp, #0] @ A4<- ip 10191 bl dvmMterp_invokeMethod @ call the C invokeMethod 10192 add sp, sp, #8 @ remove arg area 10193 b common_resumeAfterGlueCall @ continue to next instruction 10194 .endif 10195 10196 10197 10198/* 10199 * Common code for handling a return instruction. 10200 * 10201 * This does not return. 10202 */ 10203common_returnFromMethod: 10204.LreturnNew: 10205 mov r0, #kInterpEntryReturn 10206 mov r9, #0 10207 bl common_periodicChecks 10208 10209#if defined(WITH_INLINE_PROFILING) 10210 stmfd sp!, {r0-r3} @ preserve r0-r3 10211 mov r0, r6 10212 @ r0=rGlue 10213 bl dvmFastJavaMethodTraceExit 10214 ldmfd sp!, {r0-r3} @ restore r0-r3 10215#endif 10216 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 10217 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 10218 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 10219 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 10220 @ r2<- method we're returning to 10221 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10222 cmp r2, #0 @ is this a break frame? 10223#if defined(WORKAROUND_CORTEX_A9_745320) 10224 /* Don't use conditional loads if the HW defect exists */ 10225 beq 101f 10226 ldr r10, [r2, #offMethod_clazz] @ r10<- method->clazz 10227101: 10228#else 10229 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 10230#endif 10231 mov r1, #0 @ "want switch" = false 10232 beq common_gotoBail @ break frame, bail out completely 10233 10234 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 10235 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 10236 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 10237 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 10238#if defined(WITH_JIT) 10239 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr 10240 mov rPC, r9 @ publish new rPC 10241 str r1, [rGLUE, #offGlue_methodClassDex] 10242 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land 10243 cmp r10, #0 @ caller is compiled code 10244 blxne r10 10245 GET_INST_OPCODE(ip) @ extract opcode from rINST 10246 GOTO_OPCODE(ip) @ jump to next instruction 10247#else 10248 GET_INST_OPCODE(ip) @ extract opcode from rINST 10249 mov rPC, r9 @ publish new rPC 10250 str r1, [rGLUE, #offGlue_methodClassDex] 10251 GOTO_OPCODE(ip) @ jump to next instruction 10252#endif 10253 10254 /* 10255 * Return handling, calls through "glue code". 10256 */ 10257 .if 0 10258.LreturnOld: 10259 SAVE_PC_FP_TO_GLUE() @ export state 10260 mov r0, rGLUE @ arg to function 10261 bl dvmMterp_returnFromMethod 10262 b common_resumeAfterGlueCall 10263 .endif 10264 10265 10266/* 10267 * Somebody has thrown an exception. Handle it. 10268 * 10269 * If the exception processing code returns to us (instead of falling 10270 * out of the interpreter), continue with whatever the next instruction 10271 * now happens to be. 10272 * 10273 * This does not return. 10274 */ 10275 .global dvmMterpCommonExceptionThrown 10276dvmMterpCommonExceptionThrown: 10277common_exceptionThrown: 10278.LexceptionNew: 10279 mov r0, #kInterpEntryThrow 10280 mov r9, #0 10281 bl common_periodicChecks 10282 10283 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 10284 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 10285 mov r1, r10 @ r1<- self 10286 mov r0, r9 @ r0<- exception 10287 bl dvmAddTrackedAlloc @ don't let the exception be GCed 10288 mov r3, #0 @ r3<- NULL 10289 str r3, [r10, #offThread_exception] @ self->exception = NULL 10290 10291 /* set up args and a local for "&fp" */ 10292 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 10293 str rFP, [sp, #-4]! @ *--sp = fp 10294 mov ip, sp @ ip<- &fp 10295 mov r3, #0 @ r3<- false 10296 str ip, [sp, #-4]! @ *--sp = &fp 10297 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 10298 mov r0, r10 @ r0<- self 10299 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 10300 mov r2, r9 @ r2<- exception 10301 sub r1, rPC, r1 @ r1<- pc - method->insns 10302 mov r1, r1, asr #1 @ r1<- offset in code units 10303 10304 /* call, r0 gets catchRelPc (a code-unit offset) */ 10305 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 10306 10307 /* fix earlier stack overflow if necessary; may trash rFP */ 10308 ldrb r1, [r10, #offThread_stackOverflowed] 10309 cmp r1, #0 @ did we overflow earlier? 10310 beq 1f @ no, skip ahead 10311 mov rFP, r0 @ save relPc result in rFP 10312 mov r0, r10 @ r0<- self 10313 mov r1, r9 @ r1<- exception 10314 bl dvmCleanupStackOverflow @ call(self) 10315 mov r0, rFP @ restore result 103161: 10317 10318 /* update frame pointer and check result from dvmFindCatchBlock */ 10319 ldr rFP, [sp, #4] @ retrieve the updated rFP 10320 cmp r0, #0 @ is catchRelPc < 0? 10321 add sp, sp, #8 @ restore stack 10322 bmi .LnotCaughtLocally 10323 10324 /* adjust locals to match self->curFrame and updated PC */ 10325 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 10326 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 10327 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 10328 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 10329 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 10330 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 10331 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 10332 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 10333 10334 /* release the tracked alloc on the exception */ 10335 mov r0, r9 @ r0<- exception 10336 mov r1, r10 @ r1<- self 10337 bl dvmReleaseTrackedAlloc @ release the exception 10338 10339 /* restore the exception if the handler wants it */ 10340 FETCH_INST() @ load rINST from rPC 10341 GET_INST_OPCODE(ip) @ extract opcode from rINST 10342 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 10343 streq r9, [r10, #offThread_exception] @ yes, restore the exception 10344 GOTO_OPCODE(ip) @ jump to next instruction 10345 10346.LnotCaughtLocally: @ r9=exception, r10=self 10347 /* fix stack overflow if necessary */ 10348 ldrb r1, [r10, #offThread_stackOverflowed] 10349 cmp r1, #0 @ did we overflow earlier? 10350 movne r0, r10 @ if yes: r0<- self 10351 movne r1, r9 @ if yes: r1<- exception 10352 blne dvmCleanupStackOverflow @ if yes: call(self) 10353 10354 @ may want to show "not caught locally" debug messages here 10355#if DVM_SHOW_EXCEPTION >= 2 10356 /* call __android_log_print(prio, tag, format, ...) */ 10357 /* "Exception %s from %s:%d not caught locally" */ 10358 @ dvmLineNumFromPC(method, pc - method->insns) 10359 ldr r0, [rGLUE, #offGlue_method] 10360 ldr r1, [r0, #offMethod_insns] 10361 sub r1, rPC, r1 10362 asr r1, r1, #1 10363 bl dvmLineNumFromPC 10364 str r0, [sp, #-4]! 10365 @ dvmGetMethodSourceFile(method) 10366 ldr r0, [rGLUE, #offGlue_method] 10367 bl dvmGetMethodSourceFile 10368 str r0, [sp, #-4]! 10369 @ exception->clazz->descriptor 10370 ldr r3, [r9, #offObject_clazz] 10371 ldr r3, [r3, #offClassObject_descriptor] 10372 @ 10373 ldr r2, strExceptionNotCaughtLocally 10374 ldr r1, strLogTag 10375 mov r0, #3 @ LOG_DEBUG 10376 bl __android_log_print 10377#endif 10378 str r9, [r10, #offThread_exception] @ restore exception 10379 mov r0, r9 @ r0<- exception 10380 mov r1, r10 @ r1<- self 10381 bl dvmReleaseTrackedAlloc @ release the exception 10382 mov r1, #0 @ "want switch" = false 10383 b common_gotoBail @ bail out 10384 10385 10386 /* 10387 * Exception handling, calls through "glue code". 10388 */ 10389 .if 0 10390.LexceptionOld: 10391 SAVE_PC_FP_TO_GLUE() @ export state 10392 mov r0, rGLUE @ arg to function 10393 bl dvmMterp_exceptionThrown 10394 b common_resumeAfterGlueCall 10395 .endif 10396 10397 10398/* 10399 * After returning from a "glued" function, pull out the updated 10400 * values and start executing at the next instruction. 10401 */ 10402common_resumeAfterGlueCall: 10403 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 10404 FETCH_INST() @ load rINST from rPC 10405 GET_INST_OPCODE(ip) @ extract opcode from rINST 10406 GOTO_OPCODE(ip) @ jump to next instruction 10407 10408/* 10409 * Invalid array index. 10410 */ 10411common_errArrayIndex: 10412 EXPORT_PC() 10413 ldr r0, strArrayIndexException 10414 mov r1, #0 10415 bl dvmThrowException 10416 b common_exceptionThrown 10417 10418/* 10419 * Invalid array value. 10420 */ 10421common_errArrayStore: 10422 EXPORT_PC() 10423 ldr r0, strArrayStoreException 10424 mov r1, #0 10425 bl dvmThrowException 10426 b common_exceptionThrown 10427 10428/* 10429 * Integer divide or mod by zero. 10430 */ 10431common_errDivideByZero: 10432 EXPORT_PC() 10433 ldr r0, strArithmeticException 10434 ldr r1, strDivideByZero 10435 bl dvmThrowException 10436 b common_exceptionThrown 10437 10438/* 10439 * Attempt to allocate an array with a negative size. 10440 */ 10441common_errNegativeArraySize: 10442 EXPORT_PC() 10443 ldr r0, strNegativeArraySizeException 10444 mov r1, #0 10445 bl dvmThrowException 10446 b common_exceptionThrown 10447 10448/* 10449 * Invocation of a non-existent method. 10450 */ 10451common_errNoSuchMethod: 10452 EXPORT_PC() 10453 ldr r0, strNoSuchMethodError 10454 mov r1, #0 10455 bl dvmThrowException 10456 b common_exceptionThrown 10457 10458/* 10459 * We encountered a null object when we weren't expecting one. We 10460 * export the PC, throw a NullPointerException, and goto the exception 10461 * processing code. 10462 */ 10463common_errNullObject: 10464 EXPORT_PC() 10465 ldr r0, strNullPointerException 10466 mov r1, #0 10467 bl dvmThrowException 10468 b common_exceptionThrown 10469 10470/* 10471 * For debugging, cause an immediate fault. The source address will 10472 * be in lr (use a bl instruction to jump here). 10473 */ 10474common_abort: 10475 ldr pc, .LdeadFood 10476.LdeadFood: 10477 .word 0xdeadf00d 10478 10479/* 10480 * Spit out a "we were here", preserving all registers. (The attempt 10481 * to save ip won't work, but we need to save an even number of 10482 * registers for EABI 64-bit stack alignment.) 10483 */ 10484 .macro SQUEAK num 10485common_squeak\num: 10486 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10487 ldr r0, strSqueak 10488 mov r1, #\num 10489 bl printf 10490 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10491 bx lr 10492 .endm 10493 10494 SQUEAK 0 10495 SQUEAK 1 10496 SQUEAK 2 10497 SQUEAK 3 10498 SQUEAK 4 10499 SQUEAK 5 10500 10501/* 10502 * Spit out the number in r0, preserving registers. 10503 */ 10504common_printNum: 10505 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10506 mov r1, r0 10507 ldr r0, strSqueak 10508 bl printf 10509 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10510 bx lr 10511 10512/* 10513 * Print a newline, preserving registers. 10514 */ 10515common_printNewline: 10516 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10517 ldr r0, strNewline 10518 bl printf 10519 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10520 bx lr 10521 10522 /* 10523 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 10524 */ 10525common_printHex: 10526 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10527 mov r1, r0 10528 ldr r0, strPrintHex 10529 bl printf 10530 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10531 bx lr 10532 10533/* 10534 * Print the 64-bit quantity in r0-r1, preserving registers. 10535 */ 10536common_printLong: 10537 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10538 mov r3, r1 10539 mov r2, r0 10540 ldr r0, strPrintLong 10541 bl printf 10542 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10543 bx lr 10544 10545/* 10546 * Print full method info. Pass the Method* in r0. Preserves regs. 10547 */ 10548common_printMethod: 10549 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10550 bl dvmMterpPrintMethod 10551 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10552 bx lr 10553 10554/* 10555 * Call a C helper function that dumps regs and possibly some 10556 * additional info. Requires the C function to be compiled in. 10557 */ 10558 .if 0 10559common_dumpRegs: 10560 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10561 bl dvmMterpDumpArmRegs 10562 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10563 bx lr 10564 .endif 10565 10566#if 0 10567/* 10568 * Experiment on VFP mode. 10569 * 10570 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 10571 * 10572 * Updates the bits specified by "mask", setting them to the values in "val". 10573 */ 10574setFPSCR: 10575 and r0, r0, r1 @ make sure no stray bits are set 10576 fmrx r2, fpscr @ get VFP reg 10577 mvn r1, r1 @ bit-invert mask 10578 and r2, r2, r1 @ clear masked bits 10579 orr r2, r2, r0 @ set specified bits 10580 fmxr fpscr, r2 @ set VFP reg 10581 mov r0, r2 @ return new value 10582 bx lr 10583 10584 .align 2 10585 .global dvmConfigureFP 10586 .type dvmConfigureFP, %function 10587dvmConfigureFP: 10588 stmfd sp!, {ip, lr} 10589 /* 0x03000000 sets DN/FZ */ 10590 /* 0x00009f00 clears the six exception enable flags */ 10591 bl common_squeak0 10592 mov r0, #0x03000000 @ r0<- 0x03000000 10593 add r1, r0, #0x9f00 @ r1<- 0x03009f00 10594 bl setFPSCR 10595 ldmfd sp!, {ip, pc} 10596#endif 10597 10598 10599/* 10600 * String references, must be close to the code that uses them. 10601 */ 10602 .align 2 10603strArithmeticException: 10604 .word .LstrArithmeticException 10605strArrayIndexException: 10606 .word .LstrArrayIndexException 10607strArrayStoreException: 10608 .word .LstrArrayStoreException 10609strDivideByZero: 10610 .word .LstrDivideByZero 10611strNegativeArraySizeException: 10612 .word .LstrNegativeArraySizeException 10613strNoSuchMethodError: 10614 .word .LstrNoSuchMethodError 10615strNullPointerException: 10616 .word .LstrNullPointerException 10617 10618strLogTag: 10619 .word .LstrLogTag 10620strExceptionNotCaughtLocally: 10621 .word .LstrExceptionNotCaughtLocally 10622 10623strNewline: 10624 .word .LstrNewline 10625strSqueak: 10626 .word .LstrSqueak 10627strPrintHex: 10628 .word .LstrPrintHex 10629strPrintLong: 10630 .word .LstrPrintLong 10631 10632/* 10633 * Zero-terminated ASCII string data. 10634 * 10635 * On ARM we have two choices: do like gcc does, and LDR from a .word 10636 * with the address, or use an ADR pseudo-op to get the address 10637 * directly. ADR saves 4 bytes and an indirection, but it's using a 10638 * PC-relative addressing mode and hence has a limited range, which 10639 * makes it not work well with mergeable string sections. 10640 */ 10641 .section .rodata.str1.4,"aMS",%progbits,1 10642 10643.LstrBadEntryPoint: 10644 .asciz "Bad entry point %d\n" 10645.LstrArithmeticException: 10646 .asciz "Ljava/lang/ArithmeticException;" 10647.LstrArrayIndexException: 10648 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 10649.LstrArrayStoreException: 10650 .asciz "Ljava/lang/ArrayStoreException;" 10651.LstrClassCastException: 10652 .asciz "Ljava/lang/ClassCastException;" 10653.LstrDivideByZero: 10654 .asciz "divide by zero" 10655.LstrFilledNewArrayNotImpl: 10656 .asciz "filled-new-array only implemented for objects and 'int'" 10657.LstrInternalError: 10658 .asciz "Ljava/lang/InternalError;" 10659.LstrInstantiationError: 10660 .asciz "Ljava/lang/InstantiationError;" 10661.LstrNegativeArraySizeException: 10662 .asciz "Ljava/lang/NegativeArraySizeException;" 10663.LstrNoSuchMethodError: 10664 .asciz "Ljava/lang/NoSuchMethodError;" 10665.LstrNullPointerException: 10666 .asciz "Ljava/lang/NullPointerException;" 10667 10668.LstrLogTag: 10669 .asciz "mterp" 10670.LstrExceptionNotCaughtLocally: 10671 .asciz "Exception %s from %s:%d not caught locally\n" 10672 10673.LstrNewline: 10674 .asciz "\n" 10675.LstrSqueak: 10676 .asciz "<%d>" 10677.LstrPrintHex: 10678 .asciz "<0x%x>" 10679.LstrPrintLong: 10680 .asciz "<%lld>" 10681 10682