InterpAsm-armv5te-vfp.S revision 291758c5c4902900c6f86794ba8ab9cad9b26197
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/* File: armv5te/entry.S */ 253/* 254 * Copyright (C) 2008 The Android Open Source Project 255 * 256 * Licensed under the Apache License, Version 2.0 (the "License"); 257 * you may not use this file except in compliance with the License. 258 * You may obtain a copy of the License at 259 * 260 * http://www.apache.org/licenses/LICENSE-2.0 261 * 262 * Unless required by applicable law or agreed to in writing, software 263 * distributed under the License is distributed on an "AS IS" BASIS, 264 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 265 * See the License for the specific language governing permissions and 266 * limitations under the License. 267 */ 268/* 269 * Interpreter entry point. 270 */ 271 272/* 273 * We don't have formal stack frames, so gdb scans upward in the code 274 * to find the start of the function (a label with the %function type), 275 * and then looks at the next few instructions to figure out what 276 * got pushed onto the stack. From this it figures out how to restore 277 * the registers, including PC, for the previous stack frame. If gdb 278 * sees a non-function label, it stops scanning, so either we need to 279 * have nothing but assembler-local labels between the entry point and 280 * the break, or we need to fake it out. 281 * 282 * When this is defined, we add some stuff to make gdb less confused. 283 */ 284#define ASSIST_DEBUGGER 1 285 286 .text 287 .align 2 288 .global dvmMterpStdRun 289 .type dvmMterpStdRun, %function 290 291/* 292 * On entry: 293 * r0 MterpGlue* glue 294 * 295 * This function returns a boolean "changeInterp" value. The return comes 296 * via a call to dvmMterpStdBail(). 297 */ 298dvmMterpStdRun: 299#define MTERP_ENTRY1 \ 300 .save {r4-r10,fp,lr}; \ 301 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs 302#define MTERP_ENTRY2 \ 303 .pad #4; \ 304 sub sp, sp, #4 @ align 64 305 306 .fnstart 307 MTERP_ENTRY1 308 MTERP_ENTRY2 309 310 /* save stack pointer, add magic word for debuggerd */ 311 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return 312 313 /* set up "named" registers, figure out entry point */ 314 mov rGLUE, r0 @ set rGLUE 315 ldr r1, [r0, #offGlue_entryPoint] @ enum is 4 bytes in aapcs-EABI 316 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue" 317 adr rIBASE, dvmAsmInstructionStart @ set rIBASE 318 cmp r1, #kInterpEntryInstr @ usual case? 319 bne .Lnot_instr @ no, handle it 320 321#if defined(WITH_JIT) 322.LentryInstr: 323 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 324 /* Entry is always a possible trace start */ 325 GET_JIT_PROF_TABLE(r0) 326 FETCH_INST() 327 mov r1, #0 @ prepare the value for the new state 328 str r1, [r10, #offThread_inJitCodeCache] @ back to the interp land 329 cmp r0,#0 @ is profiling disabled? 330#if !defined(WITH_SELF_VERIFICATION) 331 bne common_updateProfile @ profiling is enabled 332#else 333 ldr r2, [r10, #offThread_shadowSpace] @ to find out the jit exit state 334 beq 1f @ profiling is disabled 335 ldr r3, [r2, #offShadowSpace_jitExitState] @ jit exit state 336 cmp r3, #kSVSTraceSelect @ hot trace following? 337 moveq r2,#kJitTSelectRequestHot @ ask for trace selection 338 beq common_selectTrace @ go build the trace 339 cmp r3, #kSVSNoProfile @ don't profile the next instruction? 340 beq 1f @ intrepret the next instruction 341 b common_updateProfile @ collect profiles 342#endif 3431: 344 GET_INST_OPCODE(ip) 345 GOTO_OPCODE(ip) 346#else 347 /* start executing the instruction at rPC */ 348 FETCH_INST() @ load rINST from rPC 349 GET_INST_OPCODE(ip) @ extract opcode from rINST 350 GOTO_OPCODE(ip) @ jump to next instruction 351#endif 352 353.Lnot_instr: 354 cmp r1, #kInterpEntryReturn @ were we returning from a method? 355 beq common_returnFromMethod 356 357.Lnot_return: 358 cmp r1, #kInterpEntryThrow @ were we throwing an exception? 359 beq common_exceptionThrown 360 361#if defined(WITH_JIT) 362.Lnot_throw: 363 ldr r10,[rGLUE, #offGlue_jitResumeNPC] 364 ldr r2,[rGLUE, #offGlue_jitResumeDPC] 365 cmp r1, #kInterpEntryResume @ resuming after Jit single-step? 366 bne .Lbad_arg 367 cmp rPC,r2 368 bne .LentryInstr @ must have branched, don't resume 369#if defined(WITH_SELF_VERIFICATION) 370 @ glue->entryPoint will be set in dvmSelfVerificationSaveState 371 b jitSVShadowRunStart @ re-enter the translation after the 372 @ single-stepped instruction 373 @noreturn 374#endif 375 mov r1, #kInterpEntryInstr 376 str r1, [rGLUE, #offGlue_entryPoint] 377 bx r10 @ re-enter the translation 378#endif 379 380.Lbad_arg: 381 ldr r0, strBadEntryPoint 382 @ r1 holds value of entryPoint 383 bl printf 384 bl dvmAbort 385 .fnend 386 387 388 .global dvmMterpStdBail 389 .type dvmMterpStdBail, %function 390 391/* 392 * Restore the stack pointer and PC from the save point established on entry. 393 * This is essentially the same as a longjmp, but should be cheaper. The 394 * last instruction causes us to return to whoever called dvmMterpStdRun. 395 * 396 * We pushed some registers on the stack in dvmMterpStdRun, then saved 397 * SP and LR. Here we restore SP, restore the registers, and then restore 398 * LR to PC. 399 * 400 * On entry: 401 * r0 MterpGlue* glue 402 * r1 bool changeInterp 403 */ 404dvmMterpStdBail: 405 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 406 mov r0, r1 @ return the changeInterp value 407 add sp, sp, #4 @ un-align 64 408 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return 409 410 411/* 412 * String references. 413 */ 414strBadEntryPoint: 415 .word .LstrBadEntryPoint 416 417 418 .global dvmAsmInstructionStart 419 .type dvmAsmInstructionStart, %function 420dvmAsmInstructionStart = .L_OP_NOP 421 .text 422 423/* ------------------------------ */ 424 .balign 64 425.L_OP_NOP: /* 0x00 */ 426/* File: armv5te/OP_NOP.S */ 427 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST 428 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 429 GOTO_OPCODE(ip) @ execute it 430 431#ifdef ASSIST_DEBUGGER 432 /* insert fake function header to help gdb find the stack frame */ 433 .type dalvik_inst, %function 434dalvik_inst: 435 .fnstart 436 MTERP_ENTRY1 437 MTERP_ENTRY2 438 .fnend 439#endif 440 441/* ------------------------------ */ 442 .balign 64 443.L_OP_MOVE: /* 0x01 */ 444/* File: armv5te/OP_MOVE.S */ 445 /* for move, move-object, long-to-int */ 446 /* op vA, vB */ 447 mov r1, rINST, lsr #12 @ r1<- B from 15:12 448 mov r0, rINST, lsr #8 @ r0<- A from 11:8 449 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 450 GET_VREG(r2, r1) @ r2<- fp[B] 451 and r0, r0, #15 452 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 453 SET_VREG(r2, r0) @ fp[A]<- r2 454 GOTO_OPCODE(ip) @ execute next instruction 455 456/* ------------------------------ */ 457 .balign 64 458.L_OP_MOVE_FROM16: /* 0x02 */ 459/* File: armv5te/OP_MOVE_FROM16.S */ 460 /* for: move/from16, move-object/from16 */ 461 /* op vAA, vBBBB */ 462 FETCH(r1, 1) @ r1<- BBBB 463 mov r0, rINST, lsr #8 @ r0<- AA 464 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 465 GET_VREG(r2, r1) @ r2<- fp[BBBB] 466 GET_INST_OPCODE(ip) @ extract opcode from rINST 467 SET_VREG(r2, r0) @ fp[AA]<- r2 468 GOTO_OPCODE(ip) @ jump to next instruction 469 470/* ------------------------------ */ 471 .balign 64 472.L_OP_MOVE_16: /* 0x03 */ 473/* File: armv5te/OP_MOVE_16.S */ 474 /* for: move/16, move-object/16 */ 475 /* op vAAAA, vBBBB */ 476 FETCH(r1, 2) @ r1<- BBBB 477 FETCH(r0, 1) @ r0<- AAAA 478 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 479 GET_VREG(r2, r1) @ r2<- fp[BBBB] 480 GET_INST_OPCODE(ip) @ extract opcode from rINST 481 SET_VREG(r2, r0) @ fp[AAAA]<- r2 482 GOTO_OPCODE(ip) @ jump to next instruction 483 484/* ------------------------------ */ 485 .balign 64 486.L_OP_MOVE_WIDE: /* 0x04 */ 487/* File: armv5te/OP_MOVE_WIDE.S */ 488 /* move-wide vA, vB */ 489 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 490 mov r2, rINST, lsr #8 @ r2<- A(+) 491 mov r3, rINST, lsr #12 @ r3<- B 492 and r2, r2, #15 493 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 494 add r2, rFP, r2, lsl #2 @ r2<- &fp[A] 495 ldmia r3, {r0-r1} @ r0/r1<- fp[B] 496 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 497 GET_INST_OPCODE(ip) @ extract opcode from rINST 498 stmia r2, {r0-r1} @ fp[A]<- r0/r1 499 GOTO_OPCODE(ip) @ jump to next instruction 500 501/* ------------------------------ */ 502 .balign 64 503.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 504/* File: armv5te/OP_MOVE_WIDE_FROM16.S */ 505 /* move-wide/from16 vAA, vBBBB */ 506 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 507 FETCH(r3, 1) @ r3<- BBBB 508 mov r2, rINST, lsr #8 @ r2<- AA 509 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 510 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 511 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 512 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 513 GET_INST_OPCODE(ip) @ extract opcode from rINST 514 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 515 GOTO_OPCODE(ip) @ jump to next instruction 516 517/* ------------------------------ */ 518 .balign 64 519.L_OP_MOVE_WIDE_16: /* 0x06 */ 520/* File: armv5te/OP_MOVE_WIDE_16.S */ 521 /* move-wide/16 vAAAA, vBBBB */ 522 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 523 FETCH(r3, 2) @ r3<- BBBB 524 FETCH(r2, 1) @ r2<- AAAA 525 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 526 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA] 527 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 528 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 529 GET_INST_OPCODE(ip) @ extract opcode from rINST 530 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1 531 GOTO_OPCODE(ip) @ jump to next instruction 532 533/* ------------------------------ */ 534 .balign 64 535.L_OP_MOVE_OBJECT: /* 0x07 */ 536/* File: armv5te/OP_MOVE_OBJECT.S */ 537/* File: armv5te/OP_MOVE.S */ 538 /* for move, move-object, long-to-int */ 539 /* op vA, vB */ 540 mov r1, rINST, lsr #12 @ r1<- B from 15:12 541 mov r0, rINST, lsr #8 @ r0<- A from 11:8 542 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 543 GET_VREG(r2, r1) @ r2<- fp[B] 544 and r0, r0, #15 545 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 546 SET_VREG(r2, r0) @ fp[A]<- r2 547 GOTO_OPCODE(ip) @ execute next instruction 548 549 550/* ------------------------------ */ 551 .balign 64 552.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 553/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */ 554/* File: armv5te/OP_MOVE_FROM16.S */ 555 /* for: move/from16, move-object/from16 */ 556 /* op vAA, vBBBB */ 557 FETCH(r1, 1) @ r1<- BBBB 558 mov r0, rINST, lsr #8 @ r0<- AA 559 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 560 GET_VREG(r2, r1) @ r2<- fp[BBBB] 561 GET_INST_OPCODE(ip) @ extract opcode from rINST 562 SET_VREG(r2, r0) @ fp[AA]<- r2 563 GOTO_OPCODE(ip) @ jump to next instruction 564 565 566/* ------------------------------ */ 567 .balign 64 568.L_OP_MOVE_OBJECT_16: /* 0x09 */ 569/* File: armv5te/OP_MOVE_OBJECT_16.S */ 570/* File: armv5te/OP_MOVE_16.S */ 571 /* for: move/16, move-object/16 */ 572 /* op vAAAA, vBBBB */ 573 FETCH(r1, 2) @ r1<- BBBB 574 FETCH(r0, 1) @ r0<- AAAA 575 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 576 GET_VREG(r2, r1) @ r2<- fp[BBBB] 577 GET_INST_OPCODE(ip) @ extract opcode from rINST 578 SET_VREG(r2, r0) @ fp[AAAA]<- r2 579 GOTO_OPCODE(ip) @ jump to next instruction 580 581 582/* ------------------------------ */ 583 .balign 64 584.L_OP_MOVE_RESULT: /* 0x0a */ 585/* File: armv5te/OP_MOVE_RESULT.S */ 586 /* for: move-result, move-result-object */ 587 /* op vAA */ 588 mov r2, rINST, lsr #8 @ r2<- AA 589 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 590 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 591 GET_INST_OPCODE(ip) @ extract opcode from rINST 592 SET_VREG(r0, r2) @ fp[AA]<- r0 593 GOTO_OPCODE(ip) @ jump to next instruction 594 595/* ------------------------------ */ 596 .balign 64 597.L_OP_MOVE_RESULT_WIDE: /* 0x0b */ 598/* File: armv5te/OP_MOVE_RESULT_WIDE.S */ 599 /* move-result-wide vAA */ 600 mov r2, rINST, lsr #8 @ r2<- AA 601 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 602 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 603 ldmia r3, {r0-r1} @ r0/r1<- retval.j 604 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 605 GET_INST_OPCODE(ip) @ extract opcode from rINST 606 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 607 GOTO_OPCODE(ip) @ jump to next instruction 608 609/* ------------------------------ */ 610 .balign 64 611.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 612/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */ 613/* File: armv5te/OP_MOVE_RESULT.S */ 614 /* for: move-result, move-result-object */ 615 /* op vAA */ 616 mov r2, rINST, lsr #8 @ r2<- AA 617 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 618 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 619 GET_INST_OPCODE(ip) @ extract opcode from rINST 620 SET_VREG(r0, r2) @ fp[AA]<- r0 621 GOTO_OPCODE(ip) @ jump to next instruction 622 623 624/* ------------------------------ */ 625 .balign 64 626.L_OP_MOVE_EXCEPTION: /* 0x0d */ 627/* File: armv5te/OP_MOVE_EXCEPTION.S */ 628 /* move-exception vAA */ 629 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 630 mov r2, rINST, lsr #8 @ r2<- AA 631 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass 632 mov r1, #0 @ r1<- 0 633 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 634 SET_VREG(r3, r2) @ fp[AA]<- exception obj 635 GET_INST_OPCODE(ip) @ extract opcode from rINST 636 str r1, [r0, #offThread_exception] @ dvmClearException bypass 637 GOTO_OPCODE(ip) @ jump to next instruction 638 639/* ------------------------------ */ 640 .balign 64 641.L_OP_RETURN_VOID: /* 0x0e */ 642/* File: armv5te/OP_RETURN_VOID.S */ 643 b common_returnFromMethod 644 645/* ------------------------------ */ 646 .balign 64 647.L_OP_RETURN: /* 0x0f */ 648/* File: armv5te/OP_RETURN.S */ 649 /* 650 * Return a 32-bit value. Copies the return value into the "glue" 651 * structure, then jumps to the return handler. 652 * 653 * for: return, return-object 654 */ 655 /* op vAA */ 656 mov r2, rINST, lsr #8 @ r2<- AA 657 GET_VREG(r0, r2) @ r0<- vAA 658 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 659 b common_returnFromMethod 660 661/* ------------------------------ */ 662 .balign 64 663.L_OP_RETURN_WIDE: /* 0x10 */ 664/* File: armv5te/OP_RETURN_WIDE.S */ 665 /* 666 * Return a 64-bit value. Copies the return value into the "glue" 667 * structure, then jumps to the return handler. 668 */ 669 /* return-wide vAA */ 670 mov r2, rINST, lsr #8 @ r2<- AA 671 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 672 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 673 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1 674 stmia r3, {r0-r1} @ retval<- r0/r1 675 b common_returnFromMethod 676 677/* ------------------------------ */ 678 .balign 64 679.L_OP_RETURN_OBJECT: /* 0x11 */ 680/* File: armv5te/OP_RETURN_OBJECT.S */ 681/* File: armv5te/OP_RETURN.S */ 682 /* 683 * Return a 32-bit value. Copies the return value into the "glue" 684 * structure, then jumps to the return handler. 685 * 686 * for: return, return-object 687 */ 688 /* op vAA */ 689 mov r2, rINST, lsr #8 @ r2<- AA 690 GET_VREG(r0, r2) @ r0<- vAA 691 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 692 b common_returnFromMethod 693 694 695/* ------------------------------ */ 696 .balign 64 697.L_OP_CONST_4: /* 0x12 */ 698/* File: armv5te/OP_CONST_4.S */ 699 /* const/4 vA, #+B */ 700 mov r1, rINST, lsl #16 @ r1<- Bxxx0000 701 mov r0, rINST, lsr #8 @ r0<- A+ 702 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 703 mov r1, r1, asr #28 @ r1<- sssssssB (sign-extended) 704 and r0, r0, #15 705 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 706 SET_VREG(r1, r0) @ fp[A]<- r1 707 GOTO_OPCODE(ip) @ execute next instruction 708 709/* ------------------------------ */ 710 .balign 64 711.L_OP_CONST_16: /* 0x13 */ 712/* File: armv5te/OP_CONST_16.S */ 713 /* const/16 vAA, #+BBBB */ 714 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 715 mov r3, rINST, lsr #8 @ r3<- AA 716 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 717 SET_VREG(r0, r3) @ vAA<- r0 718 GET_INST_OPCODE(ip) @ extract opcode from rINST 719 GOTO_OPCODE(ip) @ jump to next instruction 720 721/* ------------------------------ */ 722 .balign 64 723.L_OP_CONST: /* 0x14 */ 724/* File: armv5te/OP_CONST.S */ 725 /* const vAA, #+BBBBbbbb */ 726 mov r3, rINST, lsr #8 @ r3<- AA 727 FETCH(r0, 1) @ r0<- bbbb (low) 728 FETCH(r1, 2) @ r1<- BBBB (high) 729 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 730 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 731 GET_INST_OPCODE(ip) @ extract opcode from rINST 732 SET_VREG(r0, r3) @ vAA<- r0 733 GOTO_OPCODE(ip) @ jump to next instruction 734 735/* ------------------------------ */ 736 .balign 64 737.L_OP_CONST_HIGH16: /* 0x15 */ 738/* File: armv5te/OP_CONST_HIGH16.S */ 739 /* const/high16 vAA, #+BBBB0000 */ 740 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended) 741 mov r3, rINST, lsr #8 @ r3<- AA 742 mov r0, r0, lsl #16 @ r0<- BBBB0000 743 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 744 SET_VREG(r0, r3) @ vAA<- r0 745 GET_INST_OPCODE(ip) @ extract opcode from rINST 746 GOTO_OPCODE(ip) @ jump to next instruction 747 748/* ------------------------------ */ 749 .balign 64 750.L_OP_CONST_WIDE_16: /* 0x16 */ 751/* File: armv5te/OP_CONST_WIDE_16.S */ 752 /* const-wide/16 vAA, #+BBBB */ 753 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 754 mov r3, rINST, lsr #8 @ r3<- AA 755 mov r1, r0, asr #31 @ r1<- ssssssss 756 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 757 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 758 GET_INST_OPCODE(ip) @ extract opcode from rINST 759 stmia r3, {r0-r1} @ vAA<- r0/r1 760 GOTO_OPCODE(ip) @ jump to next instruction 761 762/* ------------------------------ */ 763 .balign 64 764.L_OP_CONST_WIDE_32: /* 0x17 */ 765/* File: armv5te/OP_CONST_WIDE_32.S */ 766 /* const-wide/32 vAA, #+BBBBbbbb */ 767 FETCH(r0, 1) @ r0<- 0000bbbb (low) 768 mov r3, rINST, lsr #8 @ r3<- AA 769 FETCH_S(r2, 2) @ r2<- ssssBBBB (high) 770 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 771 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb 772 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 773 mov r1, r0, asr #31 @ r1<- ssssssss 774 GET_INST_OPCODE(ip) @ extract opcode from rINST 775 stmia r3, {r0-r1} @ vAA<- r0/r1 776 GOTO_OPCODE(ip) @ jump to next instruction 777 778/* ------------------------------ */ 779 .balign 64 780.L_OP_CONST_WIDE: /* 0x18 */ 781/* File: armv5te/OP_CONST_WIDE.S */ 782 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 783 FETCH(r0, 1) @ r0<- bbbb (low) 784 FETCH(r1, 2) @ r1<- BBBB (low middle) 785 FETCH(r2, 3) @ r2<- hhhh (high middle) 786 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word) 787 FETCH(r3, 4) @ r3<- HHHH (high) 788 mov r9, rINST, lsr #8 @ r9<- AA 789 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word) 790 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 791 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 792 GET_INST_OPCODE(ip) @ extract opcode from rINST 793 stmia r9, {r0-r1} @ vAA<- r0/r1 794 GOTO_OPCODE(ip) @ jump to next instruction 795 796/* ------------------------------ */ 797 .balign 64 798.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 799/* File: armv5te/OP_CONST_WIDE_HIGH16.S */ 800 /* const-wide/high16 vAA, #+BBBB000000000000 */ 801 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended) 802 mov r3, rINST, lsr #8 @ r3<- AA 803 mov r0, #0 @ r0<- 00000000 804 mov r1, r1, lsl #16 @ r1<- BBBB0000 805 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 806 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 807 GET_INST_OPCODE(ip) @ extract opcode from rINST 808 stmia r3, {r0-r1} @ vAA<- r0/r1 809 GOTO_OPCODE(ip) @ jump to next instruction 810 811/* ------------------------------ */ 812 .balign 64 813.L_OP_CONST_STRING: /* 0x1a */ 814/* File: armv5te/OP_CONST_STRING.S */ 815 /* const/string vAA, String@BBBB */ 816 FETCH(r1, 1) @ r1<- BBBB 817 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 818 mov r9, rINST, lsr #8 @ r9<- AA 819 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 820 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 821 cmp r0, #0 @ not yet resolved? 822 beq .LOP_CONST_STRING_resolve 823 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 824 GET_INST_OPCODE(ip) @ extract opcode from rINST 825 SET_VREG(r0, r9) @ vAA<- r0 826 GOTO_OPCODE(ip) @ jump to next instruction 827 828/* ------------------------------ */ 829 .balign 64 830.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 831/* File: armv5te/OP_CONST_STRING_JUMBO.S */ 832 /* const/string vAA, String@BBBBBBBB */ 833 FETCH(r0, 1) @ r0<- bbbb (low) 834 FETCH(r1, 2) @ r1<- BBBB (high) 835 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 836 mov r9, rINST, lsr #8 @ r9<- AA 837 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 838 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 839 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 840 cmp r0, #0 841 beq .LOP_CONST_STRING_JUMBO_resolve 842 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 843 GET_INST_OPCODE(ip) @ extract opcode from rINST 844 SET_VREG(r0, r9) @ vAA<- r0 845 GOTO_OPCODE(ip) @ jump to next instruction 846 847/* ------------------------------ */ 848 .balign 64 849.L_OP_CONST_CLASS: /* 0x1c */ 850/* File: armv5te/OP_CONST_CLASS.S */ 851 /* const/class vAA, Class@BBBB */ 852 FETCH(r1, 1) @ r1<- BBBB 853 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 854 mov r9, rINST, lsr #8 @ r9<- AA 855 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 856 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB] 857 cmp r0, #0 @ not yet resolved? 858 beq .LOP_CONST_CLASS_resolve 859 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 860 GET_INST_OPCODE(ip) @ extract opcode from rINST 861 SET_VREG(r0, r9) @ vAA<- r0 862 GOTO_OPCODE(ip) @ jump to next instruction 863 864/* ------------------------------ */ 865 .balign 64 866.L_OP_MONITOR_ENTER: /* 0x1d */ 867/* File: armv5te/OP_MONITOR_ENTER.S */ 868 /* 869 * Synchronize on an object. 870 */ 871 /* monitor-enter vAA */ 872 mov r2, rINST, lsr #8 @ r2<- AA 873 GET_VREG(r1, r2) @ r1<- vAA (object) 874 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 875 cmp r1, #0 @ null object? 876 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING 877 beq common_errNullObject @ null object, throw an exception 878 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 879 bl dvmLockObject @ call(self, obj) 880#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ 881 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 882 ldr r1, [r0, #offThread_exception] @ check for exception 883 cmp r1, #0 884 bne common_exceptionThrown @ exception raised, bail out 885#endif 886 GET_INST_OPCODE(ip) @ extract opcode from rINST 887 GOTO_OPCODE(ip) @ jump to next instruction 888 889/* ------------------------------ */ 890 .balign 64 891.L_OP_MONITOR_EXIT: /* 0x1e */ 892/* File: armv5te/OP_MONITOR_EXIT.S */ 893 /* 894 * Unlock an object. 895 * 896 * Exceptions that occur when unlocking a monitor need to appear as 897 * if they happened at the following instruction. See the Dalvik 898 * instruction spec. 899 */ 900 /* monitor-exit vAA */ 901 mov r2, rINST, lsr #8 @ r2<- AA 902 EXPORT_PC() @ before fetch: export the PC 903 GET_VREG(r1, r2) @ r1<- vAA (object) 904 cmp r1, #0 @ null object? 905 beq 1f @ yes 906 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 907 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 908 cmp r0, #0 @ failed? 909 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 910 beq common_exceptionThrown @ yes, exception is pending 911 GET_INST_OPCODE(ip) @ extract opcode from rINST 912 GOTO_OPCODE(ip) @ jump to next instruction 9131: 914 FETCH_ADVANCE_INST(1) @ advance before throw 915 b common_errNullObject 916 917/* ------------------------------ */ 918 .balign 64 919.L_OP_CHECK_CAST: /* 0x1f */ 920/* File: armv5te/OP_CHECK_CAST.S */ 921 /* 922 * Check to see if a cast from one class to another is allowed. 923 */ 924 /* check-cast vAA, class@BBBB */ 925 mov r3, rINST, lsr #8 @ r3<- AA 926 FETCH(r2, 1) @ r2<- BBBB 927 GET_VREG(r9, r3) @ r9<- object 928 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 929 cmp r9, #0 @ is object null? 930 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 931 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 932 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 933 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 934 cmp r1, #0 @ have we resolved this before? 935 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 936.LOP_CHECK_CAST_resolved: 937 cmp r0, r1 @ same class (trivial success)? 938 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 939.LOP_CHECK_CAST_okay: 940 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 941 GET_INST_OPCODE(ip) @ extract opcode from rINST 942 GOTO_OPCODE(ip) @ jump to next instruction 943 944/* ------------------------------ */ 945 .balign 64 946.L_OP_INSTANCE_OF: /* 0x20 */ 947/* File: armv5te/OP_INSTANCE_OF.S */ 948 /* 949 * Check to see if an object reference is an instance of a class. 950 * 951 * Most common situation is a non-null object, being compared against 952 * an already-resolved class. 953 */ 954 /* instance-of vA, vB, class@CCCC */ 955 mov r3, rINST, lsr #12 @ r3<- B 956 mov r9, rINST, lsr #8 @ r9<- A+ 957 GET_VREG(r0, r3) @ r0<- vB (object) 958 and r9, r9, #15 @ r9<- A 959 cmp r0, #0 @ is object null? 960 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 961 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 962 FETCH(r3, 1) @ r3<- CCCC 963 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 964 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 965 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 966 cmp r1, #0 @ have we resolved this before? 967 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 968.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 969 cmp r0, r1 @ same class (trivial success)? 970 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 971 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 972 973/* ------------------------------ */ 974 .balign 64 975.L_OP_ARRAY_LENGTH: /* 0x21 */ 976/* File: armv5te/OP_ARRAY_LENGTH.S */ 977 /* 978 * Return the length of an array. 979 */ 980 mov r1, rINST, lsr #12 @ r1<- B 981 mov r2, rINST, lsr #8 @ r2<- A+ 982 GET_VREG(r0, r1) @ r0<- vB (object ref) 983 and r2, r2, #15 @ r2<- A 984 cmp r0, #0 @ is object null? 985 beq common_errNullObject @ yup, fail 986 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 987 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 988 GET_INST_OPCODE(ip) @ extract opcode from rINST 989 SET_VREG(r3, r2) @ vB<- length 990 GOTO_OPCODE(ip) @ jump to next instruction 991 992/* ------------------------------ */ 993 .balign 64 994.L_OP_NEW_INSTANCE: /* 0x22 */ 995/* File: armv5te/OP_NEW_INSTANCE.S */ 996 /* 997 * Create a new instance of a class. 998 */ 999 /* new-instance vAA, class@BBBB */ 1000 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1001 FETCH(r1, 1) @ r1<- BBBB 1002 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1003 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1004 EXPORT_PC() @ req'd for init, resolve, alloc 1005 cmp r0, #0 @ already resolved? 1006 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 1007.LOP_NEW_INSTANCE_resolved: @ r0=class 1008 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 1009 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 1010 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 1011.LOP_NEW_INSTANCE_initialized: @ r0=class 1012 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 1013 bl dvmAllocObject @ r0<- new object 1014 b .LOP_NEW_INSTANCE_finish @ continue 1015 1016/* ------------------------------ */ 1017 .balign 64 1018.L_OP_NEW_ARRAY: /* 0x23 */ 1019/* File: armv5te/OP_NEW_ARRAY.S */ 1020 /* 1021 * Allocate an array of objects, specified with the array class 1022 * and a count. 1023 * 1024 * The verifier guarantees that this is an array class, so we don't 1025 * check for it here. 1026 */ 1027 /* new-array vA, vB, class@CCCC */ 1028 mov r0, rINST, lsr #12 @ r0<- B 1029 FETCH(r2, 1) @ r2<- CCCC 1030 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1031 GET_VREG(r1, r0) @ r1<- vB (array length) 1032 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1033 cmp r1, #0 @ check length 1034 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 1035 bmi common_errNegativeArraySize @ negative length, bail 1036 cmp r0, #0 @ already resolved? 1037 EXPORT_PC() @ req'd for resolve, alloc 1038 bne .LOP_NEW_ARRAY_finish @ resolved, continue 1039 b .LOP_NEW_ARRAY_resolve @ do resolve now 1040 1041/* ------------------------------ */ 1042 .balign 64 1043.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1044/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1045 /* 1046 * Create a new array with elements filled from registers. 1047 * 1048 * for: filled-new-array, filled-new-array/range 1049 */ 1050 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1051 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1052 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1053 FETCH(r1, 1) @ r1<- BBBB 1054 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1055 EXPORT_PC() @ need for resolve and alloc 1056 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1057 mov r10, rINST, lsr #8 @ r10<- AA or BA 1058 cmp r0, #0 @ already resolved? 1059 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10608: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1061 mov r2, #0 @ r2<- false 1062 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1063 bl dvmResolveClass @ r0<- call(clazz, ref) 1064 cmp r0, #0 @ got null? 1065 beq common_exceptionThrown @ yes, handle exception 1066 b .LOP_FILLED_NEW_ARRAY_continue 1067 1068/* ------------------------------ */ 1069 .balign 64 1070.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1071/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1072/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1073 /* 1074 * Create a new array with elements filled from registers. 1075 * 1076 * for: filled-new-array, filled-new-array/range 1077 */ 1078 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1079 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1080 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1081 FETCH(r1, 1) @ r1<- BBBB 1082 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1083 EXPORT_PC() @ need for resolve and alloc 1084 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1085 mov r10, rINST, lsr #8 @ r10<- AA or BA 1086 cmp r0, #0 @ already resolved? 1087 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10888: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1089 mov r2, #0 @ r2<- false 1090 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1091 bl dvmResolveClass @ r0<- call(clazz, ref) 1092 cmp r0, #0 @ got null? 1093 beq common_exceptionThrown @ yes, handle exception 1094 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1095 1096 1097/* ------------------------------ */ 1098 .balign 64 1099.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1100/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1101 /* fill-array-data vAA, +BBBBBBBB */ 1102 FETCH(r0, 1) @ r0<- bbbb (lo) 1103 FETCH(r1, 2) @ r1<- BBBB (hi) 1104 mov r3, rINST, lsr #8 @ r3<- AA 1105 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1106 GET_VREG(r0, r3) @ r0<- vAA (array object) 1107 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1108 EXPORT_PC(); 1109 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1110 cmp r0, #0 @ 0 means an exception is thrown 1111 beq common_exceptionThrown @ has exception 1112 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1113 GET_INST_OPCODE(ip) @ extract opcode from rINST 1114 GOTO_OPCODE(ip) @ jump to next instruction 1115 1116/* ------------------------------ */ 1117 .balign 64 1118.L_OP_THROW: /* 0x27 */ 1119/* File: armv5te/OP_THROW.S */ 1120 /* 1121 * Throw an exception object in the current thread. 1122 */ 1123 /* throw vAA */ 1124 mov r2, rINST, lsr #8 @ r2<- AA 1125 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1126 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1127 EXPORT_PC() @ exception handler can throw 1128 cmp r1, #0 @ null object? 1129 beq common_errNullObject @ yes, throw an NPE instead 1130 @ bypass dvmSetException, just store it 1131 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1132 b common_exceptionThrown 1133 1134/* ------------------------------ */ 1135 .balign 64 1136.L_OP_GOTO: /* 0x28 */ 1137/* File: armv5te/OP_GOTO.S */ 1138 /* 1139 * Unconditional branch, 8-bit offset. 1140 * 1141 * The branch distance is a signed code-unit offset, which we need to 1142 * double to get a byte offset. 1143 */ 1144 /* goto +AA */ 1145 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1146 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1147 mov r9, r9, lsl #1 @ r9<- byte offset 1148 bmi common_backwardBranch @ backward branch, do periodic checks 1149#if defined(WITH_JIT) 1150 GET_JIT_PROF_TABLE(r0) 1151 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1152 cmp r0,#0 1153 bne common_updateProfile 1154 GET_INST_OPCODE(ip) @ extract opcode from rINST 1155 GOTO_OPCODE(ip) @ jump to next instruction 1156#else 1157 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1158 GET_INST_OPCODE(ip) @ extract opcode from rINST 1159 GOTO_OPCODE(ip) @ jump to next instruction 1160#endif 1161 1162/* ------------------------------ */ 1163 .balign 64 1164.L_OP_GOTO_16: /* 0x29 */ 1165/* File: armv5te/OP_GOTO_16.S */ 1166 /* 1167 * Unconditional branch, 16-bit offset. 1168 * 1169 * The branch distance is a signed code-unit offset, which we need to 1170 * double to get a byte offset. 1171 */ 1172 /* goto/16 +AAAA */ 1173 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1174 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1175 bmi common_backwardBranch @ backward branch, do periodic checks 1176#if defined(WITH_JIT) 1177 GET_JIT_PROF_TABLE(r0) 1178 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1179 cmp r0,#0 1180 bne common_updateProfile 1181 GET_INST_OPCODE(ip) @ extract opcode from rINST 1182 GOTO_OPCODE(ip) @ jump to next instruction 1183#else 1184 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1185 GET_INST_OPCODE(ip) @ extract opcode from rINST 1186 GOTO_OPCODE(ip) @ jump to next instruction 1187#endif 1188 1189/* ------------------------------ */ 1190 .balign 64 1191.L_OP_GOTO_32: /* 0x2a */ 1192/* File: armv5te/OP_GOTO_32.S */ 1193 /* 1194 * Unconditional branch, 32-bit offset. 1195 * 1196 * The branch distance is a signed code-unit offset, which we need to 1197 * double to get a byte offset. 1198 * 1199 * Unlike most opcodes, this one is allowed to branch to itself, so 1200 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1201 * instruction doesn't affect the V flag, so we need to clear it 1202 * explicitly. 1203 */ 1204 /* goto/32 +AAAAAAAA */ 1205 FETCH(r0, 1) @ r0<- aaaa (lo) 1206 FETCH(r1, 2) @ r1<- AAAA (hi) 1207 cmp ip, ip @ (clear V flag during stall) 1208 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1209 mov r9, r0, asl #1 @ r9<- byte offset 1210 ble common_backwardBranch @ backward branch, do periodic checks 1211#if defined(WITH_JIT) 1212 GET_JIT_PROF_TABLE(r0) 1213 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1214 cmp r0,#0 1215 bne common_updateProfile 1216 GET_INST_OPCODE(ip) @ extract opcode from rINST 1217 GOTO_OPCODE(ip) @ jump to next instruction 1218#else 1219 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1220 GET_INST_OPCODE(ip) @ extract opcode from rINST 1221 GOTO_OPCODE(ip) @ jump to next instruction 1222#endif 1223 1224/* ------------------------------ */ 1225 .balign 64 1226.L_OP_PACKED_SWITCH: /* 0x2b */ 1227/* File: armv5te/OP_PACKED_SWITCH.S */ 1228 /* 1229 * Handle a packed-switch or sparse-switch instruction. In both cases 1230 * we decode it and hand it off to a helper function. 1231 * 1232 * We don't really expect backward branches in a switch statement, but 1233 * they're perfectly legal, so we check for them here. 1234 * 1235 * for: packed-switch, sparse-switch 1236 */ 1237 /* op vAA, +BBBB */ 1238 FETCH(r0, 1) @ r0<- bbbb (lo) 1239 FETCH(r1, 2) @ r1<- BBBB (hi) 1240 mov r3, rINST, lsr #8 @ r3<- AA 1241 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1242 GET_VREG(r1, r3) @ r1<- vAA 1243 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1244 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1245 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1246 bmi common_backwardBranch @ backward branch, do periodic checks 1247 beq common_backwardBranch @ (want to use BLE but V is unknown) 1248#if defined(WITH_JIT) 1249 GET_JIT_PROF_TABLE(r0) 1250 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1251 cmp r0,#0 1252 bne common_updateProfile 1253 GET_INST_OPCODE(ip) @ extract opcode from rINST 1254 GOTO_OPCODE(ip) @ jump to next instruction 1255#else 1256 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1257 GET_INST_OPCODE(ip) @ extract opcode from rINST 1258 GOTO_OPCODE(ip) @ jump to next instruction 1259#endif 1260 1261/* ------------------------------ */ 1262 .balign 64 1263.L_OP_SPARSE_SWITCH: /* 0x2c */ 1264/* File: armv5te/OP_SPARSE_SWITCH.S */ 1265/* File: armv5te/OP_PACKED_SWITCH.S */ 1266 /* 1267 * Handle a packed-switch or sparse-switch instruction. In both cases 1268 * we decode it and hand it off to a helper function. 1269 * 1270 * We don't really expect backward branches in a switch statement, but 1271 * they're perfectly legal, so we check for them here. 1272 * 1273 * for: packed-switch, sparse-switch 1274 */ 1275 /* op vAA, +BBBB */ 1276 FETCH(r0, 1) @ r0<- bbbb (lo) 1277 FETCH(r1, 2) @ r1<- BBBB (hi) 1278 mov r3, rINST, lsr #8 @ r3<- AA 1279 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1280 GET_VREG(r1, r3) @ r1<- vAA 1281 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1282 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1283 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1284 bmi common_backwardBranch @ backward branch, do periodic checks 1285 beq common_backwardBranch @ (want to use BLE but V is unknown) 1286#if defined(WITH_JIT) 1287 GET_JIT_PROF_TABLE(r0) 1288 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1289 cmp r0,#0 1290 bne common_updateProfile 1291 GET_INST_OPCODE(ip) @ extract opcode from rINST 1292 GOTO_OPCODE(ip) @ jump to next instruction 1293#else 1294 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1295 GET_INST_OPCODE(ip) @ extract opcode from rINST 1296 GOTO_OPCODE(ip) @ jump to next instruction 1297#endif 1298 1299 1300/* ------------------------------ */ 1301 .balign 64 1302.L_OP_CMPL_FLOAT: /* 0x2d */ 1303/* File: arm-vfp/OP_CMPL_FLOAT.S */ 1304 /* 1305 * Compare two floating-point values. Puts 0, 1, or -1 into the 1306 * destination register based on the results of the comparison. 1307 * 1308 * int compare(x, y) { 1309 * if (x == y) { 1310 * return 0; 1311 * } else if (x > y) { 1312 * return 1; 1313 * } else if (x < y) { 1314 * return -1; 1315 * } else { 1316 * return -1; 1317 * } 1318 * } 1319 */ 1320 /* op vAA, vBB, vCC */ 1321 FETCH(r0, 1) @ r0<- CCBB 1322 mov r9, rINST, lsr #8 @ r9<- AA 1323 and r2, r0, #255 @ r2<- BB 1324 mov r3, r0, lsr #8 @ r3<- CC 1325 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1326 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1327 flds s0, [r2] @ s0<- vBB 1328 flds s1, [r3] @ s1<- vCC 1329 fcmpes s0, s1 @ compare (vBB, vCC) 1330 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1331 mvn r0, #0 @ r0<- -1 (default) 1332 GET_INST_OPCODE(ip) @ extract opcode from rINST 1333 fmstat @ export status flags 1334 movgt r0, #1 @ (greater than) r1<- 1 1335 moveq r0, #0 @ (equal) r1<- 0 1336 b .LOP_CMPL_FLOAT_finish @ argh 1337 1338 1339/* ------------------------------ */ 1340 .balign 64 1341.L_OP_CMPG_FLOAT: /* 0x2e */ 1342/* File: arm-vfp/OP_CMPG_FLOAT.S */ 1343 /* 1344 * Compare two floating-point values. Puts 0, 1, or -1 into the 1345 * destination register based on the results of the comparison. 1346 * 1347 * int compare(x, y) { 1348 * if (x == y) { 1349 * return 0; 1350 * } else if (x < y) { 1351 * return -1; 1352 * } else if (x > y) { 1353 * return 1; 1354 * } else { 1355 * return 1; 1356 * } 1357 * } 1358 */ 1359 /* op vAA, vBB, vCC */ 1360 FETCH(r0, 1) @ r0<- CCBB 1361 mov r9, rINST, lsr #8 @ r9<- AA 1362 and r2, r0, #255 @ r2<- BB 1363 mov r3, r0, lsr #8 @ r3<- CC 1364 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1365 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1366 flds s0, [r2] @ s0<- vBB 1367 flds s1, [r3] @ s1<- vCC 1368 fcmpes s0, s1 @ compare (vBB, vCC) 1369 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1370 mov r0, #1 @ r0<- 1 (default) 1371 GET_INST_OPCODE(ip) @ extract opcode from rINST 1372 fmstat @ export status flags 1373 mvnmi r0, #0 @ (less than) r1<- -1 1374 moveq r0, #0 @ (equal) r1<- 0 1375 b .LOP_CMPG_FLOAT_finish @ argh 1376 1377 1378/* ------------------------------ */ 1379 .balign 64 1380.L_OP_CMPL_DOUBLE: /* 0x2f */ 1381/* File: arm-vfp/OP_CMPL_DOUBLE.S */ 1382 /* 1383 * Compare two floating-point values. Puts 0, 1, or -1 into the 1384 * destination register based on the results of the comparison. 1385 * 1386 * int compare(x, y) { 1387 * if (x == y) { 1388 * return 0; 1389 * } else if (x > y) { 1390 * return 1; 1391 * } else if (x < y) { 1392 * return -1; 1393 * } else { 1394 * return -1; 1395 * } 1396 * } 1397 */ 1398 /* op vAA, vBB, vCC */ 1399 FETCH(r0, 1) @ r0<- CCBB 1400 mov r9, rINST, lsr #8 @ r9<- AA 1401 and r2, r0, #255 @ r2<- BB 1402 mov r3, r0, lsr #8 @ r3<- CC 1403 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1404 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1405 fldd d0, [r2] @ d0<- vBB 1406 fldd d1, [r3] @ d1<- vCC 1407 fcmped d0, d1 @ compare (vBB, vCC) 1408 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1409 mvn r0, #0 @ r0<- -1 (default) 1410 GET_INST_OPCODE(ip) @ extract opcode from rINST 1411 fmstat @ export status flags 1412 movgt r0, #1 @ (greater than) r1<- 1 1413 moveq r0, #0 @ (equal) r1<- 0 1414 b .LOP_CMPL_DOUBLE_finish @ argh 1415 1416 1417/* ------------------------------ */ 1418 .balign 64 1419.L_OP_CMPG_DOUBLE: /* 0x30 */ 1420/* File: arm-vfp/OP_CMPG_DOUBLE.S */ 1421 /* 1422 * Compare two floating-point values. Puts 0, 1, or -1 into the 1423 * destination register based on the results of the comparison. 1424 * 1425 * int compare(x, y) { 1426 * if (x == y) { 1427 * return 0; 1428 * } else if (x < y) { 1429 * return -1; 1430 * } else if (x > y) { 1431 * return 1; 1432 * } else { 1433 * return 1; 1434 * } 1435 * } 1436 */ 1437 /* op vAA, vBB, vCC */ 1438 FETCH(r0, 1) @ r0<- CCBB 1439 mov r9, rINST, lsr #8 @ r9<- AA 1440 and r2, r0, #255 @ r2<- BB 1441 mov r3, r0, lsr #8 @ r3<- CC 1442 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1443 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1444 fldd d0, [r2] @ d0<- vBB 1445 fldd d1, [r3] @ d1<- vCC 1446 fcmped d0, d1 @ compare (vBB, vCC) 1447 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1448 mov r0, #1 @ r0<- 1 (default) 1449 GET_INST_OPCODE(ip) @ extract opcode from rINST 1450 fmstat @ export status flags 1451 mvnmi r0, #0 @ (less than) r1<- -1 1452 moveq r0, #0 @ (equal) r1<- 0 1453 b .LOP_CMPG_DOUBLE_finish @ argh 1454 1455 1456/* ------------------------------ */ 1457 .balign 64 1458.L_OP_CMP_LONG: /* 0x31 */ 1459/* File: armv5te/OP_CMP_LONG.S */ 1460 /* 1461 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1462 * register based on the results of the comparison. 1463 * 1464 * We load the full values with LDM, but in practice many values could 1465 * be resolved by only looking at the high word. This could be made 1466 * faster or slower by splitting the LDM into a pair of LDRs. 1467 * 1468 * If we just wanted to set condition flags, we could do this: 1469 * subs ip, r0, r2 1470 * sbcs ip, r1, r3 1471 * subeqs ip, r0, r2 1472 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1473 * integer value, which we can do with 2 conditional mov/mvn instructions 1474 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1475 * us a constant 5-cycle path plus a branch at the end to the 1476 * instruction epilogue code. The multi-compare approach below needs 1477 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1478 * in the worst case (the 64-bit values are equal). 1479 */ 1480 /* cmp-long vAA, vBB, vCC */ 1481 FETCH(r0, 1) @ r0<- CCBB 1482 mov r9, rINST, lsr #8 @ r9<- AA 1483 and r2, r0, #255 @ r2<- BB 1484 mov r3, r0, lsr #8 @ r3<- CC 1485 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1486 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1487 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1488 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1489 cmp r1, r3 @ compare (vBB+1, vCC+1) 1490 blt .LOP_CMP_LONG_less @ signed compare on high part 1491 bgt .LOP_CMP_LONG_greater 1492 subs r1, r0, r2 @ r1<- r0 - r2 1493 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1494 bne .LOP_CMP_LONG_less 1495 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1496 1497/* ------------------------------ */ 1498 .balign 64 1499.L_OP_IF_EQ: /* 0x32 */ 1500/* File: armv5te/OP_IF_EQ.S */ 1501/* File: armv5te/bincmp.S */ 1502 /* 1503 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1504 * fragment that specifies the *reverse* comparison to perform, e.g. 1505 * for "if-le" you would use "gt". 1506 * 1507 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1508 */ 1509 /* if-cmp vA, vB, +CCCC */ 1510 mov r0, rINST, lsr #8 @ r0<- A+ 1511 mov r1, rINST, lsr #12 @ r1<- B 1512 and r0, r0, #15 1513 GET_VREG(r3, r1) @ r3<- vB 1514 GET_VREG(r2, r0) @ r2<- vA 1515 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1516 cmp r2, r3 @ compare (vA, vB) 1517 bne 1f @ branch to 1 if comparison failed 1518 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1519 movs r9, r9, asl #1 @ convert to bytes, check sign 1520 bmi common_backwardBranch @ yes, do periodic checks 15211: 1522#if defined(WITH_JIT) 1523 GET_JIT_PROF_TABLE(r0) 1524 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1525 b common_testUpdateProfile 1526#else 1527 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1528 GET_INST_OPCODE(ip) @ extract opcode from rINST 1529 GOTO_OPCODE(ip) @ jump to next instruction 1530#endif 1531 1532 1533/* ------------------------------ */ 1534 .balign 64 1535.L_OP_IF_NE: /* 0x33 */ 1536/* File: armv5te/OP_IF_NE.S */ 1537/* File: armv5te/bincmp.S */ 1538 /* 1539 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1540 * fragment that specifies the *reverse* comparison to perform, e.g. 1541 * for "if-le" you would use "gt". 1542 * 1543 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1544 */ 1545 /* if-cmp vA, vB, +CCCC */ 1546 mov r0, rINST, lsr #8 @ r0<- A+ 1547 mov r1, rINST, lsr #12 @ r1<- B 1548 and r0, r0, #15 1549 GET_VREG(r3, r1) @ r3<- vB 1550 GET_VREG(r2, r0) @ r2<- vA 1551 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1552 cmp r2, r3 @ compare (vA, vB) 1553 beq 1f @ branch to 1 if comparison failed 1554 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1555 movs r9, r9, asl #1 @ convert to bytes, check sign 1556 bmi common_backwardBranch @ yes, do periodic checks 15571: 1558#if defined(WITH_JIT) 1559 GET_JIT_PROF_TABLE(r0) 1560 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1561 b common_testUpdateProfile 1562#else 1563 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1564 GET_INST_OPCODE(ip) @ extract opcode from rINST 1565 GOTO_OPCODE(ip) @ jump to next instruction 1566#endif 1567 1568 1569/* ------------------------------ */ 1570 .balign 64 1571.L_OP_IF_LT: /* 0x34 */ 1572/* File: armv5te/OP_IF_LT.S */ 1573/* File: armv5te/bincmp.S */ 1574 /* 1575 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1576 * fragment that specifies the *reverse* comparison to perform, e.g. 1577 * for "if-le" you would use "gt". 1578 * 1579 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1580 */ 1581 /* if-cmp vA, vB, +CCCC */ 1582 mov r0, rINST, lsr #8 @ r0<- A+ 1583 mov r1, rINST, lsr #12 @ r1<- B 1584 and r0, r0, #15 1585 GET_VREG(r3, r1) @ r3<- vB 1586 GET_VREG(r2, r0) @ r2<- vA 1587 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1588 cmp r2, r3 @ compare (vA, vB) 1589 bge 1f @ branch to 1 if comparison failed 1590 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1591 movs r9, r9, asl #1 @ convert to bytes, check sign 1592 bmi common_backwardBranch @ yes, do periodic checks 15931: 1594#if defined(WITH_JIT) 1595 GET_JIT_PROF_TABLE(r0) 1596 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1597 b common_testUpdateProfile 1598#else 1599 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1600 GET_INST_OPCODE(ip) @ extract opcode from rINST 1601 GOTO_OPCODE(ip) @ jump to next instruction 1602#endif 1603 1604 1605/* ------------------------------ */ 1606 .balign 64 1607.L_OP_IF_GE: /* 0x35 */ 1608/* File: armv5te/OP_IF_GE.S */ 1609/* File: armv5te/bincmp.S */ 1610 /* 1611 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1612 * fragment that specifies the *reverse* comparison to perform, e.g. 1613 * for "if-le" you would use "gt". 1614 * 1615 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1616 */ 1617 /* if-cmp vA, vB, +CCCC */ 1618 mov r0, rINST, lsr #8 @ r0<- A+ 1619 mov r1, rINST, lsr #12 @ r1<- B 1620 and r0, r0, #15 1621 GET_VREG(r3, r1) @ r3<- vB 1622 GET_VREG(r2, r0) @ r2<- vA 1623 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1624 cmp r2, r3 @ compare (vA, vB) 1625 blt 1f @ branch to 1 if comparison failed 1626 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1627 movs r9, r9, asl #1 @ convert to bytes, check sign 1628 bmi common_backwardBranch @ yes, do periodic checks 16291: 1630#if defined(WITH_JIT) 1631 GET_JIT_PROF_TABLE(r0) 1632 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1633 b common_testUpdateProfile 1634#else 1635 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1636 GET_INST_OPCODE(ip) @ extract opcode from rINST 1637 GOTO_OPCODE(ip) @ jump to next instruction 1638#endif 1639 1640 1641/* ------------------------------ */ 1642 .balign 64 1643.L_OP_IF_GT: /* 0x36 */ 1644/* File: armv5te/OP_IF_GT.S */ 1645/* File: armv5te/bincmp.S */ 1646 /* 1647 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1648 * fragment that specifies the *reverse* comparison to perform, e.g. 1649 * for "if-le" you would use "gt". 1650 * 1651 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1652 */ 1653 /* if-cmp vA, vB, +CCCC */ 1654 mov r0, rINST, lsr #8 @ r0<- A+ 1655 mov r1, rINST, lsr #12 @ r1<- B 1656 and r0, r0, #15 1657 GET_VREG(r3, r1) @ r3<- vB 1658 GET_VREG(r2, r0) @ r2<- vA 1659 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1660 cmp r2, r3 @ compare (vA, vB) 1661 ble 1f @ branch to 1 if comparison failed 1662 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1663 movs r9, r9, asl #1 @ convert to bytes, check sign 1664 bmi common_backwardBranch @ yes, do periodic checks 16651: 1666#if defined(WITH_JIT) 1667 GET_JIT_PROF_TABLE(r0) 1668 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1669 b common_testUpdateProfile 1670#else 1671 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1672 GET_INST_OPCODE(ip) @ extract opcode from rINST 1673 GOTO_OPCODE(ip) @ jump to next instruction 1674#endif 1675 1676 1677/* ------------------------------ */ 1678 .balign 64 1679.L_OP_IF_LE: /* 0x37 */ 1680/* File: armv5te/OP_IF_LE.S */ 1681/* File: armv5te/bincmp.S */ 1682 /* 1683 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1684 * fragment that specifies the *reverse* comparison to perform, e.g. 1685 * for "if-le" you would use "gt". 1686 * 1687 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1688 */ 1689 /* if-cmp vA, vB, +CCCC */ 1690 mov r0, rINST, lsr #8 @ r0<- A+ 1691 mov r1, rINST, lsr #12 @ r1<- B 1692 and r0, r0, #15 1693 GET_VREG(r3, r1) @ r3<- vB 1694 GET_VREG(r2, r0) @ r2<- vA 1695 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1696 cmp r2, r3 @ compare (vA, vB) 1697 bgt 1f @ branch to 1 if comparison failed 1698 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1699 movs r9, r9, asl #1 @ convert to bytes, check sign 1700 bmi common_backwardBranch @ yes, do periodic checks 17011: 1702#if defined(WITH_JIT) 1703 GET_JIT_PROF_TABLE(r0) 1704 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1705 b common_testUpdateProfile 1706#else 1707 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1708 GET_INST_OPCODE(ip) @ extract opcode from rINST 1709 GOTO_OPCODE(ip) @ jump to next instruction 1710#endif 1711 1712 1713/* ------------------------------ */ 1714 .balign 64 1715.L_OP_IF_EQZ: /* 0x38 */ 1716/* File: armv5te/OP_IF_EQZ.S */ 1717/* File: armv5te/zcmp.S */ 1718 /* 1719 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1720 * fragment that specifies the *reverse* comparison to perform, e.g. 1721 * for "if-le" you would use "gt". 1722 * 1723 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1724 */ 1725 /* if-cmp vAA, +BBBB */ 1726 mov r0, rINST, lsr #8 @ r0<- AA 1727 GET_VREG(r2, r0) @ r2<- vAA 1728 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1729 cmp r2, #0 @ compare (vA, 0) 1730 bne 1f @ branch to 1 if comparison failed 1731 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1732 movs r9, r9, asl #1 @ convert to bytes, check sign 1733 bmi common_backwardBranch @ backward branch, do periodic checks 17341: 1735#if defined(WITH_JIT) 1736 GET_JIT_PROF_TABLE(r0) 1737 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1738 cmp r0,#0 1739 bne common_updateProfile 1740 GET_INST_OPCODE(ip) @ extract opcode from rINST 1741 GOTO_OPCODE(ip) @ jump to next instruction 1742#else 1743 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1744 GET_INST_OPCODE(ip) @ extract opcode from rINST 1745 GOTO_OPCODE(ip) @ jump to next instruction 1746#endif 1747 1748 1749/* ------------------------------ */ 1750 .balign 64 1751.L_OP_IF_NEZ: /* 0x39 */ 1752/* File: armv5te/OP_IF_NEZ.S */ 1753/* File: armv5te/zcmp.S */ 1754 /* 1755 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1756 * fragment that specifies the *reverse* comparison to perform, e.g. 1757 * for "if-le" you would use "gt". 1758 * 1759 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1760 */ 1761 /* if-cmp vAA, +BBBB */ 1762 mov r0, rINST, lsr #8 @ r0<- AA 1763 GET_VREG(r2, r0) @ r2<- vAA 1764 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1765 cmp r2, #0 @ compare (vA, 0) 1766 beq 1f @ branch to 1 if comparison failed 1767 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1768 movs r9, r9, asl #1 @ convert to bytes, check sign 1769 bmi common_backwardBranch @ backward branch, do periodic checks 17701: 1771#if defined(WITH_JIT) 1772 GET_JIT_PROF_TABLE(r0) 1773 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1774 cmp r0,#0 1775 bne common_updateProfile 1776 GET_INST_OPCODE(ip) @ extract opcode from rINST 1777 GOTO_OPCODE(ip) @ jump to next instruction 1778#else 1779 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1780 GET_INST_OPCODE(ip) @ extract opcode from rINST 1781 GOTO_OPCODE(ip) @ jump to next instruction 1782#endif 1783 1784 1785/* ------------------------------ */ 1786 .balign 64 1787.L_OP_IF_LTZ: /* 0x3a */ 1788/* File: armv5te/OP_IF_LTZ.S */ 1789/* File: armv5te/zcmp.S */ 1790 /* 1791 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1792 * fragment that specifies the *reverse* comparison to perform, e.g. 1793 * for "if-le" you would use "gt". 1794 * 1795 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1796 */ 1797 /* if-cmp vAA, +BBBB */ 1798 mov r0, rINST, lsr #8 @ r0<- AA 1799 GET_VREG(r2, r0) @ r2<- vAA 1800 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1801 cmp r2, #0 @ compare (vA, 0) 1802 bge 1f @ branch to 1 if comparison failed 1803 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1804 movs r9, r9, asl #1 @ convert to bytes, check sign 1805 bmi common_backwardBranch @ backward branch, do periodic checks 18061: 1807#if defined(WITH_JIT) 1808 GET_JIT_PROF_TABLE(r0) 1809 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1810 cmp r0,#0 1811 bne common_updateProfile 1812 GET_INST_OPCODE(ip) @ extract opcode from rINST 1813 GOTO_OPCODE(ip) @ jump to next instruction 1814#else 1815 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1816 GET_INST_OPCODE(ip) @ extract opcode from rINST 1817 GOTO_OPCODE(ip) @ jump to next instruction 1818#endif 1819 1820 1821/* ------------------------------ */ 1822 .balign 64 1823.L_OP_IF_GEZ: /* 0x3b */ 1824/* File: armv5te/OP_IF_GEZ.S */ 1825/* File: armv5te/zcmp.S */ 1826 /* 1827 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1828 * fragment that specifies the *reverse* comparison to perform, e.g. 1829 * for "if-le" you would use "gt". 1830 * 1831 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1832 */ 1833 /* if-cmp vAA, +BBBB */ 1834 mov r0, rINST, lsr #8 @ r0<- AA 1835 GET_VREG(r2, r0) @ r2<- vAA 1836 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1837 cmp r2, #0 @ compare (vA, 0) 1838 blt 1f @ branch to 1 if comparison failed 1839 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1840 movs r9, r9, asl #1 @ convert to bytes, check sign 1841 bmi common_backwardBranch @ backward branch, do periodic checks 18421: 1843#if defined(WITH_JIT) 1844 GET_JIT_PROF_TABLE(r0) 1845 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1846 cmp r0,#0 1847 bne common_updateProfile 1848 GET_INST_OPCODE(ip) @ extract opcode from rINST 1849 GOTO_OPCODE(ip) @ jump to next instruction 1850#else 1851 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1852 GET_INST_OPCODE(ip) @ extract opcode from rINST 1853 GOTO_OPCODE(ip) @ jump to next instruction 1854#endif 1855 1856 1857/* ------------------------------ */ 1858 .balign 64 1859.L_OP_IF_GTZ: /* 0x3c */ 1860/* File: armv5te/OP_IF_GTZ.S */ 1861/* File: armv5te/zcmp.S */ 1862 /* 1863 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1864 * fragment that specifies the *reverse* comparison to perform, e.g. 1865 * for "if-le" you would use "gt". 1866 * 1867 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1868 */ 1869 /* if-cmp vAA, +BBBB */ 1870 mov r0, rINST, lsr #8 @ r0<- AA 1871 GET_VREG(r2, r0) @ r2<- vAA 1872 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1873 cmp r2, #0 @ compare (vA, 0) 1874 ble 1f @ branch to 1 if comparison failed 1875 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1876 movs r9, r9, asl #1 @ convert to bytes, check sign 1877 bmi common_backwardBranch @ backward branch, do periodic checks 18781: 1879#if defined(WITH_JIT) 1880 GET_JIT_PROF_TABLE(r0) 1881 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1882 cmp r0,#0 1883 bne common_updateProfile 1884 GET_INST_OPCODE(ip) @ extract opcode from rINST 1885 GOTO_OPCODE(ip) @ jump to next instruction 1886#else 1887 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1888 GET_INST_OPCODE(ip) @ extract opcode from rINST 1889 GOTO_OPCODE(ip) @ jump to next instruction 1890#endif 1891 1892 1893/* ------------------------------ */ 1894 .balign 64 1895.L_OP_IF_LEZ: /* 0x3d */ 1896/* File: armv5te/OP_IF_LEZ.S */ 1897/* File: armv5te/zcmp.S */ 1898 /* 1899 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1900 * fragment that specifies the *reverse* comparison to perform, e.g. 1901 * for "if-le" you would use "gt". 1902 * 1903 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1904 */ 1905 /* if-cmp vAA, +BBBB */ 1906 mov r0, rINST, lsr #8 @ r0<- AA 1907 GET_VREG(r2, r0) @ r2<- vAA 1908 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1909 cmp r2, #0 @ compare (vA, 0) 1910 bgt 1f @ branch to 1 if comparison failed 1911 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1912 movs r9, r9, asl #1 @ convert to bytes, check sign 1913 bmi common_backwardBranch @ backward branch, do periodic checks 19141: 1915#if defined(WITH_JIT) 1916 GET_JIT_PROF_TABLE(r0) 1917 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1918 cmp r0,#0 1919 bne common_updateProfile 1920 GET_INST_OPCODE(ip) @ extract opcode from rINST 1921 GOTO_OPCODE(ip) @ jump to next instruction 1922#else 1923 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1924 GET_INST_OPCODE(ip) @ extract opcode from rINST 1925 GOTO_OPCODE(ip) @ jump to next instruction 1926#endif 1927 1928 1929/* ------------------------------ */ 1930 .balign 64 1931.L_OP_UNUSED_3E: /* 0x3e */ 1932/* File: armv5te/OP_UNUSED_3E.S */ 1933/* File: armv5te/unused.S */ 1934 bl common_abort 1935 1936 1937/* ------------------------------ */ 1938 .balign 64 1939.L_OP_UNUSED_3F: /* 0x3f */ 1940/* File: armv5te/OP_UNUSED_3F.S */ 1941/* File: armv5te/unused.S */ 1942 bl common_abort 1943 1944 1945/* ------------------------------ */ 1946 .balign 64 1947.L_OP_UNUSED_40: /* 0x40 */ 1948/* File: armv5te/OP_UNUSED_40.S */ 1949/* File: armv5te/unused.S */ 1950 bl common_abort 1951 1952 1953/* ------------------------------ */ 1954 .balign 64 1955.L_OP_UNUSED_41: /* 0x41 */ 1956/* File: armv5te/OP_UNUSED_41.S */ 1957/* File: armv5te/unused.S */ 1958 bl common_abort 1959 1960 1961/* ------------------------------ */ 1962 .balign 64 1963.L_OP_UNUSED_42: /* 0x42 */ 1964/* File: armv5te/OP_UNUSED_42.S */ 1965/* File: armv5te/unused.S */ 1966 bl common_abort 1967 1968 1969/* ------------------------------ */ 1970 .balign 64 1971.L_OP_UNUSED_43: /* 0x43 */ 1972/* File: armv5te/OP_UNUSED_43.S */ 1973/* File: armv5te/unused.S */ 1974 bl common_abort 1975 1976 1977/* ------------------------------ */ 1978 .balign 64 1979.L_OP_AGET: /* 0x44 */ 1980/* File: armv5te/OP_AGET.S */ 1981 /* 1982 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1983 * 1984 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 1985 * instructions. We use a pair of FETCH_Bs instead. 1986 * 1987 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1988 */ 1989 /* op vAA, vBB, vCC */ 1990 FETCH_B(r2, 1, 0) @ r2<- BB 1991 mov r9, rINST, lsr #8 @ r9<- AA 1992 FETCH_B(r3, 1, 1) @ r3<- CC 1993 GET_VREG(r0, r2) @ r0<- vBB (array object) 1994 GET_VREG(r1, r3) @ r1<- vCC (requested index) 1995 cmp r0, #0 @ null array object? 1996 beq common_errNullObject @ yes, bail 1997 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 1998 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 1999 cmp r1, r3 @ compare unsigned index, length 2000 bcs common_errArrayIndex @ index >= length, bail 2001 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2002 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2003 GET_INST_OPCODE(ip) @ extract opcode from rINST 2004 SET_VREG(r2, r9) @ vAA<- r2 2005 GOTO_OPCODE(ip) @ jump to next instruction 2006 2007/* ------------------------------ */ 2008 .balign 64 2009.L_OP_AGET_WIDE: /* 0x45 */ 2010/* File: armv5te/OP_AGET_WIDE.S */ 2011 /* 2012 * Array get, 64 bits. vAA <- vBB[vCC]. 2013 * 2014 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 2015 */ 2016 /* aget-wide vAA, vBB, vCC */ 2017 FETCH(r0, 1) @ r0<- CCBB 2018 mov r9, rINST, lsr #8 @ r9<- AA 2019 and r2, r0, #255 @ r2<- BB 2020 mov r3, r0, lsr #8 @ r3<- CC 2021 GET_VREG(r0, r2) @ r0<- vBB (array object) 2022 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2023 cmp r0, #0 @ null array object? 2024 beq common_errNullObject @ yes, bail 2025 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2026 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2027 cmp r1, r3 @ compare unsigned index, length 2028 bcc .LOP_AGET_WIDE_finish @ okay, continue below 2029 b common_errArrayIndex @ index >= length, bail 2030 @ May want to swap the order of these two branches depending on how the 2031 @ branch prediction (if any) handles conditional forward branches vs. 2032 @ unconditional forward branches. 2033 2034/* ------------------------------ */ 2035 .balign 64 2036.L_OP_AGET_OBJECT: /* 0x46 */ 2037/* File: armv5te/OP_AGET_OBJECT.S */ 2038/* File: armv5te/OP_AGET.S */ 2039 /* 2040 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2041 * 2042 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2043 * instructions. We use a pair of FETCH_Bs instead. 2044 * 2045 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2046 */ 2047 /* op vAA, vBB, vCC */ 2048 FETCH_B(r2, 1, 0) @ r2<- BB 2049 mov r9, rINST, lsr #8 @ r9<- AA 2050 FETCH_B(r3, 1, 1) @ r3<- CC 2051 GET_VREG(r0, r2) @ r0<- vBB (array object) 2052 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2053 cmp r0, #0 @ null array object? 2054 beq common_errNullObject @ yes, bail 2055 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2056 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2057 cmp r1, r3 @ compare unsigned index, length 2058 bcs common_errArrayIndex @ index >= length, bail 2059 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2060 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2061 GET_INST_OPCODE(ip) @ extract opcode from rINST 2062 SET_VREG(r2, r9) @ vAA<- r2 2063 GOTO_OPCODE(ip) @ jump to next instruction 2064 2065 2066/* ------------------------------ */ 2067 .balign 64 2068.L_OP_AGET_BOOLEAN: /* 0x47 */ 2069/* File: armv5te/OP_AGET_BOOLEAN.S */ 2070/* File: armv5te/OP_AGET.S */ 2071 /* 2072 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2073 * 2074 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2075 * instructions. We use a pair of FETCH_Bs instead. 2076 * 2077 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2078 */ 2079 /* op vAA, vBB, vCC */ 2080 FETCH_B(r2, 1, 0) @ r2<- BB 2081 mov r9, rINST, lsr #8 @ r9<- AA 2082 FETCH_B(r3, 1, 1) @ r3<- CC 2083 GET_VREG(r0, r2) @ r0<- vBB (array object) 2084 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2085 cmp r0, #0 @ null array object? 2086 beq common_errNullObject @ yes, bail 2087 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2088 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2089 cmp r1, r3 @ compare unsigned index, length 2090 bcs common_errArrayIndex @ index >= length, bail 2091 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2092 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2093 GET_INST_OPCODE(ip) @ extract opcode from rINST 2094 SET_VREG(r2, r9) @ vAA<- r2 2095 GOTO_OPCODE(ip) @ jump to next instruction 2096 2097 2098/* ------------------------------ */ 2099 .balign 64 2100.L_OP_AGET_BYTE: /* 0x48 */ 2101/* File: armv5te/OP_AGET_BYTE.S */ 2102/* File: armv5te/OP_AGET.S */ 2103 /* 2104 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2105 * 2106 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2107 * instructions. We use a pair of FETCH_Bs instead. 2108 * 2109 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2110 */ 2111 /* op vAA, vBB, vCC */ 2112 FETCH_B(r2, 1, 0) @ r2<- BB 2113 mov r9, rINST, lsr #8 @ r9<- AA 2114 FETCH_B(r3, 1, 1) @ r3<- CC 2115 GET_VREG(r0, r2) @ r0<- vBB (array object) 2116 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2117 cmp r0, #0 @ null array object? 2118 beq common_errNullObject @ yes, bail 2119 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2120 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2121 cmp r1, r3 @ compare unsigned index, length 2122 bcs common_errArrayIndex @ index >= length, bail 2123 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2124 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2125 GET_INST_OPCODE(ip) @ extract opcode from rINST 2126 SET_VREG(r2, r9) @ vAA<- r2 2127 GOTO_OPCODE(ip) @ jump to next instruction 2128 2129 2130/* ------------------------------ */ 2131 .balign 64 2132.L_OP_AGET_CHAR: /* 0x49 */ 2133/* File: armv5te/OP_AGET_CHAR.S */ 2134/* File: armv5te/OP_AGET.S */ 2135 /* 2136 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2137 * 2138 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2139 * instructions. We use a pair of FETCH_Bs instead. 2140 * 2141 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2142 */ 2143 /* op vAA, vBB, vCC */ 2144 FETCH_B(r2, 1, 0) @ r2<- BB 2145 mov r9, rINST, lsr #8 @ r9<- AA 2146 FETCH_B(r3, 1, 1) @ r3<- CC 2147 GET_VREG(r0, r2) @ r0<- vBB (array object) 2148 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2149 cmp r0, #0 @ null array object? 2150 beq common_errNullObject @ yes, bail 2151 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2152 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2153 cmp r1, r3 @ compare unsigned index, length 2154 bcs common_errArrayIndex @ index >= length, bail 2155 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2156 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2157 GET_INST_OPCODE(ip) @ extract opcode from rINST 2158 SET_VREG(r2, r9) @ vAA<- r2 2159 GOTO_OPCODE(ip) @ jump to next instruction 2160 2161 2162/* ------------------------------ */ 2163 .balign 64 2164.L_OP_AGET_SHORT: /* 0x4a */ 2165/* File: armv5te/OP_AGET_SHORT.S */ 2166/* File: armv5te/OP_AGET.S */ 2167 /* 2168 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2169 * 2170 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2171 * instructions. We use a pair of FETCH_Bs instead. 2172 * 2173 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2174 */ 2175 /* op vAA, vBB, vCC */ 2176 FETCH_B(r2, 1, 0) @ r2<- BB 2177 mov r9, rINST, lsr #8 @ r9<- AA 2178 FETCH_B(r3, 1, 1) @ r3<- CC 2179 GET_VREG(r0, r2) @ r0<- vBB (array object) 2180 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2181 cmp r0, #0 @ null array object? 2182 beq common_errNullObject @ yes, bail 2183 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2184 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2185 cmp r1, r3 @ compare unsigned index, length 2186 bcs common_errArrayIndex @ index >= length, bail 2187 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2188 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2189 GET_INST_OPCODE(ip) @ extract opcode from rINST 2190 SET_VREG(r2, r9) @ vAA<- r2 2191 GOTO_OPCODE(ip) @ jump to next instruction 2192 2193 2194/* ------------------------------ */ 2195 .balign 64 2196.L_OP_APUT: /* 0x4b */ 2197/* File: armv5te/OP_APUT.S */ 2198 /* 2199 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2200 * 2201 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2202 * instructions. We use a pair of FETCH_Bs instead. 2203 * 2204 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2205 */ 2206 /* op vAA, vBB, vCC */ 2207 FETCH_B(r2, 1, 0) @ r2<- BB 2208 mov r9, rINST, lsr #8 @ r9<- AA 2209 FETCH_B(r3, 1, 1) @ r3<- CC 2210 GET_VREG(r0, r2) @ r0<- vBB (array object) 2211 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2212 cmp r0, #0 @ null array object? 2213 beq common_errNullObject @ yes, bail 2214 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2215 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2216 cmp r1, r3 @ compare unsigned index, length 2217 bcs common_errArrayIndex @ index >= length, bail 2218 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2219 GET_VREG(r2, r9) @ r2<- vAA 2220 GET_INST_OPCODE(ip) @ extract opcode from rINST 2221 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2222 GOTO_OPCODE(ip) @ jump to next instruction 2223 2224/* ------------------------------ */ 2225 .balign 64 2226.L_OP_APUT_WIDE: /* 0x4c */ 2227/* File: armv5te/OP_APUT_WIDE.S */ 2228 /* 2229 * Array put, 64 bits. vBB[vCC] <- vAA. 2230 * 2231 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 2232 */ 2233 /* aput-wide vAA, vBB, vCC */ 2234 FETCH(r0, 1) @ r0<- CCBB 2235 mov r9, rINST, lsr #8 @ r9<- AA 2236 and r2, r0, #255 @ r2<- BB 2237 mov r3, r0, lsr #8 @ r3<- CC 2238 GET_VREG(r0, r2) @ r0<- vBB (array object) 2239 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2240 cmp r0, #0 @ null array object? 2241 beq common_errNullObject @ yes, bail 2242 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2243 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2244 cmp r1, r3 @ compare unsigned index, length 2245 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2246 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2247 b common_errArrayIndex @ index >= length, bail 2248 @ May want to swap the order of these two branches depending on how the 2249 @ branch prediction (if any) handles conditional forward branches vs. 2250 @ unconditional forward branches. 2251 2252/* ------------------------------ */ 2253 .balign 64 2254.L_OP_APUT_OBJECT: /* 0x4d */ 2255/* File: armv5te/OP_APUT_OBJECT.S */ 2256 /* 2257 * Store an object into an array. vBB[vCC] <- vAA. 2258 * 2259 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2260 * instructions. We use a pair of FETCH_Bs instead. 2261 */ 2262 /* op vAA, vBB, vCC */ 2263 FETCH(r0, 1) @ r0<- CCBB 2264 mov r9, rINST, lsr #8 @ r9<- AA 2265 and r2, r0, #255 @ r2<- BB 2266 mov r3, r0, lsr #8 @ r3<- CC 2267 GET_VREG(r1, r2) @ r1<- vBB (array object) 2268 GET_VREG(r0, r3) @ r0<- vCC (requested index) 2269 cmp r1, #0 @ null array object? 2270 GET_VREG(r9, r9) @ r9<- vAA 2271 beq common_errNullObject @ yes, bail 2272 ldr r3, [r1, #offArrayObject_length] @ r3<- arrayObj->length 2273 add r10, r1, r0, lsl #2 @ r10<- arrayObj + index*width 2274 cmp r0, r3 @ compare unsigned index, length 2275 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2276 b common_errArrayIndex @ index >= length, bail 2277 2278 2279/* ------------------------------ */ 2280 .balign 64 2281.L_OP_APUT_BOOLEAN: /* 0x4e */ 2282/* File: armv5te/OP_APUT_BOOLEAN.S */ 2283/* File: armv5te/OP_APUT.S */ 2284 /* 2285 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2286 * 2287 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2288 * instructions. We use a pair of FETCH_Bs instead. 2289 * 2290 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2291 */ 2292 /* op vAA, vBB, vCC */ 2293 FETCH_B(r2, 1, 0) @ r2<- BB 2294 mov r9, rINST, lsr #8 @ r9<- AA 2295 FETCH_B(r3, 1, 1) @ r3<- CC 2296 GET_VREG(r0, r2) @ r0<- vBB (array object) 2297 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2298 cmp r0, #0 @ null array object? 2299 beq common_errNullObject @ yes, bail 2300 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2301 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2302 cmp r1, r3 @ compare unsigned index, length 2303 bcs common_errArrayIndex @ index >= length, bail 2304 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2305 GET_VREG(r2, r9) @ r2<- vAA 2306 GET_INST_OPCODE(ip) @ extract opcode from rINST 2307 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2308 GOTO_OPCODE(ip) @ jump to next instruction 2309 2310 2311/* ------------------------------ */ 2312 .balign 64 2313.L_OP_APUT_BYTE: /* 0x4f */ 2314/* File: armv5te/OP_APUT_BYTE.S */ 2315/* File: armv5te/OP_APUT.S */ 2316 /* 2317 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2318 * 2319 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2320 * instructions. We use a pair of FETCH_Bs instead. 2321 * 2322 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2323 */ 2324 /* op vAA, vBB, vCC */ 2325 FETCH_B(r2, 1, 0) @ r2<- BB 2326 mov r9, rINST, lsr #8 @ r9<- AA 2327 FETCH_B(r3, 1, 1) @ r3<- CC 2328 GET_VREG(r0, r2) @ r0<- vBB (array object) 2329 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2330 cmp r0, #0 @ null array object? 2331 beq common_errNullObject @ yes, bail 2332 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2333 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2334 cmp r1, r3 @ compare unsigned index, length 2335 bcs common_errArrayIndex @ index >= length, bail 2336 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2337 GET_VREG(r2, r9) @ r2<- vAA 2338 GET_INST_OPCODE(ip) @ extract opcode from rINST 2339 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2340 GOTO_OPCODE(ip) @ jump to next instruction 2341 2342 2343/* ------------------------------ */ 2344 .balign 64 2345.L_OP_APUT_CHAR: /* 0x50 */ 2346/* File: armv5te/OP_APUT_CHAR.S */ 2347/* File: armv5te/OP_APUT.S */ 2348 /* 2349 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2350 * 2351 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2352 * instructions. We use a pair of FETCH_Bs instead. 2353 * 2354 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2355 */ 2356 /* op vAA, vBB, vCC */ 2357 FETCH_B(r2, 1, 0) @ r2<- BB 2358 mov r9, rINST, lsr #8 @ r9<- AA 2359 FETCH_B(r3, 1, 1) @ r3<- CC 2360 GET_VREG(r0, r2) @ r0<- vBB (array object) 2361 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2362 cmp r0, #0 @ null array object? 2363 beq common_errNullObject @ yes, bail 2364 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2365 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2366 cmp r1, r3 @ compare unsigned index, length 2367 bcs common_errArrayIndex @ index >= length, bail 2368 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2369 GET_VREG(r2, r9) @ r2<- vAA 2370 GET_INST_OPCODE(ip) @ extract opcode from rINST 2371 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2372 GOTO_OPCODE(ip) @ jump to next instruction 2373 2374 2375/* ------------------------------ */ 2376 .balign 64 2377.L_OP_APUT_SHORT: /* 0x51 */ 2378/* File: armv5te/OP_APUT_SHORT.S */ 2379/* File: armv5te/OP_APUT.S */ 2380 /* 2381 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2382 * 2383 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2384 * instructions. We use a pair of FETCH_Bs instead. 2385 * 2386 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2387 */ 2388 /* op vAA, vBB, vCC */ 2389 FETCH_B(r2, 1, 0) @ r2<- BB 2390 mov r9, rINST, lsr #8 @ r9<- AA 2391 FETCH_B(r3, 1, 1) @ r3<- CC 2392 GET_VREG(r0, r2) @ r0<- vBB (array object) 2393 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2394 cmp r0, #0 @ null array object? 2395 beq common_errNullObject @ yes, bail 2396 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2397 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2398 cmp r1, r3 @ compare unsigned index, length 2399 bcs common_errArrayIndex @ index >= length, bail 2400 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2401 GET_VREG(r2, r9) @ r2<- vAA 2402 GET_INST_OPCODE(ip) @ extract opcode from rINST 2403 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2404 GOTO_OPCODE(ip) @ jump to next instruction 2405 2406 2407/* ------------------------------ */ 2408 .balign 64 2409.L_OP_IGET: /* 0x52 */ 2410/* File: armv5te/OP_IGET.S */ 2411 /* 2412 * General 32-bit instance field get. 2413 * 2414 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2415 */ 2416 /* op vA, vB, field@CCCC */ 2417 mov r0, rINST, lsr #12 @ r0<- B 2418 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2419 FETCH(r1, 1) @ r1<- field ref CCCC 2420 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2421 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2422 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2423 cmp r0, #0 @ is resolved entry null? 2424 bne .LOP_IGET_finish @ no, already resolved 24258: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2426 EXPORT_PC() @ resolve() could throw 2427 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2428 bl dvmResolveInstField @ r0<- resolved InstField ptr 2429 cmp r0, #0 2430 bne .LOP_IGET_finish 2431 b common_exceptionThrown 2432 2433/* ------------------------------ */ 2434 .balign 64 2435.L_OP_IGET_WIDE: /* 0x53 */ 2436/* File: armv5te/OP_IGET_WIDE.S */ 2437 /* 2438 * Wide 32-bit instance field get. 2439 */ 2440 /* iget-wide vA, vB, field@CCCC */ 2441 mov r0, rINST, lsr #12 @ r0<- B 2442 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2443 FETCH(r1, 1) @ r1<- field ref CCCC 2444 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2445 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2446 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2447 cmp r0, #0 @ is resolved entry null? 2448 bne .LOP_IGET_WIDE_finish @ no, already resolved 24498: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2450 EXPORT_PC() @ resolve() could throw 2451 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2452 bl dvmResolveInstField @ r0<- resolved InstField ptr 2453 cmp r0, #0 2454 bne .LOP_IGET_WIDE_finish 2455 b common_exceptionThrown 2456 2457/* ------------------------------ */ 2458 .balign 64 2459.L_OP_IGET_OBJECT: /* 0x54 */ 2460/* File: armv5te/OP_IGET_OBJECT.S */ 2461/* File: armv5te/OP_IGET.S */ 2462 /* 2463 * General 32-bit instance field get. 2464 * 2465 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2466 */ 2467 /* op vA, vB, field@CCCC */ 2468 mov r0, rINST, lsr #12 @ r0<- B 2469 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2470 FETCH(r1, 1) @ r1<- field ref CCCC 2471 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2472 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2473 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2474 cmp r0, #0 @ is resolved entry null? 2475 bne .LOP_IGET_OBJECT_finish @ no, already resolved 24768: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2477 EXPORT_PC() @ resolve() could throw 2478 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2479 bl dvmResolveInstField @ r0<- resolved InstField ptr 2480 cmp r0, #0 2481 bne .LOP_IGET_OBJECT_finish 2482 b common_exceptionThrown 2483 2484 2485/* ------------------------------ */ 2486 .balign 64 2487.L_OP_IGET_BOOLEAN: /* 0x55 */ 2488/* File: armv5te/OP_IGET_BOOLEAN.S */ 2489@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2490/* File: armv5te/OP_IGET.S */ 2491 /* 2492 * General 32-bit instance field get. 2493 * 2494 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2495 */ 2496 /* op vA, vB, field@CCCC */ 2497 mov r0, rINST, lsr #12 @ r0<- B 2498 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2499 FETCH(r1, 1) @ r1<- field ref CCCC 2500 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2501 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2502 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2503 cmp r0, #0 @ is resolved entry null? 2504 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 25058: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2506 EXPORT_PC() @ resolve() could throw 2507 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2508 bl dvmResolveInstField @ r0<- resolved InstField ptr 2509 cmp r0, #0 2510 bne .LOP_IGET_BOOLEAN_finish 2511 b common_exceptionThrown 2512 2513 2514/* ------------------------------ */ 2515 .balign 64 2516.L_OP_IGET_BYTE: /* 0x56 */ 2517/* File: armv5te/OP_IGET_BYTE.S */ 2518@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2519/* File: armv5te/OP_IGET.S */ 2520 /* 2521 * General 32-bit instance field get. 2522 * 2523 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2524 */ 2525 /* op vA, vB, field@CCCC */ 2526 mov r0, rINST, lsr #12 @ r0<- B 2527 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2528 FETCH(r1, 1) @ r1<- field ref CCCC 2529 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2530 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2531 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2532 cmp r0, #0 @ is resolved entry null? 2533 bne .LOP_IGET_BYTE_finish @ no, already resolved 25348: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2535 EXPORT_PC() @ resolve() could throw 2536 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2537 bl dvmResolveInstField @ r0<- resolved InstField ptr 2538 cmp r0, #0 2539 bne .LOP_IGET_BYTE_finish 2540 b common_exceptionThrown 2541 2542 2543/* ------------------------------ */ 2544 .balign 64 2545.L_OP_IGET_CHAR: /* 0x57 */ 2546/* File: armv5te/OP_IGET_CHAR.S */ 2547@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2548/* File: armv5te/OP_IGET.S */ 2549 /* 2550 * General 32-bit instance field get. 2551 * 2552 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2553 */ 2554 /* op vA, vB, field@CCCC */ 2555 mov r0, rINST, lsr #12 @ r0<- B 2556 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2557 FETCH(r1, 1) @ r1<- field ref CCCC 2558 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2559 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2560 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2561 cmp r0, #0 @ is resolved entry null? 2562 bne .LOP_IGET_CHAR_finish @ no, already resolved 25638: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2564 EXPORT_PC() @ resolve() could throw 2565 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2566 bl dvmResolveInstField @ r0<- resolved InstField ptr 2567 cmp r0, #0 2568 bne .LOP_IGET_CHAR_finish 2569 b common_exceptionThrown 2570 2571 2572/* ------------------------------ */ 2573 .balign 64 2574.L_OP_IGET_SHORT: /* 0x58 */ 2575/* File: armv5te/OP_IGET_SHORT.S */ 2576@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2577/* File: armv5te/OP_IGET.S */ 2578 /* 2579 * General 32-bit instance field get. 2580 * 2581 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2582 */ 2583 /* op vA, vB, field@CCCC */ 2584 mov r0, rINST, lsr #12 @ r0<- B 2585 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2586 FETCH(r1, 1) @ r1<- field ref CCCC 2587 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2588 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2589 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2590 cmp r0, #0 @ is resolved entry null? 2591 bne .LOP_IGET_SHORT_finish @ no, already resolved 25928: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2593 EXPORT_PC() @ resolve() could throw 2594 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2595 bl dvmResolveInstField @ r0<- resolved InstField ptr 2596 cmp r0, #0 2597 bne .LOP_IGET_SHORT_finish 2598 b common_exceptionThrown 2599 2600 2601/* ------------------------------ */ 2602 .balign 64 2603.L_OP_IPUT: /* 0x59 */ 2604/* File: armv5te/OP_IPUT.S */ 2605 /* 2606 * General 32-bit instance field put. 2607 * 2608 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2609 */ 2610 /* op vA, vB, field@CCCC */ 2611 mov r0, rINST, lsr #12 @ r0<- B 2612 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2613 FETCH(r1, 1) @ r1<- field ref CCCC 2614 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2615 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2616 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2617 cmp r0, #0 @ is resolved entry null? 2618 bne .LOP_IPUT_finish @ no, already resolved 26198: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2620 EXPORT_PC() @ resolve() could throw 2621 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2622 bl dvmResolveInstField @ r0<- resolved InstField ptr 2623 cmp r0, #0 @ success? 2624 bne .LOP_IPUT_finish @ yes, finish up 2625 b common_exceptionThrown 2626 2627/* ------------------------------ */ 2628 .balign 64 2629.L_OP_IPUT_WIDE: /* 0x5a */ 2630/* File: armv5te/OP_IPUT_WIDE.S */ 2631 /* iput-wide vA, vB, field@CCCC */ 2632 mov r0, rINST, lsr #12 @ r0<- B 2633 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2634 FETCH(r1, 1) @ r1<- field ref CCCC 2635 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2636 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2637 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2638 cmp r0, #0 @ is resolved entry null? 2639 bne .LOP_IPUT_WIDE_finish @ no, already resolved 26408: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2641 EXPORT_PC() @ resolve() could throw 2642 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2643 bl dvmResolveInstField @ r0<- resolved InstField ptr 2644 cmp r0, #0 @ success? 2645 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2646 b common_exceptionThrown 2647 2648/* ------------------------------ */ 2649 .balign 64 2650.L_OP_IPUT_OBJECT: /* 0x5b */ 2651/* File: armv5te/OP_IPUT_OBJECT.S */ 2652 /* 2653 * 32-bit instance field put. 2654 * 2655 * for: iput-object, iput-object-volatile 2656 */ 2657 /* op vA, vB, field@CCCC */ 2658 mov r0, rINST, lsr #12 @ r0<- B 2659 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2660 FETCH(r1, 1) @ r1<- field ref CCCC 2661 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2662 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2663 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2664 cmp r0, #0 @ is resolved entry null? 2665 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 26668: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2667 EXPORT_PC() @ resolve() could throw 2668 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2669 bl dvmResolveInstField @ r0<- resolved InstField ptr 2670 cmp r0, #0 @ success? 2671 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2672 b common_exceptionThrown 2673 2674/* ------------------------------ */ 2675 .balign 64 2676.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2677/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2678@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2679/* File: armv5te/OP_IPUT.S */ 2680 /* 2681 * General 32-bit instance field put. 2682 * 2683 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2684 */ 2685 /* op vA, vB, field@CCCC */ 2686 mov r0, rINST, lsr #12 @ r0<- B 2687 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2688 FETCH(r1, 1) @ r1<- field ref CCCC 2689 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2690 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2691 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2692 cmp r0, #0 @ is resolved entry null? 2693 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 26948: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2695 EXPORT_PC() @ resolve() could throw 2696 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2697 bl dvmResolveInstField @ r0<- resolved InstField ptr 2698 cmp r0, #0 @ success? 2699 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2700 b common_exceptionThrown 2701 2702 2703/* ------------------------------ */ 2704 .balign 64 2705.L_OP_IPUT_BYTE: /* 0x5d */ 2706/* File: armv5te/OP_IPUT_BYTE.S */ 2707@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2708/* File: armv5te/OP_IPUT.S */ 2709 /* 2710 * General 32-bit instance field put. 2711 * 2712 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2713 */ 2714 /* op vA, vB, field@CCCC */ 2715 mov r0, rINST, lsr #12 @ r0<- B 2716 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2717 FETCH(r1, 1) @ r1<- field ref CCCC 2718 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2719 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2720 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2721 cmp r0, #0 @ is resolved entry null? 2722 bne .LOP_IPUT_BYTE_finish @ no, already resolved 27238: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2724 EXPORT_PC() @ resolve() could throw 2725 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2726 bl dvmResolveInstField @ r0<- resolved InstField ptr 2727 cmp r0, #0 @ success? 2728 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2729 b common_exceptionThrown 2730 2731 2732/* ------------------------------ */ 2733 .balign 64 2734.L_OP_IPUT_CHAR: /* 0x5e */ 2735/* File: armv5te/OP_IPUT_CHAR.S */ 2736@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2737/* File: armv5te/OP_IPUT.S */ 2738 /* 2739 * General 32-bit instance field put. 2740 * 2741 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2742 */ 2743 /* op vA, vB, field@CCCC */ 2744 mov r0, rINST, lsr #12 @ r0<- B 2745 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2746 FETCH(r1, 1) @ r1<- field ref CCCC 2747 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2748 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2749 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2750 cmp r0, #0 @ is resolved entry null? 2751 bne .LOP_IPUT_CHAR_finish @ no, already resolved 27528: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2753 EXPORT_PC() @ resolve() could throw 2754 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2755 bl dvmResolveInstField @ r0<- resolved InstField ptr 2756 cmp r0, #0 @ success? 2757 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2758 b common_exceptionThrown 2759 2760 2761/* ------------------------------ */ 2762 .balign 64 2763.L_OP_IPUT_SHORT: /* 0x5f */ 2764/* File: armv5te/OP_IPUT_SHORT.S */ 2765@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2766/* File: armv5te/OP_IPUT.S */ 2767 /* 2768 * General 32-bit instance field put. 2769 * 2770 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 2771 */ 2772 /* op vA, vB, field@CCCC */ 2773 mov r0, rINST, lsr #12 @ r0<- B 2774 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2775 FETCH(r1, 1) @ r1<- field ref CCCC 2776 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2777 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2778 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2779 cmp r0, #0 @ is resolved entry null? 2780 bne .LOP_IPUT_SHORT_finish @ no, already resolved 27818: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2782 EXPORT_PC() @ resolve() could throw 2783 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2784 bl dvmResolveInstField @ r0<- resolved InstField ptr 2785 cmp r0, #0 @ success? 2786 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2787 b common_exceptionThrown 2788 2789 2790/* ------------------------------ */ 2791 .balign 64 2792.L_OP_SGET: /* 0x60 */ 2793/* File: armv5te/OP_SGET.S */ 2794 /* 2795 * General 32-bit SGET handler. 2796 * 2797 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2798 */ 2799 /* op vAA, field@BBBB */ 2800 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2801 FETCH(r1, 1) @ r1<- field ref BBBB 2802 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2803 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2804 cmp r0, #0 @ is resolved entry null? 2805 beq .LOP_SGET_resolve @ yes, do resolve 2806.LOP_SGET_finish: @ field ptr in r0 2807 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2808 @ no-op @ acquiring load 2809 mov r2, rINST, lsr #8 @ r2<- AA 2810 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2811 SET_VREG(r1, r2) @ fp[AA]<- r1 2812 GET_INST_OPCODE(ip) @ extract opcode from rINST 2813 GOTO_OPCODE(ip) @ jump to next instruction 2814 2815/* ------------------------------ */ 2816 .balign 64 2817.L_OP_SGET_WIDE: /* 0x61 */ 2818/* File: armv5te/OP_SGET_WIDE.S */ 2819 /* 2820 * 64-bit SGET handler. 2821 */ 2822 /* sget-wide vAA, field@BBBB */ 2823 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2824 FETCH(r1, 1) @ r1<- field ref BBBB 2825 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2826 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2827 cmp r0, #0 @ is resolved entry null? 2828 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2829.LOP_SGET_WIDE_finish: 2830 mov r9, rINST, lsr #8 @ r9<- AA 2831 .if 0 2832 add r0, r0, #offStaticField_value @ r0<- pointer to data 2833 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 2834 .else 2835 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 2836 .endif 2837 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2838 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2839 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 2840 GET_INST_OPCODE(ip) @ extract opcode from rINST 2841 GOTO_OPCODE(ip) @ jump to next instruction 2842 2843/* ------------------------------ */ 2844 .balign 64 2845.L_OP_SGET_OBJECT: /* 0x62 */ 2846/* File: armv5te/OP_SGET_OBJECT.S */ 2847/* File: armv5te/OP_SGET.S */ 2848 /* 2849 * General 32-bit SGET handler. 2850 * 2851 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2852 */ 2853 /* op vAA, field@BBBB */ 2854 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2855 FETCH(r1, 1) @ r1<- field ref BBBB 2856 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2857 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2858 cmp r0, #0 @ is resolved entry null? 2859 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2860.LOP_SGET_OBJECT_finish: @ field ptr in r0 2861 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2862 @ no-op @ acquiring load 2863 mov r2, rINST, lsr #8 @ r2<- AA 2864 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2865 SET_VREG(r1, r2) @ fp[AA]<- r1 2866 GET_INST_OPCODE(ip) @ extract opcode from rINST 2867 GOTO_OPCODE(ip) @ jump to next instruction 2868 2869 2870/* ------------------------------ */ 2871 .balign 64 2872.L_OP_SGET_BOOLEAN: /* 0x63 */ 2873/* File: armv5te/OP_SGET_BOOLEAN.S */ 2874/* File: armv5te/OP_SGET.S */ 2875 /* 2876 * General 32-bit SGET handler. 2877 * 2878 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2879 */ 2880 /* op vAA, field@BBBB */ 2881 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2882 FETCH(r1, 1) @ r1<- field ref BBBB 2883 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2884 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2885 cmp r0, #0 @ is resolved entry null? 2886 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2887.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2888 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2889 @ no-op @ acquiring load 2890 mov r2, rINST, lsr #8 @ r2<- AA 2891 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2892 SET_VREG(r1, r2) @ fp[AA]<- r1 2893 GET_INST_OPCODE(ip) @ extract opcode from rINST 2894 GOTO_OPCODE(ip) @ jump to next instruction 2895 2896 2897/* ------------------------------ */ 2898 .balign 64 2899.L_OP_SGET_BYTE: /* 0x64 */ 2900/* File: armv5te/OP_SGET_BYTE.S */ 2901/* File: armv5te/OP_SGET.S */ 2902 /* 2903 * General 32-bit SGET handler. 2904 * 2905 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2906 */ 2907 /* op vAA, field@BBBB */ 2908 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2909 FETCH(r1, 1) @ r1<- field ref BBBB 2910 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2911 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2912 cmp r0, #0 @ is resolved entry null? 2913 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2914.LOP_SGET_BYTE_finish: @ field ptr in r0 2915 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2916 @ no-op @ acquiring load 2917 mov r2, rINST, lsr #8 @ r2<- AA 2918 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2919 SET_VREG(r1, r2) @ fp[AA]<- r1 2920 GET_INST_OPCODE(ip) @ extract opcode from rINST 2921 GOTO_OPCODE(ip) @ jump to next instruction 2922 2923 2924/* ------------------------------ */ 2925 .balign 64 2926.L_OP_SGET_CHAR: /* 0x65 */ 2927/* File: armv5te/OP_SGET_CHAR.S */ 2928/* File: armv5te/OP_SGET.S */ 2929 /* 2930 * General 32-bit SGET handler. 2931 * 2932 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2933 */ 2934 /* op vAA, field@BBBB */ 2935 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2936 FETCH(r1, 1) @ r1<- field ref BBBB 2937 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2938 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2939 cmp r0, #0 @ is resolved entry null? 2940 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2941.LOP_SGET_CHAR_finish: @ field ptr in r0 2942 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2943 @ no-op @ acquiring load 2944 mov r2, rINST, lsr #8 @ r2<- AA 2945 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2946 SET_VREG(r1, r2) @ fp[AA]<- r1 2947 GET_INST_OPCODE(ip) @ extract opcode from rINST 2948 GOTO_OPCODE(ip) @ jump to next instruction 2949 2950 2951/* ------------------------------ */ 2952 .balign 64 2953.L_OP_SGET_SHORT: /* 0x66 */ 2954/* File: armv5te/OP_SGET_SHORT.S */ 2955/* File: armv5te/OP_SGET.S */ 2956 /* 2957 * General 32-bit SGET handler. 2958 * 2959 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2960 */ 2961 /* op vAA, field@BBBB */ 2962 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2963 FETCH(r1, 1) @ r1<- field ref BBBB 2964 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2965 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2966 cmp r0, #0 @ is resolved entry null? 2967 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 2968.LOP_SGET_SHORT_finish: @ field ptr in r0 2969 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2970 @ no-op @ acquiring load 2971 mov r2, rINST, lsr #8 @ r2<- AA 2972 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2973 SET_VREG(r1, r2) @ fp[AA]<- r1 2974 GET_INST_OPCODE(ip) @ extract opcode from rINST 2975 GOTO_OPCODE(ip) @ jump to next instruction 2976 2977 2978/* ------------------------------ */ 2979 .balign 64 2980.L_OP_SPUT: /* 0x67 */ 2981/* File: armv5te/OP_SPUT.S */ 2982 /* 2983 * General 32-bit SPUT handler. 2984 * 2985 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 2986 */ 2987 /* op vAA, field@BBBB */ 2988 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2989 FETCH(r1, 1) @ r1<- field ref BBBB 2990 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2991 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2992 cmp r0, #0 @ is resolved entry null? 2993 beq .LOP_SPUT_resolve @ yes, do resolve 2994.LOP_SPUT_finish: @ field ptr in r0 2995 mov r2, rINST, lsr #8 @ r2<- AA 2996 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2997 GET_VREG(r1, r2) @ r1<- fp[AA] 2998 GET_INST_OPCODE(ip) @ extract opcode from rINST 2999 @ no-op @ releasing store 3000 str r1, [r0, #offStaticField_value] @ field<- vAA 3001 GOTO_OPCODE(ip) @ jump to next instruction 3002 3003/* ------------------------------ */ 3004 .balign 64 3005.L_OP_SPUT_WIDE: /* 0x68 */ 3006/* File: armv5te/OP_SPUT_WIDE.S */ 3007 /* 3008 * 64-bit SPUT handler. 3009 */ 3010 /* sput-wide vAA, field@BBBB */ 3011 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 3012 FETCH(r1, 1) @ r1<- field ref BBBB 3013 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 3014 mov r9, rINST, lsr #8 @ r9<- AA 3015 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 3016 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 3017 cmp r2, #0 @ is resolved entry null? 3018 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 3019.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9 3020 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3021 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 3022 GET_INST_OPCODE(r10) @ extract opcode from rINST 3023 .if 0 3024 add r2, r2, #offStaticField_value @ r2<- pointer to data 3025 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 3026 .else 3027 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 3028 .endif 3029 GOTO_OPCODE(r10) @ jump to next instruction 3030 3031/* ------------------------------ */ 3032 .balign 64 3033.L_OP_SPUT_OBJECT: /* 0x69 */ 3034/* File: armv5te/OP_SPUT_OBJECT.S */ 3035 /* 3036 * 32-bit SPUT handler for objects 3037 * 3038 * for: sput-object, sput-object-volatile 3039 */ 3040 /* op vAA, field@BBBB */ 3041 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3042 FETCH(r1, 1) @ r1<- field ref BBBB 3043 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3044 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3045 cmp r0, #0 @ is resolved entry null? 3046 bne .LOP_SPUT_OBJECT_finish @ no, continue 3047 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 3048 EXPORT_PC() @ resolve() could throw, so export now 3049 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 3050 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 3051 cmp r0, #0 @ success? 3052 bne .LOP_SPUT_OBJECT_finish @ yes, finish 3053 b common_exceptionThrown @ no, handle exception 3054 3055 3056/* ------------------------------ */ 3057 .balign 64 3058.L_OP_SPUT_BOOLEAN: /* 0x6a */ 3059/* File: armv5te/OP_SPUT_BOOLEAN.S */ 3060/* File: armv5te/OP_SPUT.S */ 3061 /* 3062 * General 32-bit SPUT handler. 3063 * 3064 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3065 */ 3066 /* op vAA, field@BBBB */ 3067 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3068 FETCH(r1, 1) @ r1<- field ref BBBB 3069 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3070 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3071 cmp r0, #0 @ is resolved entry null? 3072 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 3073.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 3074 mov r2, rINST, lsr #8 @ r2<- AA 3075 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3076 GET_VREG(r1, r2) @ r1<- fp[AA] 3077 GET_INST_OPCODE(ip) @ extract opcode from rINST 3078 @ no-op @ releasing store 3079 str r1, [r0, #offStaticField_value] @ field<- vAA 3080 GOTO_OPCODE(ip) @ jump to next instruction 3081 3082 3083/* ------------------------------ */ 3084 .balign 64 3085.L_OP_SPUT_BYTE: /* 0x6b */ 3086/* File: armv5te/OP_SPUT_BYTE.S */ 3087/* File: armv5te/OP_SPUT.S */ 3088 /* 3089 * General 32-bit SPUT handler. 3090 * 3091 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3092 */ 3093 /* op vAA, field@BBBB */ 3094 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3095 FETCH(r1, 1) @ r1<- field ref BBBB 3096 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3097 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3098 cmp r0, #0 @ is resolved entry null? 3099 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 3100.LOP_SPUT_BYTE_finish: @ field ptr in r0 3101 mov r2, rINST, lsr #8 @ r2<- AA 3102 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3103 GET_VREG(r1, r2) @ r1<- fp[AA] 3104 GET_INST_OPCODE(ip) @ extract opcode from rINST 3105 @ no-op @ releasing store 3106 str r1, [r0, #offStaticField_value] @ field<- vAA 3107 GOTO_OPCODE(ip) @ jump to next instruction 3108 3109 3110/* ------------------------------ */ 3111 .balign 64 3112.L_OP_SPUT_CHAR: /* 0x6c */ 3113/* File: armv5te/OP_SPUT_CHAR.S */ 3114/* File: armv5te/OP_SPUT.S */ 3115 /* 3116 * General 32-bit SPUT handler. 3117 * 3118 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3119 */ 3120 /* op vAA, field@BBBB */ 3121 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3122 FETCH(r1, 1) @ r1<- field ref BBBB 3123 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3124 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3125 cmp r0, #0 @ is resolved entry null? 3126 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 3127.LOP_SPUT_CHAR_finish: @ field ptr in r0 3128 mov r2, rINST, lsr #8 @ r2<- AA 3129 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3130 GET_VREG(r1, r2) @ r1<- fp[AA] 3131 GET_INST_OPCODE(ip) @ extract opcode from rINST 3132 @ no-op @ releasing store 3133 str r1, [r0, #offStaticField_value] @ field<- vAA 3134 GOTO_OPCODE(ip) @ jump to next instruction 3135 3136 3137/* ------------------------------ */ 3138 .balign 64 3139.L_OP_SPUT_SHORT: /* 0x6d */ 3140/* File: armv5te/OP_SPUT_SHORT.S */ 3141/* File: armv5te/OP_SPUT.S */ 3142 /* 3143 * General 32-bit SPUT handler. 3144 * 3145 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3146 */ 3147 /* op vAA, field@BBBB */ 3148 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3149 FETCH(r1, 1) @ r1<- field ref BBBB 3150 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3151 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3152 cmp r0, #0 @ is resolved entry null? 3153 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 3154.LOP_SPUT_SHORT_finish: @ field ptr in r0 3155 mov r2, rINST, lsr #8 @ r2<- AA 3156 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3157 GET_VREG(r1, r2) @ r1<- fp[AA] 3158 GET_INST_OPCODE(ip) @ extract opcode from rINST 3159 @ no-op @ releasing store 3160 str r1, [r0, #offStaticField_value] @ field<- vAA 3161 GOTO_OPCODE(ip) @ jump to next instruction 3162 3163 3164/* ------------------------------ */ 3165 .balign 64 3166.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3167/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3168 /* 3169 * Handle a virtual method call. 3170 * 3171 * for: invoke-virtual, invoke-virtual/range 3172 */ 3173 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3174 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3175 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3176 FETCH(r1, 1) @ r1<- BBBB 3177 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3178 FETCH(r10, 2) @ r10<- GFED or CCCC 3179 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3180 .if (!0) 3181 and r10, r10, #15 @ r10<- D (or stays CCCC) 3182 .endif 3183 cmp r0, #0 @ already resolved? 3184 EXPORT_PC() @ must export for invoke 3185 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3186 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3187 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3188 mov r2, #METHOD_VIRTUAL @ resolver method type 3189 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3190 cmp r0, #0 @ got null? 3191 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3192 b common_exceptionThrown @ yes, handle exception 3193 3194/* ------------------------------ */ 3195 .balign 64 3196.L_OP_INVOKE_SUPER: /* 0x6f */ 3197/* File: armv5te/OP_INVOKE_SUPER.S */ 3198 /* 3199 * Handle a "super" method call. 3200 * 3201 * for: invoke-super, invoke-super/range 3202 */ 3203 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3204 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3205 FETCH(r10, 2) @ r10<- GFED or CCCC 3206 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3207 .if (!0) 3208 and r10, r10, #15 @ r10<- D (or stays CCCC) 3209 .endif 3210 FETCH(r1, 1) @ r1<- BBBB 3211 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3212 GET_VREG(r2, r10) @ r2<- "this" ptr 3213 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3214 cmp r2, #0 @ null "this"? 3215 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3216 beq common_errNullObject @ null "this", throw exception 3217 cmp r0, #0 @ already resolved? 3218 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3219 EXPORT_PC() @ must export for invoke 3220 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3221 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3222 3223/* ------------------------------ */ 3224 .balign 64 3225.L_OP_INVOKE_DIRECT: /* 0x70 */ 3226/* File: armv5te/OP_INVOKE_DIRECT.S */ 3227 /* 3228 * Handle a direct method call. 3229 * 3230 * (We could defer the "is 'this' pointer null" test to the common 3231 * method invocation code, and use a flag to indicate that static 3232 * calls don't count. If we do this as part of copying the arguments 3233 * out we could avoiding loading the first arg twice.) 3234 * 3235 * for: invoke-direct, invoke-direct/range 3236 */ 3237 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3238 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3239 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3240 FETCH(r1, 1) @ r1<- BBBB 3241 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3242 FETCH(r10, 2) @ r10<- GFED or CCCC 3243 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3244 .if (!0) 3245 and r10, r10, #15 @ r10<- D (or stays CCCC) 3246 .endif 3247 cmp r0, #0 @ already resolved? 3248 EXPORT_PC() @ must export for invoke 3249 GET_VREG(r2, r10) @ r2<- "this" ptr 3250 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3251.LOP_INVOKE_DIRECT_finish: 3252 cmp r2, #0 @ null "this" ref? 3253 bne common_invokeMethodNoRange @ no, continue on 3254 b common_errNullObject @ yes, throw exception 3255 3256/* ------------------------------ */ 3257 .balign 64 3258.L_OP_INVOKE_STATIC: /* 0x71 */ 3259/* File: armv5te/OP_INVOKE_STATIC.S */ 3260 /* 3261 * Handle a static method call. 3262 * 3263 * for: invoke-static, invoke-static/range 3264 */ 3265 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3266 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3267 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3268 FETCH(r1, 1) @ r1<- BBBB 3269 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3270 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3271 cmp r0, #0 @ already resolved? 3272 EXPORT_PC() @ must export for invoke 3273 bne common_invokeMethodNoRange @ yes, continue on 32740: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3275 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3276 mov r2, #METHOD_STATIC @ resolver method type 3277 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3278 cmp r0, #0 @ got null? 3279 bne common_invokeMethodNoRange @ no, continue 3280 b common_exceptionThrown @ yes, handle exception 3281 3282/* ------------------------------ */ 3283 .balign 64 3284.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3285/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3286 /* 3287 * Handle an interface method call. 3288 * 3289 * for: invoke-interface, invoke-interface/range 3290 */ 3291 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3292 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3293 FETCH(r2, 2) @ r2<- FEDC or CCCC 3294 FETCH(r1, 1) @ r1<- BBBB 3295 .if (!0) 3296 and r2, r2, #15 @ r2<- C (or stays CCCC) 3297 .endif 3298 EXPORT_PC() @ must export for invoke 3299 GET_VREG(r0, r2) @ r0<- first arg ("this") 3300 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3301 cmp r0, #0 @ null obj? 3302 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3303 beq common_errNullObject @ yes, fail 3304 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3305 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3306 cmp r0, #0 @ failed? 3307 beq common_exceptionThrown @ yes, handle exception 3308 b common_invokeMethodNoRange @ jump to common handler 3309 3310/* ------------------------------ */ 3311 .balign 64 3312.L_OP_UNUSED_73: /* 0x73 */ 3313/* File: armv5te/OP_UNUSED_73.S */ 3314/* File: armv5te/unused.S */ 3315 bl common_abort 3316 3317 3318/* ------------------------------ */ 3319 .balign 64 3320.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3321/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3322/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3323 /* 3324 * Handle a virtual method call. 3325 * 3326 * for: invoke-virtual, invoke-virtual/range 3327 */ 3328 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3329 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3330 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3331 FETCH(r1, 1) @ r1<- BBBB 3332 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3333 FETCH(r10, 2) @ r10<- GFED or CCCC 3334 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3335 .if (!1) 3336 and r10, r10, #15 @ r10<- D (or stays CCCC) 3337 .endif 3338 cmp r0, #0 @ already resolved? 3339 EXPORT_PC() @ must export for invoke 3340 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3341 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3342 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3343 mov r2, #METHOD_VIRTUAL @ resolver method type 3344 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3345 cmp r0, #0 @ got null? 3346 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3347 b common_exceptionThrown @ yes, handle exception 3348 3349 3350/* ------------------------------ */ 3351 .balign 64 3352.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3353/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3354/* File: armv5te/OP_INVOKE_SUPER.S */ 3355 /* 3356 * Handle a "super" method call. 3357 * 3358 * for: invoke-super, invoke-super/range 3359 */ 3360 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3361 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3362 FETCH(r10, 2) @ r10<- GFED or CCCC 3363 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3364 .if (!1) 3365 and r10, r10, #15 @ r10<- D (or stays CCCC) 3366 .endif 3367 FETCH(r1, 1) @ r1<- BBBB 3368 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3369 GET_VREG(r2, r10) @ r2<- "this" ptr 3370 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3371 cmp r2, #0 @ null "this"? 3372 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3373 beq common_errNullObject @ null "this", throw exception 3374 cmp r0, #0 @ already resolved? 3375 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3376 EXPORT_PC() @ must export for invoke 3377 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3378 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3379 3380 3381/* ------------------------------ */ 3382 .balign 64 3383.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3384/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3385/* File: armv5te/OP_INVOKE_DIRECT.S */ 3386 /* 3387 * Handle a direct method call. 3388 * 3389 * (We could defer the "is 'this' pointer null" test to the common 3390 * method invocation code, and use a flag to indicate that static 3391 * calls don't count. If we do this as part of copying the arguments 3392 * out we could avoiding loading the first arg twice.) 3393 * 3394 * for: invoke-direct, invoke-direct/range 3395 */ 3396 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3397 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3398 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3399 FETCH(r1, 1) @ r1<- BBBB 3400 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3401 FETCH(r10, 2) @ r10<- GFED or CCCC 3402 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3403 .if (!1) 3404 and r10, r10, #15 @ r10<- D (or stays CCCC) 3405 .endif 3406 cmp r0, #0 @ already resolved? 3407 EXPORT_PC() @ must export for invoke 3408 GET_VREG(r2, r10) @ r2<- "this" ptr 3409 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3410.LOP_INVOKE_DIRECT_RANGE_finish: 3411 cmp r2, #0 @ null "this" ref? 3412 bne common_invokeMethodRange @ no, continue on 3413 b common_errNullObject @ yes, throw exception 3414 3415 3416/* ------------------------------ */ 3417 .balign 64 3418.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3419/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3420/* File: armv5te/OP_INVOKE_STATIC.S */ 3421 /* 3422 * Handle a static method call. 3423 * 3424 * for: invoke-static, invoke-static/range 3425 */ 3426 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3427 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3428 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3429 FETCH(r1, 1) @ r1<- BBBB 3430 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3431 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3432 cmp r0, #0 @ already resolved? 3433 EXPORT_PC() @ must export for invoke 3434 bne common_invokeMethodRange @ yes, continue on 34350: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3436 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3437 mov r2, #METHOD_STATIC @ resolver method type 3438 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3439 cmp r0, #0 @ got null? 3440 bne common_invokeMethodRange @ no, continue 3441 b common_exceptionThrown @ yes, handle exception 3442 3443 3444/* ------------------------------ */ 3445 .balign 64 3446.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3447/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3448/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3449 /* 3450 * Handle an interface method call. 3451 * 3452 * for: invoke-interface, invoke-interface/range 3453 */ 3454 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3455 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3456 FETCH(r2, 2) @ r2<- FEDC or CCCC 3457 FETCH(r1, 1) @ r1<- BBBB 3458 .if (!1) 3459 and r2, r2, #15 @ r2<- C (or stays CCCC) 3460 .endif 3461 EXPORT_PC() @ must export for invoke 3462 GET_VREG(r0, r2) @ r0<- first arg ("this") 3463 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3464 cmp r0, #0 @ null obj? 3465 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3466 beq common_errNullObject @ yes, fail 3467 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3468 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3469 cmp r0, #0 @ failed? 3470 beq common_exceptionThrown @ yes, handle exception 3471 b common_invokeMethodRange @ jump to common handler 3472 3473 3474/* ------------------------------ */ 3475 .balign 64 3476.L_OP_UNUSED_79: /* 0x79 */ 3477/* File: armv5te/OP_UNUSED_79.S */ 3478/* File: armv5te/unused.S */ 3479 bl common_abort 3480 3481 3482/* ------------------------------ */ 3483 .balign 64 3484.L_OP_UNUSED_7A: /* 0x7a */ 3485/* File: armv5te/OP_UNUSED_7A.S */ 3486/* File: armv5te/unused.S */ 3487 bl common_abort 3488 3489 3490/* ------------------------------ */ 3491 .balign 64 3492.L_OP_NEG_INT: /* 0x7b */ 3493/* File: armv5te/OP_NEG_INT.S */ 3494/* File: armv5te/unop.S */ 3495 /* 3496 * Generic 32-bit unary operation. Provide an "instr" line that 3497 * specifies an instruction that performs "result = op r0". 3498 * This could be an ARM instruction or a function call. 3499 * 3500 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3501 * int-to-byte, int-to-char, int-to-short 3502 */ 3503 /* unop vA, vB */ 3504 mov r3, rINST, lsr #12 @ r3<- B 3505 mov r9, rINST, lsr #8 @ r9<- A+ 3506 GET_VREG(r0, r3) @ r0<- vB 3507 and r9, r9, #15 3508 @ optional op; may set condition codes 3509 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3510 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3511 GET_INST_OPCODE(ip) @ extract opcode from rINST 3512 SET_VREG(r0, r9) @ vAA<- r0 3513 GOTO_OPCODE(ip) @ jump to next instruction 3514 /* 9-10 instructions */ 3515 3516 3517/* ------------------------------ */ 3518 .balign 64 3519.L_OP_NOT_INT: /* 0x7c */ 3520/* File: armv5te/OP_NOT_INT.S */ 3521/* File: armv5te/unop.S */ 3522 /* 3523 * Generic 32-bit unary operation. Provide an "instr" line that 3524 * specifies an instruction that performs "result = op r0". 3525 * This could be an ARM instruction or a function call. 3526 * 3527 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3528 * int-to-byte, int-to-char, int-to-short 3529 */ 3530 /* unop vA, vB */ 3531 mov r3, rINST, lsr #12 @ r3<- B 3532 mov r9, rINST, lsr #8 @ r9<- A+ 3533 GET_VREG(r0, r3) @ r0<- vB 3534 and r9, r9, #15 3535 @ optional op; may set condition codes 3536 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3537 mvn r0, r0 @ r0<- op, r0-r3 changed 3538 GET_INST_OPCODE(ip) @ extract opcode from rINST 3539 SET_VREG(r0, r9) @ vAA<- r0 3540 GOTO_OPCODE(ip) @ jump to next instruction 3541 /* 9-10 instructions */ 3542 3543 3544/* ------------------------------ */ 3545 .balign 64 3546.L_OP_NEG_LONG: /* 0x7d */ 3547/* File: armv5te/OP_NEG_LONG.S */ 3548/* File: armv5te/unopWide.S */ 3549 /* 3550 * Generic 64-bit unary operation. Provide an "instr" line that 3551 * specifies an instruction that performs "result = op r0/r1". 3552 * This could be an ARM instruction or a function call. 3553 * 3554 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3555 */ 3556 /* unop vA, vB */ 3557 mov r9, rINST, lsr #8 @ r9<- A+ 3558 mov r3, rINST, lsr #12 @ r3<- B 3559 and r9, r9, #15 3560 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3561 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3562 ldmia r3, {r0-r1} @ r0/r1<- vAA 3563 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3564 rsbs r0, r0, #0 @ optional op; may set condition codes 3565 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3566 GET_INST_OPCODE(ip) @ extract opcode from rINST 3567 stmia r9, {r0-r1} @ vAA<- r0/r1 3568 GOTO_OPCODE(ip) @ jump to next instruction 3569 /* 12-13 instructions */ 3570 3571 3572/* ------------------------------ */ 3573 .balign 64 3574.L_OP_NOT_LONG: /* 0x7e */ 3575/* File: armv5te/OP_NOT_LONG.S */ 3576/* File: armv5te/unopWide.S */ 3577 /* 3578 * Generic 64-bit unary operation. Provide an "instr" line that 3579 * specifies an instruction that performs "result = op r0/r1". 3580 * This could be an ARM instruction or a function call. 3581 * 3582 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3583 */ 3584 /* unop vA, vB */ 3585 mov r9, rINST, lsr #8 @ r9<- A+ 3586 mov r3, rINST, lsr #12 @ r3<- B 3587 and r9, r9, #15 3588 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3589 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3590 ldmia r3, {r0-r1} @ r0/r1<- vAA 3591 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3592 mvn r0, r0 @ optional op; may set condition codes 3593 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3594 GET_INST_OPCODE(ip) @ extract opcode from rINST 3595 stmia r9, {r0-r1} @ vAA<- r0/r1 3596 GOTO_OPCODE(ip) @ jump to next instruction 3597 /* 12-13 instructions */ 3598 3599 3600/* ------------------------------ */ 3601 .balign 64 3602.L_OP_NEG_FLOAT: /* 0x7f */ 3603/* File: armv5te/OP_NEG_FLOAT.S */ 3604/* File: armv5te/unop.S */ 3605 /* 3606 * Generic 32-bit unary operation. Provide an "instr" line that 3607 * specifies an instruction that performs "result = op r0". 3608 * This could be an ARM instruction or a function call. 3609 * 3610 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3611 * int-to-byte, int-to-char, int-to-short 3612 */ 3613 /* unop vA, vB */ 3614 mov r3, rINST, lsr #12 @ r3<- B 3615 mov r9, rINST, lsr #8 @ r9<- A+ 3616 GET_VREG(r0, r3) @ r0<- vB 3617 and r9, r9, #15 3618 @ optional op; may set condition codes 3619 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3620 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3621 GET_INST_OPCODE(ip) @ extract opcode from rINST 3622 SET_VREG(r0, r9) @ vAA<- r0 3623 GOTO_OPCODE(ip) @ jump to next instruction 3624 /* 9-10 instructions */ 3625 3626 3627/* ------------------------------ */ 3628 .balign 64 3629.L_OP_NEG_DOUBLE: /* 0x80 */ 3630/* File: armv5te/OP_NEG_DOUBLE.S */ 3631/* File: armv5te/unopWide.S */ 3632 /* 3633 * Generic 64-bit unary operation. Provide an "instr" line that 3634 * specifies an instruction that performs "result = op r0/r1". 3635 * This could be an ARM instruction or a function call. 3636 * 3637 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3638 */ 3639 /* unop vA, vB */ 3640 mov r9, rINST, lsr #8 @ r9<- A+ 3641 mov r3, rINST, lsr #12 @ r3<- B 3642 and r9, r9, #15 3643 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3644 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3645 ldmia r3, {r0-r1} @ r0/r1<- vAA 3646 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3647 @ optional op; may set condition codes 3648 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3649 GET_INST_OPCODE(ip) @ extract opcode from rINST 3650 stmia r9, {r0-r1} @ vAA<- r0/r1 3651 GOTO_OPCODE(ip) @ jump to next instruction 3652 /* 12-13 instructions */ 3653 3654 3655/* ------------------------------ */ 3656 .balign 64 3657.L_OP_INT_TO_LONG: /* 0x81 */ 3658/* File: armv5te/OP_INT_TO_LONG.S */ 3659/* File: armv5te/unopWider.S */ 3660 /* 3661 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3662 * that specifies an instruction that performs "result = op r0", where 3663 * "result" is a 64-bit quantity in r0/r1. 3664 * 3665 * For: int-to-long, int-to-double, float-to-long, float-to-double 3666 */ 3667 /* unop vA, vB */ 3668 mov r9, rINST, lsr #8 @ r9<- A+ 3669 mov r3, rINST, lsr #12 @ r3<- B 3670 and r9, r9, #15 3671 GET_VREG(r0, r3) @ r0<- vB 3672 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3673 @ optional op; may set condition codes 3674 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3675 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3676 GET_INST_OPCODE(ip) @ extract opcode from rINST 3677 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3678 GOTO_OPCODE(ip) @ jump to next instruction 3679 /* 10-11 instructions */ 3680 3681 3682/* ------------------------------ */ 3683 .balign 64 3684.L_OP_INT_TO_FLOAT: /* 0x82 */ 3685/* File: arm-vfp/OP_INT_TO_FLOAT.S */ 3686/* File: arm-vfp/funop.S */ 3687 /* 3688 * Generic 32-bit unary floating-point operation. Provide an "instr" 3689 * line that specifies an instruction that performs "s1 = op s0". 3690 * 3691 * for: int-to-float, float-to-int 3692 */ 3693 /* unop vA, vB */ 3694 mov r3, rINST, lsr #12 @ r3<- B 3695 mov r9, rINST, lsr #8 @ r9<- A+ 3696 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3697 flds s0, [r3] @ s0<- vB 3698 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3699 and r9, r9, #15 @ r9<- A 3700 fsitos s1, s0 @ s1<- op 3701 GET_INST_OPCODE(ip) @ extract opcode from rINST 3702 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3703 fsts s1, [r9] @ vA<- s1 3704 GOTO_OPCODE(ip) @ jump to next instruction 3705 3706 3707/* ------------------------------ */ 3708 .balign 64 3709.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3710/* File: arm-vfp/OP_INT_TO_DOUBLE.S */ 3711/* File: arm-vfp/funopWider.S */ 3712 /* 3713 * Generic 32bit-to-64bit floating point unary operation. Provide an 3714 * "instr" line that specifies an instruction that performs "d0 = op s0". 3715 * 3716 * For: int-to-double, float-to-double 3717 */ 3718 /* unop vA, vB */ 3719 mov r3, rINST, lsr #12 @ r3<- B 3720 mov r9, rINST, lsr #8 @ r9<- A+ 3721 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3722 flds s0, [r3] @ s0<- vB 3723 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3724 and r9, r9, #15 @ r9<- A 3725 fsitod d0, s0 @ d0<- op 3726 GET_INST_OPCODE(ip) @ extract opcode from rINST 3727 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3728 fstd d0, [r9] @ vA<- d0 3729 GOTO_OPCODE(ip) @ jump to next instruction 3730 3731 3732/* ------------------------------ */ 3733 .balign 64 3734.L_OP_LONG_TO_INT: /* 0x84 */ 3735/* File: armv5te/OP_LONG_TO_INT.S */ 3736/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3737/* File: armv5te/OP_MOVE.S */ 3738 /* for move, move-object, long-to-int */ 3739 /* op vA, vB */ 3740 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3741 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3742 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3743 GET_VREG(r2, r1) @ r2<- fp[B] 3744 and r0, r0, #15 3745 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3746 SET_VREG(r2, r0) @ fp[A]<- r2 3747 GOTO_OPCODE(ip) @ execute next instruction 3748 3749 3750/* ------------------------------ */ 3751 .balign 64 3752.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3753/* File: armv5te/OP_LONG_TO_FLOAT.S */ 3754/* File: armv5te/unopNarrower.S */ 3755 /* 3756 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3757 * that specifies an instruction that performs "result = op r0/r1", where 3758 * "result" is a 32-bit quantity in r0. 3759 * 3760 * For: long-to-float, double-to-int, double-to-float 3761 * 3762 * (This would work for long-to-int, but that instruction is actually 3763 * an exact match for OP_MOVE.) 3764 */ 3765 /* unop vA, vB */ 3766 mov r3, rINST, lsr #12 @ r3<- B 3767 mov r9, rINST, lsr #8 @ r9<- A+ 3768 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3769 and r9, r9, #15 3770 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3771 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3772 @ optional op; may set condition codes 3773 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3774 GET_INST_OPCODE(ip) @ extract opcode from rINST 3775 SET_VREG(r0, r9) @ vA<- r0 3776 GOTO_OPCODE(ip) @ jump to next instruction 3777 /* 10-11 instructions */ 3778 3779 3780/* ------------------------------ */ 3781 .balign 64 3782.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3783/* File: armv5te/OP_LONG_TO_DOUBLE.S */ 3784/* File: armv5te/unopWide.S */ 3785 /* 3786 * Generic 64-bit unary operation. Provide an "instr" line that 3787 * specifies an instruction that performs "result = op r0/r1". 3788 * This could be an ARM instruction or a function call. 3789 * 3790 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3791 */ 3792 /* unop vA, vB */ 3793 mov r9, rINST, lsr #8 @ r9<- A+ 3794 mov r3, rINST, lsr #12 @ r3<- B 3795 and r9, r9, #15 3796 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3797 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3798 ldmia r3, {r0-r1} @ r0/r1<- vAA 3799 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3800 @ optional op; may set condition codes 3801 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3802 GET_INST_OPCODE(ip) @ extract opcode from rINST 3803 stmia r9, {r0-r1} @ vAA<- r0/r1 3804 GOTO_OPCODE(ip) @ jump to next instruction 3805 /* 12-13 instructions */ 3806 3807 3808/* ------------------------------ */ 3809 .balign 64 3810.L_OP_FLOAT_TO_INT: /* 0x87 */ 3811/* File: arm-vfp/OP_FLOAT_TO_INT.S */ 3812/* File: arm-vfp/funop.S */ 3813 /* 3814 * Generic 32-bit unary floating-point operation. Provide an "instr" 3815 * line that specifies an instruction that performs "s1 = op s0". 3816 * 3817 * for: int-to-float, float-to-int 3818 */ 3819 /* unop vA, vB */ 3820 mov r3, rINST, lsr #12 @ r3<- B 3821 mov r9, rINST, lsr #8 @ r9<- A+ 3822 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3823 flds s0, [r3] @ s0<- vB 3824 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3825 and r9, r9, #15 @ r9<- A 3826 ftosizs s1, s0 @ s1<- op 3827 GET_INST_OPCODE(ip) @ extract opcode from rINST 3828 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3829 fsts s1, [r9] @ vA<- s1 3830 GOTO_OPCODE(ip) @ jump to next instruction 3831 3832 3833/* ------------------------------ */ 3834 .balign 64 3835.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3836/* File: armv5te/OP_FLOAT_TO_LONG.S */ 3837@include "armv5te/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3838/* File: armv5te/unopWider.S */ 3839 /* 3840 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3841 * that specifies an instruction that performs "result = op r0", where 3842 * "result" is a 64-bit quantity in r0/r1. 3843 * 3844 * For: int-to-long, int-to-double, float-to-long, float-to-double 3845 */ 3846 /* unop vA, vB */ 3847 mov r9, rINST, lsr #8 @ r9<- A+ 3848 mov r3, rINST, lsr #12 @ r3<- B 3849 and r9, r9, #15 3850 GET_VREG(r0, r3) @ r0<- vB 3851 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3852 @ optional op; may set condition codes 3853 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3854 bl f2l_doconv @ r0<- op, r0-r3 changed 3855 GET_INST_OPCODE(ip) @ extract opcode from rINST 3856 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3857 GOTO_OPCODE(ip) @ jump to next instruction 3858 /* 10-11 instructions */ 3859 3860 3861 3862/* ------------------------------ */ 3863 .balign 64 3864.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3865/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */ 3866/* File: arm-vfp/funopWider.S */ 3867 /* 3868 * Generic 32bit-to-64bit floating point unary operation. Provide an 3869 * "instr" line that specifies an instruction that performs "d0 = op s0". 3870 * 3871 * For: int-to-double, float-to-double 3872 */ 3873 /* unop vA, vB */ 3874 mov r3, rINST, lsr #12 @ r3<- B 3875 mov r9, rINST, lsr #8 @ r9<- A+ 3876 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3877 flds s0, [r3] @ s0<- vB 3878 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3879 and r9, r9, #15 @ r9<- A 3880 fcvtds d0, s0 @ d0<- op 3881 GET_INST_OPCODE(ip) @ extract opcode from rINST 3882 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3883 fstd d0, [r9] @ vA<- d0 3884 GOTO_OPCODE(ip) @ jump to next instruction 3885 3886 3887/* ------------------------------ */ 3888 .balign 64 3889.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3890/* File: arm-vfp/OP_DOUBLE_TO_INT.S */ 3891/* File: arm-vfp/funopNarrower.S */ 3892 /* 3893 * Generic 64bit-to-32bit unary floating point operation. Provide an 3894 * "instr" line that specifies an instruction that performs "s0 = op d0". 3895 * 3896 * For: double-to-int, double-to-float 3897 */ 3898 /* unop vA, vB */ 3899 mov r3, rINST, lsr #12 @ r3<- B 3900 mov r9, rINST, lsr #8 @ r9<- A+ 3901 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3902 fldd d0, [r3] @ d0<- vB 3903 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3904 and r9, r9, #15 @ r9<- A 3905 ftosizd s0, d0 @ s0<- op 3906 GET_INST_OPCODE(ip) @ extract opcode from rINST 3907 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3908 fsts s0, [r9] @ vA<- s0 3909 GOTO_OPCODE(ip) @ jump to next instruction 3910 3911 3912/* ------------------------------ */ 3913 .balign 64 3914.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3915/* File: armv5te/OP_DOUBLE_TO_LONG.S */ 3916@include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"} 3917/* File: armv5te/unopWide.S */ 3918 /* 3919 * Generic 64-bit unary operation. Provide an "instr" line that 3920 * specifies an instruction that performs "result = op r0/r1". 3921 * This could be an ARM instruction or a function call. 3922 * 3923 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3924 */ 3925 /* unop vA, vB */ 3926 mov r9, rINST, lsr #8 @ r9<- A+ 3927 mov r3, rINST, lsr #12 @ r3<- B 3928 and r9, r9, #15 3929 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3930 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3931 ldmia r3, {r0-r1} @ r0/r1<- vAA 3932 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3933 @ optional op; may set condition codes 3934 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 3935 GET_INST_OPCODE(ip) @ extract opcode from rINST 3936 stmia r9, {r0-r1} @ vAA<- r0/r1 3937 GOTO_OPCODE(ip) @ jump to next instruction 3938 /* 12-13 instructions */ 3939 3940 3941 3942/* ------------------------------ */ 3943 .balign 64 3944.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3945/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */ 3946/* File: arm-vfp/funopNarrower.S */ 3947 /* 3948 * Generic 64bit-to-32bit unary floating point operation. Provide an 3949 * "instr" line that specifies an instruction that performs "s0 = op d0". 3950 * 3951 * For: double-to-int, double-to-float 3952 */ 3953 /* unop vA, vB */ 3954 mov r3, rINST, lsr #12 @ r3<- B 3955 mov r9, rINST, lsr #8 @ r9<- A+ 3956 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3957 fldd d0, [r3] @ d0<- vB 3958 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3959 and r9, r9, #15 @ r9<- A 3960 fcvtsd s0, d0 @ s0<- op 3961 GET_INST_OPCODE(ip) @ extract opcode from rINST 3962 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3963 fsts s0, [r9] @ vA<- s0 3964 GOTO_OPCODE(ip) @ jump to next instruction 3965 3966 3967/* ------------------------------ */ 3968 .balign 64 3969.L_OP_INT_TO_BYTE: /* 0x8d */ 3970/* File: armv5te/OP_INT_TO_BYTE.S */ 3971/* File: armv5te/unop.S */ 3972 /* 3973 * Generic 32-bit unary operation. Provide an "instr" line that 3974 * specifies an instruction that performs "result = op r0". 3975 * This could be an ARM instruction or a function call. 3976 * 3977 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3978 * int-to-byte, int-to-char, int-to-short 3979 */ 3980 /* unop vA, vB */ 3981 mov r3, rINST, lsr #12 @ r3<- B 3982 mov r9, rINST, lsr #8 @ r9<- A+ 3983 GET_VREG(r0, r3) @ r0<- vB 3984 and r9, r9, #15 3985 mov r0, r0, asl #24 @ optional op; may set condition codes 3986 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3987 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed 3988 GET_INST_OPCODE(ip) @ extract opcode from rINST 3989 SET_VREG(r0, r9) @ vAA<- r0 3990 GOTO_OPCODE(ip) @ jump to next instruction 3991 /* 9-10 instructions */ 3992 3993 3994/* ------------------------------ */ 3995 .balign 64 3996.L_OP_INT_TO_CHAR: /* 0x8e */ 3997/* File: armv5te/OP_INT_TO_CHAR.S */ 3998/* File: armv5te/unop.S */ 3999 /* 4000 * Generic 32-bit unary operation. Provide an "instr" line that 4001 * specifies an instruction that performs "result = op r0". 4002 * This could be an ARM instruction or a function call. 4003 * 4004 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4005 * int-to-byte, int-to-char, int-to-short 4006 */ 4007 /* unop vA, vB */ 4008 mov r3, rINST, lsr #12 @ r3<- B 4009 mov r9, rINST, lsr #8 @ r9<- A+ 4010 GET_VREG(r0, r3) @ r0<- vB 4011 and r9, r9, #15 4012 mov r0, r0, asl #16 @ optional op; may set condition codes 4013 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4014 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed 4015 GET_INST_OPCODE(ip) @ extract opcode from rINST 4016 SET_VREG(r0, r9) @ vAA<- r0 4017 GOTO_OPCODE(ip) @ jump to next instruction 4018 /* 9-10 instructions */ 4019 4020 4021/* ------------------------------ */ 4022 .balign 64 4023.L_OP_INT_TO_SHORT: /* 0x8f */ 4024/* File: armv5te/OP_INT_TO_SHORT.S */ 4025/* File: armv5te/unop.S */ 4026 /* 4027 * Generic 32-bit unary operation. Provide an "instr" line that 4028 * specifies an instruction that performs "result = op r0". 4029 * This could be an ARM instruction or a function call. 4030 * 4031 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4032 * int-to-byte, int-to-char, int-to-short 4033 */ 4034 /* unop vA, vB */ 4035 mov r3, rINST, lsr #12 @ r3<- B 4036 mov r9, rINST, lsr #8 @ r9<- A+ 4037 GET_VREG(r0, r3) @ r0<- vB 4038 and r9, r9, #15 4039 mov r0, r0, asl #16 @ optional op; may set condition codes 4040 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4041 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed 4042 GET_INST_OPCODE(ip) @ extract opcode from rINST 4043 SET_VREG(r0, r9) @ vAA<- r0 4044 GOTO_OPCODE(ip) @ jump to next instruction 4045 /* 9-10 instructions */ 4046 4047 4048/* ------------------------------ */ 4049 .balign 64 4050.L_OP_ADD_INT: /* 0x90 */ 4051/* File: armv5te/OP_ADD_INT.S */ 4052/* File: armv5te/binop.S */ 4053 /* 4054 * Generic 32-bit binary operation. Provide an "instr" line that 4055 * specifies an instruction that performs "result = r0 op r1". 4056 * This could be an ARM instruction or a function call. (If the result 4057 * comes back in a register other than r0, you can override "result".) 4058 * 4059 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4060 * vCC (r1). Useful for integer division and modulus. Note that we 4061 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4062 * handles it correctly. 4063 * 4064 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4065 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4066 * mul-float, div-float, rem-float 4067 */ 4068 /* binop vAA, vBB, vCC */ 4069 FETCH(r0, 1) @ r0<- CCBB 4070 mov r9, rINST, lsr #8 @ r9<- AA 4071 mov r3, r0, lsr #8 @ r3<- CC 4072 and r2, r0, #255 @ r2<- BB 4073 GET_VREG(r1, r3) @ r1<- vCC 4074 GET_VREG(r0, r2) @ r0<- vBB 4075 .if 0 4076 cmp r1, #0 @ is second operand zero? 4077 beq common_errDivideByZero 4078 .endif 4079 4080 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4081 @ optional op; may set condition codes 4082 add r0, r0, r1 @ r0<- op, r0-r3 changed 4083 GET_INST_OPCODE(ip) @ extract opcode from rINST 4084 SET_VREG(r0, r9) @ vAA<- r0 4085 GOTO_OPCODE(ip) @ jump to next instruction 4086 /* 11-14 instructions */ 4087 4088 4089/* ------------------------------ */ 4090 .balign 64 4091.L_OP_SUB_INT: /* 0x91 */ 4092/* File: armv5te/OP_SUB_INT.S */ 4093/* File: armv5te/binop.S */ 4094 /* 4095 * Generic 32-bit binary operation. Provide an "instr" line that 4096 * specifies an instruction that performs "result = r0 op r1". 4097 * This could be an ARM instruction or a function call. (If the result 4098 * comes back in a register other than r0, you can override "result".) 4099 * 4100 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4101 * vCC (r1). Useful for integer division and modulus. Note that we 4102 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4103 * handles it correctly. 4104 * 4105 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4106 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4107 * mul-float, div-float, rem-float 4108 */ 4109 /* binop vAA, vBB, vCC */ 4110 FETCH(r0, 1) @ r0<- CCBB 4111 mov r9, rINST, lsr #8 @ r9<- AA 4112 mov r3, r0, lsr #8 @ r3<- CC 4113 and r2, r0, #255 @ r2<- BB 4114 GET_VREG(r1, r3) @ r1<- vCC 4115 GET_VREG(r0, r2) @ r0<- vBB 4116 .if 0 4117 cmp r1, #0 @ is second operand zero? 4118 beq common_errDivideByZero 4119 .endif 4120 4121 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4122 @ optional op; may set condition codes 4123 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4124 GET_INST_OPCODE(ip) @ extract opcode from rINST 4125 SET_VREG(r0, r9) @ vAA<- r0 4126 GOTO_OPCODE(ip) @ jump to next instruction 4127 /* 11-14 instructions */ 4128 4129 4130/* ------------------------------ */ 4131 .balign 64 4132.L_OP_MUL_INT: /* 0x92 */ 4133/* File: armv5te/OP_MUL_INT.S */ 4134/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4135/* File: armv5te/binop.S */ 4136 /* 4137 * Generic 32-bit binary operation. Provide an "instr" line that 4138 * specifies an instruction that performs "result = r0 op r1". 4139 * This could be an ARM instruction or a function call. (If the result 4140 * comes back in a register other than r0, you can override "result".) 4141 * 4142 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4143 * vCC (r1). Useful for integer division and modulus. Note that we 4144 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4145 * handles it correctly. 4146 * 4147 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4148 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4149 * mul-float, div-float, rem-float 4150 */ 4151 /* binop vAA, vBB, vCC */ 4152 FETCH(r0, 1) @ r0<- CCBB 4153 mov r9, rINST, lsr #8 @ r9<- AA 4154 mov r3, r0, lsr #8 @ r3<- CC 4155 and r2, r0, #255 @ r2<- BB 4156 GET_VREG(r1, r3) @ r1<- vCC 4157 GET_VREG(r0, r2) @ r0<- vBB 4158 .if 0 4159 cmp r1, #0 @ is second operand zero? 4160 beq common_errDivideByZero 4161 .endif 4162 4163 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4164 @ optional op; may set condition codes 4165 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4166 GET_INST_OPCODE(ip) @ extract opcode from rINST 4167 SET_VREG(r0, r9) @ vAA<- r0 4168 GOTO_OPCODE(ip) @ jump to next instruction 4169 /* 11-14 instructions */ 4170 4171 4172/* ------------------------------ */ 4173 .balign 64 4174.L_OP_DIV_INT: /* 0x93 */ 4175/* File: armv5te/OP_DIV_INT.S */ 4176/* File: armv5te/binop.S */ 4177 /* 4178 * Generic 32-bit binary operation. Provide an "instr" line that 4179 * specifies an instruction that performs "result = r0 op r1". 4180 * This could be an ARM instruction or a function call. (If the result 4181 * comes back in a register other than r0, you can override "result".) 4182 * 4183 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4184 * vCC (r1). Useful for integer division and modulus. Note that we 4185 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4186 * handles it correctly. 4187 * 4188 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4189 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4190 * mul-float, div-float, rem-float 4191 */ 4192 /* binop vAA, vBB, vCC */ 4193 FETCH(r0, 1) @ r0<- CCBB 4194 mov r9, rINST, lsr #8 @ r9<- AA 4195 mov r3, r0, lsr #8 @ r3<- CC 4196 and r2, r0, #255 @ r2<- BB 4197 GET_VREG(r1, r3) @ r1<- vCC 4198 GET_VREG(r0, r2) @ r0<- vBB 4199 .if 1 4200 cmp r1, #0 @ is second operand zero? 4201 beq common_errDivideByZero 4202 .endif 4203 4204 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4205 @ optional op; may set condition codes 4206 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4207 GET_INST_OPCODE(ip) @ extract opcode from rINST 4208 SET_VREG(r0, r9) @ vAA<- r0 4209 GOTO_OPCODE(ip) @ jump to next instruction 4210 /* 11-14 instructions */ 4211 4212 4213/* ------------------------------ */ 4214 .balign 64 4215.L_OP_REM_INT: /* 0x94 */ 4216/* File: armv5te/OP_REM_INT.S */ 4217/* idivmod returns quotient in r0 and remainder in r1 */ 4218/* File: armv5te/binop.S */ 4219 /* 4220 * Generic 32-bit binary operation. Provide an "instr" line that 4221 * specifies an instruction that performs "result = r0 op r1". 4222 * This could be an ARM instruction or a function call. (If the result 4223 * comes back in a register other than r0, you can override "result".) 4224 * 4225 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4226 * vCC (r1). Useful for integer division and modulus. Note that we 4227 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4228 * handles it correctly. 4229 * 4230 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4231 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4232 * mul-float, div-float, rem-float 4233 */ 4234 /* binop vAA, vBB, vCC */ 4235 FETCH(r0, 1) @ r0<- CCBB 4236 mov r9, rINST, lsr #8 @ r9<- AA 4237 mov r3, r0, lsr #8 @ r3<- CC 4238 and r2, r0, #255 @ r2<- BB 4239 GET_VREG(r1, r3) @ r1<- vCC 4240 GET_VREG(r0, r2) @ r0<- vBB 4241 .if 1 4242 cmp r1, #0 @ is second operand zero? 4243 beq common_errDivideByZero 4244 .endif 4245 4246 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4247 @ optional op; may set condition codes 4248 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4249 GET_INST_OPCODE(ip) @ extract opcode from rINST 4250 SET_VREG(r1, r9) @ vAA<- r1 4251 GOTO_OPCODE(ip) @ jump to next instruction 4252 /* 11-14 instructions */ 4253 4254 4255/* ------------------------------ */ 4256 .balign 64 4257.L_OP_AND_INT: /* 0x95 */ 4258/* File: armv5te/OP_AND_INT.S */ 4259/* File: armv5te/binop.S */ 4260 /* 4261 * Generic 32-bit binary operation. Provide an "instr" line that 4262 * specifies an instruction that performs "result = r0 op r1". 4263 * This could be an ARM instruction or a function call. (If the result 4264 * comes back in a register other than r0, you can override "result".) 4265 * 4266 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4267 * vCC (r1). Useful for integer division and modulus. Note that we 4268 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4269 * handles it correctly. 4270 * 4271 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4272 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4273 * mul-float, div-float, rem-float 4274 */ 4275 /* binop vAA, vBB, vCC */ 4276 FETCH(r0, 1) @ r0<- CCBB 4277 mov r9, rINST, lsr #8 @ r9<- AA 4278 mov r3, r0, lsr #8 @ r3<- CC 4279 and r2, r0, #255 @ r2<- BB 4280 GET_VREG(r1, r3) @ r1<- vCC 4281 GET_VREG(r0, r2) @ r0<- vBB 4282 .if 0 4283 cmp r1, #0 @ is second operand zero? 4284 beq common_errDivideByZero 4285 .endif 4286 4287 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4288 @ optional op; may set condition codes 4289 and r0, r0, r1 @ r0<- op, r0-r3 changed 4290 GET_INST_OPCODE(ip) @ extract opcode from rINST 4291 SET_VREG(r0, r9) @ vAA<- r0 4292 GOTO_OPCODE(ip) @ jump to next instruction 4293 /* 11-14 instructions */ 4294 4295 4296/* ------------------------------ */ 4297 .balign 64 4298.L_OP_OR_INT: /* 0x96 */ 4299/* File: armv5te/OP_OR_INT.S */ 4300/* File: armv5te/binop.S */ 4301 /* 4302 * Generic 32-bit binary operation. Provide an "instr" line that 4303 * specifies an instruction that performs "result = r0 op r1". 4304 * This could be an ARM instruction or a function call. (If the result 4305 * comes back in a register other than r0, you can override "result".) 4306 * 4307 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4308 * vCC (r1). Useful for integer division and modulus. Note that we 4309 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4310 * handles it correctly. 4311 * 4312 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4313 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4314 * mul-float, div-float, rem-float 4315 */ 4316 /* binop vAA, vBB, vCC */ 4317 FETCH(r0, 1) @ r0<- CCBB 4318 mov r9, rINST, lsr #8 @ r9<- AA 4319 mov r3, r0, lsr #8 @ r3<- CC 4320 and r2, r0, #255 @ r2<- BB 4321 GET_VREG(r1, r3) @ r1<- vCC 4322 GET_VREG(r0, r2) @ r0<- vBB 4323 .if 0 4324 cmp r1, #0 @ is second operand zero? 4325 beq common_errDivideByZero 4326 .endif 4327 4328 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4329 @ optional op; may set condition codes 4330 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4331 GET_INST_OPCODE(ip) @ extract opcode from rINST 4332 SET_VREG(r0, r9) @ vAA<- r0 4333 GOTO_OPCODE(ip) @ jump to next instruction 4334 /* 11-14 instructions */ 4335 4336 4337/* ------------------------------ */ 4338 .balign 64 4339.L_OP_XOR_INT: /* 0x97 */ 4340/* File: armv5te/OP_XOR_INT.S */ 4341/* File: armv5te/binop.S */ 4342 /* 4343 * Generic 32-bit binary operation. Provide an "instr" line that 4344 * specifies an instruction that performs "result = r0 op r1". 4345 * This could be an ARM instruction or a function call. (If the result 4346 * comes back in a register other than r0, you can override "result".) 4347 * 4348 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4349 * vCC (r1). Useful for integer division and modulus. Note that we 4350 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4351 * handles it correctly. 4352 * 4353 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4354 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4355 * mul-float, div-float, rem-float 4356 */ 4357 /* binop vAA, vBB, vCC */ 4358 FETCH(r0, 1) @ r0<- CCBB 4359 mov r9, rINST, lsr #8 @ r9<- AA 4360 mov r3, r0, lsr #8 @ r3<- CC 4361 and r2, r0, #255 @ r2<- BB 4362 GET_VREG(r1, r3) @ r1<- vCC 4363 GET_VREG(r0, r2) @ r0<- vBB 4364 .if 0 4365 cmp r1, #0 @ is second operand zero? 4366 beq common_errDivideByZero 4367 .endif 4368 4369 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4370 @ optional op; may set condition codes 4371 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4372 GET_INST_OPCODE(ip) @ extract opcode from rINST 4373 SET_VREG(r0, r9) @ vAA<- r0 4374 GOTO_OPCODE(ip) @ jump to next instruction 4375 /* 11-14 instructions */ 4376 4377 4378/* ------------------------------ */ 4379 .balign 64 4380.L_OP_SHL_INT: /* 0x98 */ 4381/* File: armv5te/OP_SHL_INT.S */ 4382/* File: armv5te/binop.S */ 4383 /* 4384 * Generic 32-bit binary operation. Provide an "instr" line that 4385 * specifies an instruction that performs "result = r0 op r1". 4386 * This could be an ARM instruction or a function call. (If the result 4387 * comes back in a register other than r0, you can override "result".) 4388 * 4389 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4390 * vCC (r1). Useful for integer division and modulus. Note that we 4391 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4392 * handles it correctly. 4393 * 4394 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4395 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4396 * mul-float, div-float, rem-float 4397 */ 4398 /* binop vAA, vBB, vCC */ 4399 FETCH(r0, 1) @ r0<- CCBB 4400 mov r9, rINST, lsr #8 @ r9<- AA 4401 mov r3, r0, lsr #8 @ r3<- CC 4402 and r2, r0, #255 @ r2<- BB 4403 GET_VREG(r1, r3) @ r1<- vCC 4404 GET_VREG(r0, r2) @ r0<- vBB 4405 .if 0 4406 cmp r1, #0 @ is second operand zero? 4407 beq common_errDivideByZero 4408 .endif 4409 4410 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4411 and r1, r1, #31 @ optional op; may set condition codes 4412 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4413 GET_INST_OPCODE(ip) @ extract opcode from rINST 4414 SET_VREG(r0, r9) @ vAA<- r0 4415 GOTO_OPCODE(ip) @ jump to next instruction 4416 /* 11-14 instructions */ 4417 4418 4419/* ------------------------------ */ 4420 .balign 64 4421.L_OP_SHR_INT: /* 0x99 */ 4422/* File: armv5te/OP_SHR_INT.S */ 4423/* File: armv5te/binop.S */ 4424 /* 4425 * Generic 32-bit binary operation. Provide an "instr" line that 4426 * specifies an instruction that performs "result = r0 op r1". 4427 * This could be an ARM instruction or a function call. (If the result 4428 * comes back in a register other than r0, you can override "result".) 4429 * 4430 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4431 * vCC (r1). Useful for integer division and modulus. Note that we 4432 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4433 * handles it correctly. 4434 * 4435 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4436 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4437 * mul-float, div-float, rem-float 4438 */ 4439 /* binop vAA, vBB, vCC */ 4440 FETCH(r0, 1) @ r0<- CCBB 4441 mov r9, rINST, lsr #8 @ r9<- AA 4442 mov r3, r0, lsr #8 @ r3<- CC 4443 and r2, r0, #255 @ r2<- BB 4444 GET_VREG(r1, r3) @ r1<- vCC 4445 GET_VREG(r0, r2) @ r0<- vBB 4446 .if 0 4447 cmp r1, #0 @ is second operand zero? 4448 beq common_errDivideByZero 4449 .endif 4450 4451 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4452 and r1, r1, #31 @ optional op; may set condition codes 4453 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4454 GET_INST_OPCODE(ip) @ extract opcode from rINST 4455 SET_VREG(r0, r9) @ vAA<- r0 4456 GOTO_OPCODE(ip) @ jump to next instruction 4457 /* 11-14 instructions */ 4458 4459 4460/* ------------------------------ */ 4461 .balign 64 4462.L_OP_USHR_INT: /* 0x9a */ 4463/* File: armv5te/OP_USHR_INT.S */ 4464/* File: armv5te/binop.S */ 4465 /* 4466 * Generic 32-bit binary operation. Provide an "instr" line that 4467 * specifies an instruction that performs "result = r0 op r1". 4468 * This could be an ARM instruction or a function call. (If the result 4469 * comes back in a register other than r0, you can override "result".) 4470 * 4471 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4472 * vCC (r1). Useful for integer division and modulus. Note that we 4473 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4474 * handles it correctly. 4475 * 4476 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4477 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4478 * mul-float, div-float, rem-float 4479 */ 4480 /* binop vAA, vBB, vCC */ 4481 FETCH(r0, 1) @ r0<- CCBB 4482 mov r9, rINST, lsr #8 @ r9<- AA 4483 mov r3, r0, lsr #8 @ r3<- CC 4484 and r2, r0, #255 @ r2<- BB 4485 GET_VREG(r1, r3) @ r1<- vCC 4486 GET_VREG(r0, r2) @ r0<- vBB 4487 .if 0 4488 cmp r1, #0 @ is second operand zero? 4489 beq common_errDivideByZero 4490 .endif 4491 4492 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4493 and r1, r1, #31 @ optional op; may set condition codes 4494 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4495 GET_INST_OPCODE(ip) @ extract opcode from rINST 4496 SET_VREG(r0, r9) @ vAA<- r0 4497 GOTO_OPCODE(ip) @ jump to next instruction 4498 /* 11-14 instructions */ 4499 4500 4501/* ------------------------------ */ 4502 .balign 64 4503.L_OP_ADD_LONG: /* 0x9b */ 4504/* File: armv5te/OP_ADD_LONG.S */ 4505/* File: armv5te/binopWide.S */ 4506 /* 4507 * Generic 64-bit binary operation. Provide an "instr" line that 4508 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4509 * This could be an ARM instruction or a function call. (If the result 4510 * comes back in a register other than r0, you can override "result".) 4511 * 4512 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4513 * vCC (r1). Useful for integer division and modulus. 4514 * 4515 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4516 * xor-long, add-double, sub-double, mul-double, div-double, 4517 * rem-double 4518 * 4519 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4520 */ 4521 /* binop vAA, vBB, vCC */ 4522 FETCH(r0, 1) @ r0<- CCBB 4523 mov r9, rINST, lsr #8 @ r9<- AA 4524 and r2, r0, #255 @ r2<- BB 4525 mov r3, r0, lsr #8 @ r3<- CC 4526 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4527 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4528 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4529 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4530 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4531 .if 0 4532 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4533 beq common_errDivideByZero 4534 .endif 4535 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4536 4537 adds r0, r0, r2 @ optional op; may set condition codes 4538 adc r1, r1, r3 @ result<- op, r0-r3 changed 4539 GET_INST_OPCODE(ip) @ extract opcode from rINST 4540 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4541 GOTO_OPCODE(ip) @ jump to next instruction 4542 /* 14-17 instructions */ 4543 4544 4545/* ------------------------------ */ 4546 .balign 64 4547.L_OP_SUB_LONG: /* 0x9c */ 4548/* File: armv5te/OP_SUB_LONG.S */ 4549/* File: armv5te/binopWide.S */ 4550 /* 4551 * Generic 64-bit binary operation. Provide an "instr" line that 4552 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4553 * This could be an ARM instruction or a function call. (If the result 4554 * comes back in a register other than r0, you can override "result".) 4555 * 4556 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4557 * vCC (r1). Useful for integer division and modulus. 4558 * 4559 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4560 * xor-long, add-double, sub-double, mul-double, div-double, 4561 * rem-double 4562 * 4563 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4564 */ 4565 /* binop vAA, vBB, vCC */ 4566 FETCH(r0, 1) @ r0<- CCBB 4567 mov r9, rINST, lsr #8 @ r9<- AA 4568 and r2, r0, #255 @ r2<- BB 4569 mov r3, r0, lsr #8 @ r3<- CC 4570 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4571 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4572 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4573 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4574 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4575 .if 0 4576 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4577 beq common_errDivideByZero 4578 .endif 4579 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4580 4581 subs r0, r0, r2 @ optional op; may set condition codes 4582 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4583 GET_INST_OPCODE(ip) @ extract opcode from rINST 4584 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4585 GOTO_OPCODE(ip) @ jump to next instruction 4586 /* 14-17 instructions */ 4587 4588 4589/* ------------------------------ */ 4590 .balign 64 4591.L_OP_MUL_LONG: /* 0x9d */ 4592/* File: armv5te/OP_MUL_LONG.S */ 4593 /* 4594 * Signed 64-bit integer multiply. 4595 * 4596 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4597 * WX 4598 * x YZ 4599 * -------- 4600 * ZW ZX 4601 * YW YX 4602 * 4603 * The low word of the result holds ZX, the high word holds 4604 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4605 * it doesn't fit in the low 64 bits. 4606 * 4607 * Unlike most ARM math operations, multiply instructions have 4608 * restrictions on using the same register more than once (Rd and Rm 4609 * cannot be the same). 4610 */ 4611 /* mul-long vAA, vBB, vCC */ 4612 FETCH(r0, 1) @ r0<- CCBB 4613 and r2, r0, #255 @ r2<- BB 4614 mov r3, r0, lsr #8 @ r3<- CC 4615 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4616 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4617 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4618 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4619 mul ip, r2, r1 @ ip<- ZxW 4620 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4621 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4622 mov r0, rINST, lsr #8 @ r0<- AA 4623 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4624 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4625 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4626 b .LOP_MUL_LONG_finish 4627 4628/* ------------------------------ */ 4629 .balign 64 4630.L_OP_DIV_LONG: /* 0x9e */ 4631/* File: armv5te/OP_DIV_LONG.S */ 4632/* File: armv5te/binopWide.S */ 4633 /* 4634 * Generic 64-bit binary operation. Provide an "instr" line that 4635 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4636 * This could be an ARM instruction or a function call. (If the result 4637 * comes back in a register other than r0, you can override "result".) 4638 * 4639 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4640 * vCC (r1). Useful for integer division and modulus. 4641 * 4642 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4643 * xor-long, add-double, sub-double, mul-double, div-double, 4644 * rem-double 4645 * 4646 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4647 */ 4648 /* binop vAA, vBB, vCC */ 4649 FETCH(r0, 1) @ r0<- CCBB 4650 mov r9, rINST, lsr #8 @ r9<- AA 4651 and r2, r0, #255 @ r2<- BB 4652 mov r3, r0, lsr #8 @ r3<- CC 4653 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4654 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4655 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4656 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4657 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4658 .if 1 4659 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4660 beq common_errDivideByZero 4661 .endif 4662 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4663 4664 @ optional op; may set condition codes 4665 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4666 GET_INST_OPCODE(ip) @ extract opcode from rINST 4667 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4668 GOTO_OPCODE(ip) @ jump to next instruction 4669 /* 14-17 instructions */ 4670 4671 4672/* ------------------------------ */ 4673 .balign 64 4674.L_OP_REM_LONG: /* 0x9f */ 4675/* File: armv5te/OP_REM_LONG.S */ 4676/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4677/* File: armv5te/binopWide.S */ 4678 /* 4679 * Generic 64-bit binary operation. Provide an "instr" line that 4680 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4681 * This could be an ARM instruction or a function call. (If the result 4682 * comes back in a register other than r0, you can override "result".) 4683 * 4684 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4685 * vCC (r1). Useful for integer division and modulus. 4686 * 4687 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4688 * xor-long, add-double, sub-double, mul-double, div-double, 4689 * rem-double 4690 * 4691 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4692 */ 4693 /* binop vAA, vBB, vCC */ 4694 FETCH(r0, 1) @ r0<- CCBB 4695 mov r9, rINST, lsr #8 @ r9<- AA 4696 and r2, r0, #255 @ r2<- BB 4697 mov r3, r0, lsr #8 @ r3<- CC 4698 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4699 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4700 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4701 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4702 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4703 .if 1 4704 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4705 beq common_errDivideByZero 4706 .endif 4707 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4708 4709 @ optional op; may set condition codes 4710 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4711 GET_INST_OPCODE(ip) @ extract opcode from rINST 4712 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4713 GOTO_OPCODE(ip) @ jump to next instruction 4714 /* 14-17 instructions */ 4715 4716 4717/* ------------------------------ */ 4718 .balign 64 4719.L_OP_AND_LONG: /* 0xa0 */ 4720/* File: armv5te/OP_AND_LONG.S */ 4721/* File: armv5te/binopWide.S */ 4722 /* 4723 * Generic 64-bit binary operation. Provide an "instr" line that 4724 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4725 * This could be an ARM instruction or a function call. (If the result 4726 * comes back in a register other than r0, you can override "result".) 4727 * 4728 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4729 * vCC (r1). Useful for integer division and modulus. 4730 * 4731 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4732 * xor-long, add-double, sub-double, mul-double, div-double, 4733 * rem-double 4734 * 4735 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4736 */ 4737 /* binop vAA, vBB, vCC */ 4738 FETCH(r0, 1) @ r0<- CCBB 4739 mov r9, rINST, lsr #8 @ r9<- AA 4740 and r2, r0, #255 @ r2<- BB 4741 mov r3, r0, lsr #8 @ r3<- CC 4742 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4743 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4744 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4745 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4746 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4747 .if 0 4748 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4749 beq common_errDivideByZero 4750 .endif 4751 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4752 4753 and r0, r0, r2 @ optional op; may set condition codes 4754 and r1, r1, r3 @ result<- op, r0-r3 changed 4755 GET_INST_OPCODE(ip) @ extract opcode from rINST 4756 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4757 GOTO_OPCODE(ip) @ jump to next instruction 4758 /* 14-17 instructions */ 4759 4760 4761/* ------------------------------ */ 4762 .balign 64 4763.L_OP_OR_LONG: /* 0xa1 */ 4764/* File: armv5te/OP_OR_LONG.S */ 4765/* File: armv5te/binopWide.S */ 4766 /* 4767 * Generic 64-bit binary operation. Provide an "instr" line that 4768 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4769 * This could be an ARM instruction or a function call. (If the result 4770 * comes back in a register other than r0, you can override "result".) 4771 * 4772 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4773 * vCC (r1). Useful for integer division and modulus. 4774 * 4775 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4776 * xor-long, add-double, sub-double, mul-double, div-double, 4777 * rem-double 4778 * 4779 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4780 */ 4781 /* binop vAA, vBB, vCC */ 4782 FETCH(r0, 1) @ r0<- CCBB 4783 mov r9, rINST, lsr #8 @ r9<- AA 4784 and r2, r0, #255 @ r2<- BB 4785 mov r3, r0, lsr #8 @ r3<- CC 4786 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4787 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4788 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4789 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4790 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4791 .if 0 4792 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4793 beq common_errDivideByZero 4794 .endif 4795 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4796 4797 orr r0, r0, r2 @ optional op; may set condition codes 4798 orr r1, r1, r3 @ result<- op, r0-r3 changed 4799 GET_INST_OPCODE(ip) @ extract opcode from rINST 4800 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4801 GOTO_OPCODE(ip) @ jump to next instruction 4802 /* 14-17 instructions */ 4803 4804 4805/* ------------------------------ */ 4806 .balign 64 4807.L_OP_XOR_LONG: /* 0xa2 */ 4808/* File: armv5te/OP_XOR_LONG.S */ 4809/* File: armv5te/binopWide.S */ 4810 /* 4811 * Generic 64-bit binary operation. Provide an "instr" line that 4812 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4813 * This could be an ARM instruction or a function call. (If the result 4814 * comes back in a register other than r0, you can override "result".) 4815 * 4816 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4817 * vCC (r1). Useful for integer division and modulus. 4818 * 4819 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4820 * xor-long, add-double, sub-double, mul-double, div-double, 4821 * rem-double 4822 * 4823 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4824 */ 4825 /* binop vAA, vBB, vCC */ 4826 FETCH(r0, 1) @ r0<- CCBB 4827 mov r9, rINST, lsr #8 @ r9<- AA 4828 and r2, r0, #255 @ r2<- BB 4829 mov r3, r0, lsr #8 @ r3<- CC 4830 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4831 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4832 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4833 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4834 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4835 .if 0 4836 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4837 beq common_errDivideByZero 4838 .endif 4839 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4840 4841 eor r0, r0, r2 @ optional op; may set condition codes 4842 eor r1, r1, r3 @ result<- op, r0-r3 changed 4843 GET_INST_OPCODE(ip) @ extract opcode from rINST 4844 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4845 GOTO_OPCODE(ip) @ jump to next instruction 4846 /* 14-17 instructions */ 4847 4848 4849/* ------------------------------ */ 4850 .balign 64 4851.L_OP_SHL_LONG: /* 0xa3 */ 4852/* File: armv5te/OP_SHL_LONG.S */ 4853 /* 4854 * Long integer shift. This is different from the generic 32/64-bit 4855 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4856 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4857 * 6 bits of the shift distance. 4858 */ 4859 /* shl-long vAA, vBB, vCC */ 4860 FETCH(r0, 1) @ r0<- CCBB 4861 mov r9, rINST, lsr #8 @ r9<- AA 4862 and r3, r0, #255 @ r3<- BB 4863 mov r0, r0, lsr #8 @ r0<- CC 4864 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4865 GET_VREG(r2, r0) @ r2<- vCC 4866 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4867 and r2, r2, #63 @ r2<- r2 & 0x3f 4868 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4869 4870 mov r1, r1, asl r2 @ r1<- r1 << r2 4871 rsb r3, r2, #32 @ r3<- 32 - r2 4872 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 4873 subs ip, r2, #32 @ ip<- r2 - 32 4874 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 4875 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4876 b .LOP_SHL_LONG_finish 4877 4878/* ------------------------------ */ 4879 .balign 64 4880.L_OP_SHR_LONG: /* 0xa4 */ 4881/* File: armv5te/OP_SHR_LONG.S */ 4882 /* 4883 * Long integer shift. This is different from the generic 32/64-bit 4884 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4885 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4886 * 6 bits of the shift distance. 4887 */ 4888 /* shr-long vAA, vBB, vCC */ 4889 FETCH(r0, 1) @ r0<- CCBB 4890 mov r9, rINST, lsr #8 @ r9<- AA 4891 and r3, r0, #255 @ r3<- BB 4892 mov r0, r0, lsr #8 @ r0<- CC 4893 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4894 GET_VREG(r2, r0) @ r2<- vCC 4895 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4896 and r2, r2, #63 @ r0<- r0 & 0x3f 4897 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4898 4899 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4900 rsb r3, r2, #32 @ r3<- 32 - r2 4901 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4902 subs ip, r2, #32 @ ip<- r2 - 32 4903 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 4904 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4905 b .LOP_SHR_LONG_finish 4906 4907/* ------------------------------ */ 4908 .balign 64 4909.L_OP_USHR_LONG: /* 0xa5 */ 4910/* File: armv5te/OP_USHR_LONG.S */ 4911 /* 4912 * Long integer shift. This is different from the generic 32/64-bit 4913 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4914 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4915 * 6 bits of the shift distance. 4916 */ 4917 /* ushr-long vAA, vBB, vCC */ 4918 FETCH(r0, 1) @ r0<- CCBB 4919 mov r9, rINST, lsr #8 @ r9<- AA 4920 and r3, r0, #255 @ r3<- BB 4921 mov r0, r0, lsr #8 @ r0<- CC 4922 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4923 GET_VREG(r2, r0) @ r2<- vCC 4924 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4925 and r2, r2, #63 @ r0<- r0 & 0x3f 4926 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4927 4928 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4929 rsb r3, r2, #32 @ r3<- 32 - r2 4930 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4931 subs ip, r2, #32 @ ip<- r2 - 32 4932 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 4933 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4934 b .LOP_USHR_LONG_finish 4935 4936/* ------------------------------ */ 4937 .balign 64 4938.L_OP_ADD_FLOAT: /* 0xa6 */ 4939/* File: arm-vfp/OP_ADD_FLOAT.S */ 4940/* File: arm-vfp/fbinop.S */ 4941 /* 4942 * Generic 32-bit floating-point operation. Provide an "instr" line that 4943 * specifies an instruction that performs "s2 = s0 op s1". Because we 4944 * use the "softfp" ABI, this must be an instruction, not a function call. 4945 * 4946 * For: add-float, sub-float, mul-float, div-float 4947 */ 4948 /* floatop vAA, vBB, vCC */ 4949 FETCH(r0, 1) @ r0<- CCBB 4950 mov r9, rINST, lsr #8 @ r9<- AA 4951 mov r3, r0, lsr #8 @ r3<- CC 4952 and r2, r0, #255 @ r2<- BB 4953 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4954 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4955 flds s1, [r3] @ s1<- vCC 4956 flds s0, [r2] @ s0<- vBB 4957 4958 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4959 fadds s2, s0, s1 @ s2<- op 4960 GET_INST_OPCODE(ip) @ extract opcode from rINST 4961 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4962 fsts s2, [r9] @ vAA<- s2 4963 GOTO_OPCODE(ip) @ jump to next instruction 4964 4965 4966/* ------------------------------ */ 4967 .balign 64 4968.L_OP_SUB_FLOAT: /* 0xa7 */ 4969/* File: arm-vfp/OP_SUB_FLOAT.S */ 4970/* File: arm-vfp/fbinop.S */ 4971 /* 4972 * Generic 32-bit floating-point operation. Provide an "instr" line that 4973 * specifies an instruction that performs "s2 = s0 op s1". Because we 4974 * use the "softfp" ABI, this must be an instruction, not a function call. 4975 * 4976 * For: add-float, sub-float, mul-float, div-float 4977 */ 4978 /* floatop vAA, vBB, vCC */ 4979 FETCH(r0, 1) @ r0<- CCBB 4980 mov r9, rINST, lsr #8 @ r9<- AA 4981 mov r3, r0, lsr #8 @ r3<- CC 4982 and r2, r0, #255 @ r2<- BB 4983 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 4984 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 4985 flds s1, [r3] @ s1<- vCC 4986 flds s0, [r2] @ s0<- vBB 4987 4988 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4989 fsubs s2, s0, s1 @ s2<- op 4990 GET_INST_OPCODE(ip) @ extract opcode from rINST 4991 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 4992 fsts s2, [r9] @ vAA<- s2 4993 GOTO_OPCODE(ip) @ jump to next instruction 4994 4995 4996/* ------------------------------ */ 4997 .balign 64 4998.L_OP_MUL_FLOAT: /* 0xa8 */ 4999/* File: arm-vfp/OP_MUL_FLOAT.S */ 5000/* File: arm-vfp/fbinop.S */ 5001 /* 5002 * Generic 32-bit floating-point operation. Provide an "instr" line that 5003 * specifies an instruction that performs "s2 = s0 op s1". Because we 5004 * use the "softfp" ABI, this must be an instruction, not a function call. 5005 * 5006 * For: add-float, sub-float, mul-float, div-float 5007 */ 5008 /* floatop vAA, vBB, vCC */ 5009 FETCH(r0, 1) @ r0<- CCBB 5010 mov r9, rINST, lsr #8 @ r9<- AA 5011 mov r3, r0, lsr #8 @ r3<- CC 5012 and r2, r0, #255 @ r2<- BB 5013 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5014 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5015 flds s1, [r3] @ s1<- vCC 5016 flds s0, [r2] @ s0<- vBB 5017 5018 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5019 fmuls s2, s0, s1 @ s2<- op 5020 GET_INST_OPCODE(ip) @ extract opcode from rINST 5021 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5022 fsts s2, [r9] @ vAA<- s2 5023 GOTO_OPCODE(ip) @ jump to next instruction 5024 5025 5026/* ------------------------------ */ 5027 .balign 64 5028.L_OP_DIV_FLOAT: /* 0xa9 */ 5029/* File: arm-vfp/OP_DIV_FLOAT.S */ 5030/* File: arm-vfp/fbinop.S */ 5031 /* 5032 * Generic 32-bit floating-point operation. Provide an "instr" line that 5033 * specifies an instruction that performs "s2 = s0 op s1". Because we 5034 * use the "softfp" ABI, this must be an instruction, not a function call. 5035 * 5036 * For: add-float, sub-float, mul-float, div-float 5037 */ 5038 /* floatop vAA, vBB, vCC */ 5039 FETCH(r0, 1) @ r0<- CCBB 5040 mov r9, rINST, lsr #8 @ r9<- AA 5041 mov r3, r0, lsr #8 @ r3<- CC 5042 and r2, r0, #255 @ r2<- BB 5043 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5044 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5045 flds s1, [r3] @ s1<- vCC 5046 flds s0, [r2] @ s0<- vBB 5047 5048 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5049 fdivs s2, s0, s1 @ s2<- op 5050 GET_INST_OPCODE(ip) @ extract opcode from rINST 5051 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5052 fsts s2, [r9] @ vAA<- s2 5053 GOTO_OPCODE(ip) @ jump to next instruction 5054 5055 5056/* ------------------------------ */ 5057 .balign 64 5058.L_OP_REM_FLOAT: /* 0xaa */ 5059/* File: armv5te/OP_REM_FLOAT.S */ 5060/* EABI doesn't define a float remainder function, but libm does */ 5061/* File: armv5te/binop.S */ 5062 /* 5063 * Generic 32-bit binary operation. Provide an "instr" line that 5064 * specifies an instruction that performs "result = r0 op r1". 5065 * This could be an ARM instruction or a function call. (If the result 5066 * comes back in a register other than r0, you can override "result".) 5067 * 5068 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5069 * vCC (r1). Useful for integer division and modulus. Note that we 5070 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5071 * handles it correctly. 5072 * 5073 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5074 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5075 * mul-float, div-float, rem-float 5076 */ 5077 /* binop vAA, vBB, vCC */ 5078 FETCH(r0, 1) @ r0<- CCBB 5079 mov r9, rINST, lsr #8 @ r9<- AA 5080 mov r3, r0, lsr #8 @ r3<- CC 5081 and r2, r0, #255 @ r2<- BB 5082 GET_VREG(r1, r3) @ r1<- vCC 5083 GET_VREG(r0, r2) @ r0<- vBB 5084 .if 0 5085 cmp r1, #0 @ is second operand zero? 5086 beq common_errDivideByZero 5087 .endif 5088 5089 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5090 @ optional op; may set condition codes 5091 bl fmodf @ r0<- op, r0-r3 changed 5092 GET_INST_OPCODE(ip) @ extract opcode from rINST 5093 SET_VREG(r0, r9) @ vAA<- r0 5094 GOTO_OPCODE(ip) @ jump to next instruction 5095 /* 11-14 instructions */ 5096 5097 5098/* ------------------------------ */ 5099 .balign 64 5100.L_OP_ADD_DOUBLE: /* 0xab */ 5101/* File: arm-vfp/OP_ADD_DOUBLE.S */ 5102/* File: arm-vfp/fbinopWide.S */ 5103 /* 5104 * Generic 64-bit double-precision floating point binary operation. 5105 * Provide an "instr" line that specifies an instruction that performs 5106 * "d2 = d0 op d1". 5107 * 5108 * for: add-double, sub-double, mul-double, div-double 5109 */ 5110 /* doubleop vAA, vBB, vCC */ 5111 FETCH(r0, 1) @ r0<- CCBB 5112 mov r9, rINST, lsr #8 @ r9<- AA 5113 mov r3, r0, lsr #8 @ r3<- CC 5114 and r2, r0, #255 @ r2<- BB 5115 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5116 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5117 fldd d1, [r3] @ d1<- vCC 5118 fldd d0, [r2] @ d0<- vBB 5119 5120 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5121 faddd d2, d0, d1 @ s2<- op 5122 GET_INST_OPCODE(ip) @ extract opcode from rINST 5123 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5124 fstd d2, [r9] @ vAA<- d2 5125 GOTO_OPCODE(ip) @ jump to next instruction 5126 5127 5128/* ------------------------------ */ 5129 .balign 64 5130.L_OP_SUB_DOUBLE: /* 0xac */ 5131/* File: arm-vfp/OP_SUB_DOUBLE.S */ 5132/* File: arm-vfp/fbinopWide.S */ 5133 /* 5134 * Generic 64-bit double-precision floating point binary operation. 5135 * Provide an "instr" line that specifies an instruction that performs 5136 * "d2 = d0 op d1". 5137 * 5138 * for: add-double, sub-double, mul-double, div-double 5139 */ 5140 /* doubleop vAA, vBB, vCC */ 5141 FETCH(r0, 1) @ r0<- CCBB 5142 mov r9, rINST, lsr #8 @ r9<- AA 5143 mov r3, r0, lsr #8 @ r3<- CC 5144 and r2, r0, #255 @ r2<- BB 5145 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5146 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5147 fldd d1, [r3] @ d1<- vCC 5148 fldd d0, [r2] @ d0<- vBB 5149 5150 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5151 fsubd d2, d0, d1 @ s2<- op 5152 GET_INST_OPCODE(ip) @ extract opcode from rINST 5153 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5154 fstd d2, [r9] @ vAA<- d2 5155 GOTO_OPCODE(ip) @ jump to next instruction 5156 5157 5158/* ------------------------------ */ 5159 .balign 64 5160.L_OP_MUL_DOUBLE: /* 0xad */ 5161/* File: arm-vfp/OP_MUL_DOUBLE.S */ 5162/* File: arm-vfp/fbinopWide.S */ 5163 /* 5164 * Generic 64-bit double-precision floating point binary operation. 5165 * Provide an "instr" line that specifies an instruction that performs 5166 * "d2 = d0 op d1". 5167 * 5168 * for: add-double, sub-double, mul-double, div-double 5169 */ 5170 /* doubleop vAA, vBB, vCC */ 5171 FETCH(r0, 1) @ r0<- CCBB 5172 mov r9, rINST, lsr #8 @ r9<- AA 5173 mov r3, r0, lsr #8 @ r3<- CC 5174 and r2, r0, #255 @ r2<- BB 5175 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5176 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5177 fldd d1, [r3] @ d1<- vCC 5178 fldd d0, [r2] @ d0<- vBB 5179 5180 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5181 fmuld d2, d0, d1 @ s2<- op 5182 GET_INST_OPCODE(ip) @ extract opcode from rINST 5183 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5184 fstd d2, [r9] @ vAA<- d2 5185 GOTO_OPCODE(ip) @ jump to next instruction 5186 5187 5188/* ------------------------------ */ 5189 .balign 64 5190.L_OP_DIV_DOUBLE: /* 0xae */ 5191/* File: arm-vfp/OP_DIV_DOUBLE.S */ 5192/* File: arm-vfp/fbinopWide.S */ 5193 /* 5194 * Generic 64-bit double-precision floating point binary operation. 5195 * Provide an "instr" line that specifies an instruction that performs 5196 * "d2 = d0 op d1". 5197 * 5198 * for: add-double, sub-double, mul-double, div-double 5199 */ 5200 /* doubleop vAA, vBB, vCC */ 5201 FETCH(r0, 1) @ r0<- CCBB 5202 mov r9, rINST, lsr #8 @ r9<- AA 5203 mov r3, r0, lsr #8 @ r3<- CC 5204 and r2, r0, #255 @ r2<- BB 5205 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5206 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5207 fldd d1, [r3] @ d1<- vCC 5208 fldd d0, [r2] @ d0<- vBB 5209 5210 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5211 fdivd d2, d0, d1 @ s2<- op 5212 GET_INST_OPCODE(ip) @ extract opcode from rINST 5213 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5214 fstd d2, [r9] @ vAA<- d2 5215 GOTO_OPCODE(ip) @ jump to next instruction 5216 5217 5218/* ------------------------------ */ 5219 .balign 64 5220.L_OP_REM_DOUBLE: /* 0xaf */ 5221/* File: armv5te/OP_REM_DOUBLE.S */ 5222/* EABI doesn't define a double remainder function, but libm does */ 5223/* File: armv5te/binopWide.S */ 5224 /* 5225 * Generic 64-bit binary operation. Provide an "instr" line that 5226 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5227 * This could be an ARM instruction or a function call. (If the result 5228 * comes back in a register other than r0, you can override "result".) 5229 * 5230 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5231 * vCC (r1). Useful for integer division and modulus. 5232 * 5233 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5234 * xor-long, add-double, sub-double, mul-double, div-double, 5235 * rem-double 5236 * 5237 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5238 */ 5239 /* binop vAA, vBB, vCC */ 5240 FETCH(r0, 1) @ r0<- CCBB 5241 mov r9, rINST, lsr #8 @ r9<- AA 5242 and r2, r0, #255 @ r2<- BB 5243 mov r3, r0, lsr #8 @ r3<- CC 5244 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5245 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5246 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5247 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5248 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5249 .if 0 5250 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5251 beq common_errDivideByZero 5252 .endif 5253 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5254 5255 @ optional op; may set condition codes 5256 bl fmod @ result<- op, r0-r3 changed 5257 GET_INST_OPCODE(ip) @ extract opcode from rINST 5258 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5259 GOTO_OPCODE(ip) @ jump to next instruction 5260 /* 14-17 instructions */ 5261 5262 5263/* ------------------------------ */ 5264 .balign 64 5265.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5266/* File: armv5te/OP_ADD_INT_2ADDR.S */ 5267/* File: armv5te/binop2addr.S */ 5268 /* 5269 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5270 * that specifies an instruction that performs "result = r0 op r1". 5271 * This could be an ARM instruction or a function call. (If the result 5272 * comes back in a register other than r0, you can override "result".) 5273 * 5274 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5275 * vCC (r1). Useful for integer division and modulus. 5276 * 5277 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5278 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5279 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5280 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5281 */ 5282 /* binop/2addr vA, vB */ 5283 mov r9, rINST, lsr #8 @ r9<- A+ 5284 mov r3, rINST, lsr #12 @ r3<- B 5285 and r9, r9, #15 5286 GET_VREG(r1, r3) @ r1<- vB 5287 GET_VREG(r0, r9) @ r0<- vA 5288 .if 0 5289 cmp r1, #0 @ is second operand zero? 5290 beq common_errDivideByZero 5291 .endif 5292 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5293 5294 @ optional op; may set condition codes 5295 add r0, r0, r1 @ r0<- op, r0-r3 changed 5296 GET_INST_OPCODE(ip) @ extract opcode from rINST 5297 SET_VREG(r0, r9) @ vAA<- r0 5298 GOTO_OPCODE(ip) @ jump to next instruction 5299 /* 10-13 instructions */ 5300 5301 5302/* ------------------------------ */ 5303 .balign 64 5304.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5305/* File: armv5te/OP_SUB_INT_2ADDR.S */ 5306/* File: armv5te/binop2addr.S */ 5307 /* 5308 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5309 * that specifies an instruction that performs "result = r0 op r1". 5310 * This could be an ARM instruction or a function call. (If the result 5311 * comes back in a register other than r0, you can override "result".) 5312 * 5313 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5314 * vCC (r1). Useful for integer division and modulus. 5315 * 5316 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5317 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5318 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5319 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5320 */ 5321 /* binop/2addr vA, vB */ 5322 mov r9, rINST, lsr #8 @ r9<- A+ 5323 mov r3, rINST, lsr #12 @ r3<- B 5324 and r9, r9, #15 5325 GET_VREG(r1, r3) @ r1<- vB 5326 GET_VREG(r0, r9) @ r0<- vA 5327 .if 0 5328 cmp r1, #0 @ is second operand zero? 5329 beq common_errDivideByZero 5330 .endif 5331 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5332 5333 @ optional op; may set condition codes 5334 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5335 GET_INST_OPCODE(ip) @ extract opcode from rINST 5336 SET_VREG(r0, r9) @ vAA<- r0 5337 GOTO_OPCODE(ip) @ jump to next instruction 5338 /* 10-13 instructions */ 5339 5340 5341/* ------------------------------ */ 5342 .balign 64 5343.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5344/* File: armv5te/OP_MUL_INT_2ADDR.S */ 5345/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5346/* File: armv5te/binop2addr.S */ 5347 /* 5348 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5349 * that specifies an instruction that performs "result = r0 op r1". 5350 * This could be an ARM instruction or a function call. (If the result 5351 * comes back in a register other than r0, you can override "result".) 5352 * 5353 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5354 * vCC (r1). Useful for integer division and modulus. 5355 * 5356 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5357 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5358 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5359 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5360 */ 5361 /* binop/2addr vA, vB */ 5362 mov r9, rINST, lsr #8 @ r9<- A+ 5363 mov r3, rINST, lsr #12 @ r3<- B 5364 and r9, r9, #15 5365 GET_VREG(r1, r3) @ r1<- vB 5366 GET_VREG(r0, r9) @ r0<- vA 5367 .if 0 5368 cmp r1, #0 @ is second operand zero? 5369 beq common_errDivideByZero 5370 .endif 5371 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5372 5373 @ optional op; may set condition codes 5374 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5375 GET_INST_OPCODE(ip) @ extract opcode from rINST 5376 SET_VREG(r0, r9) @ vAA<- r0 5377 GOTO_OPCODE(ip) @ jump to next instruction 5378 /* 10-13 instructions */ 5379 5380 5381/* ------------------------------ */ 5382 .balign 64 5383.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5384/* File: armv5te/OP_DIV_INT_2ADDR.S */ 5385/* File: armv5te/binop2addr.S */ 5386 /* 5387 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5388 * that specifies an instruction that performs "result = r0 op r1". 5389 * This could be an ARM instruction or a function call. (If the result 5390 * comes back in a register other than r0, you can override "result".) 5391 * 5392 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5393 * vCC (r1). Useful for integer division and modulus. 5394 * 5395 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5396 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5397 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5398 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5399 */ 5400 /* binop/2addr vA, vB */ 5401 mov r9, rINST, lsr #8 @ r9<- A+ 5402 mov r3, rINST, lsr #12 @ r3<- B 5403 and r9, r9, #15 5404 GET_VREG(r1, r3) @ r1<- vB 5405 GET_VREG(r0, r9) @ r0<- vA 5406 .if 1 5407 cmp r1, #0 @ is second operand zero? 5408 beq common_errDivideByZero 5409 .endif 5410 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5411 5412 @ optional op; may set condition codes 5413 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5414 GET_INST_OPCODE(ip) @ extract opcode from rINST 5415 SET_VREG(r0, r9) @ vAA<- r0 5416 GOTO_OPCODE(ip) @ jump to next instruction 5417 /* 10-13 instructions */ 5418 5419 5420/* ------------------------------ */ 5421 .balign 64 5422.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5423/* File: armv5te/OP_REM_INT_2ADDR.S */ 5424/* idivmod returns quotient in r0 and remainder in r1 */ 5425/* File: armv5te/binop2addr.S */ 5426 /* 5427 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5428 * that specifies an instruction that performs "result = r0 op r1". 5429 * This could be an ARM instruction or a function call. (If the result 5430 * comes back in a register other than r0, you can override "result".) 5431 * 5432 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5433 * vCC (r1). Useful for integer division and modulus. 5434 * 5435 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5436 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5437 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5438 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5439 */ 5440 /* binop/2addr vA, vB */ 5441 mov r9, rINST, lsr #8 @ r9<- A+ 5442 mov r3, rINST, lsr #12 @ r3<- B 5443 and r9, r9, #15 5444 GET_VREG(r1, r3) @ r1<- vB 5445 GET_VREG(r0, r9) @ r0<- vA 5446 .if 1 5447 cmp r1, #0 @ is second operand zero? 5448 beq common_errDivideByZero 5449 .endif 5450 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5451 5452 @ optional op; may set condition codes 5453 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5454 GET_INST_OPCODE(ip) @ extract opcode from rINST 5455 SET_VREG(r1, r9) @ vAA<- r1 5456 GOTO_OPCODE(ip) @ jump to next instruction 5457 /* 10-13 instructions */ 5458 5459 5460/* ------------------------------ */ 5461 .balign 64 5462.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5463/* File: armv5te/OP_AND_INT_2ADDR.S */ 5464/* File: armv5te/binop2addr.S */ 5465 /* 5466 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5467 * that specifies an instruction that performs "result = r0 op r1". 5468 * This could be an ARM instruction or a function call. (If the result 5469 * comes back in a register other than r0, you can override "result".) 5470 * 5471 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5472 * vCC (r1). Useful for integer division and modulus. 5473 * 5474 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5475 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5476 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5477 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5478 */ 5479 /* binop/2addr vA, vB */ 5480 mov r9, rINST, lsr #8 @ r9<- A+ 5481 mov r3, rINST, lsr #12 @ r3<- B 5482 and r9, r9, #15 5483 GET_VREG(r1, r3) @ r1<- vB 5484 GET_VREG(r0, r9) @ r0<- vA 5485 .if 0 5486 cmp r1, #0 @ is second operand zero? 5487 beq common_errDivideByZero 5488 .endif 5489 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5490 5491 @ optional op; may set condition codes 5492 and r0, r0, r1 @ r0<- op, r0-r3 changed 5493 GET_INST_OPCODE(ip) @ extract opcode from rINST 5494 SET_VREG(r0, r9) @ vAA<- r0 5495 GOTO_OPCODE(ip) @ jump to next instruction 5496 /* 10-13 instructions */ 5497 5498 5499/* ------------------------------ */ 5500 .balign 64 5501.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5502/* File: armv5te/OP_OR_INT_2ADDR.S */ 5503/* File: armv5te/binop2addr.S */ 5504 /* 5505 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5506 * that specifies an instruction that performs "result = r0 op r1". 5507 * This could be an ARM instruction or a function call. (If the result 5508 * comes back in a register other than r0, you can override "result".) 5509 * 5510 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5511 * vCC (r1). Useful for integer division and modulus. 5512 * 5513 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5514 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5515 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5516 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5517 */ 5518 /* binop/2addr vA, vB */ 5519 mov r9, rINST, lsr #8 @ r9<- A+ 5520 mov r3, rINST, lsr #12 @ r3<- B 5521 and r9, r9, #15 5522 GET_VREG(r1, r3) @ r1<- vB 5523 GET_VREG(r0, r9) @ r0<- vA 5524 .if 0 5525 cmp r1, #0 @ is second operand zero? 5526 beq common_errDivideByZero 5527 .endif 5528 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5529 5530 @ optional op; may set condition codes 5531 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5532 GET_INST_OPCODE(ip) @ extract opcode from rINST 5533 SET_VREG(r0, r9) @ vAA<- r0 5534 GOTO_OPCODE(ip) @ jump to next instruction 5535 /* 10-13 instructions */ 5536 5537 5538/* ------------------------------ */ 5539 .balign 64 5540.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5541/* File: armv5te/OP_XOR_INT_2ADDR.S */ 5542/* File: armv5te/binop2addr.S */ 5543 /* 5544 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5545 * that specifies an instruction that performs "result = r0 op r1". 5546 * This could be an ARM instruction or a function call. (If the result 5547 * comes back in a register other than r0, you can override "result".) 5548 * 5549 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5550 * vCC (r1). Useful for integer division and modulus. 5551 * 5552 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5553 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5554 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5555 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5556 */ 5557 /* binop/2addr vA, vB */ 5558 mov r9, rINST, lsr #8 @ r9<- A+ 5559 mov r3, rINST, lsr #12 @ r3<- B 5560 and r9, r9, #15 5561 GET_VREG(r1, r3) @ r1<- vB 5562 GET_VREG(r0, r9) @ r0<- vA 5563 .if 0 5564 cmp r1, #0 @ is second operand zero? 5565 beq common_errDivideByZero 5566 .endif 5567 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5568 5569 @ optional op; may set condition codes 5570 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5571 GET_INST_OPCODE(ip) @ extract opcode from rINST 5572 SET_VREG(r0, r9) @ vAA<- r0 5573 GOTO_OPCODE(ip) @ jump to next instruction 5574 /* 10-13 instructions */ 5575 5576 5577/* ------------------------------ */ 5578 .balign 64 5579.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5580/* File: armv5te/OP_SHL_INT_2ADDR.S */ 5581/* File: armv5te/binop2addr.S */ 5582 /* 5583 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5584 * that specifies an instruction that performs "result = r0 op r1". 5585 * This could be an ARM instruction or a function call. (If the result 5586 * comes back in a register other than r0, you can override "result".) 5587 * 5588 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5589 * vCC (r1). Useful for integer division and modulus. 5590 * 5591 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5592 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5593 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5594 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5595 */ 5596 /* binop/2addr vA, vB */ 5597 mov r9, rINST, lsr #8 @ r9<- A+ 5598 mov r3, rINST, lsr #12 @ r3<- B 5599 and r9, r9, #15 5600 GET_VREG(r1, r3) @ r1<- vB 5601 GET_VREG(r0, r9) @ r0<- vA 5602 .if 0 5603 cmp r1, #0 @ is second operand zero? 5604 beq common_errDivideByZero 5605 .endif 5606 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5607 5608 and r1, r1, #31 @ optional op; may set condition codes 5609 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5610 GET_INST_OPCODE(ip) @ extract opcode from rINST 5611 SET_VREG(r0, r9) @ vAA<- r0 5612 GOTO_OPCODE(ip) @ jump to next instruction 5613 /* 10-13 instructions */ 5614 5615 5616/* ------------------------------ */ 5617 .balign 64 5618.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5619/* File: armv5te/OP_SHR_INT_2ADDR.S */ 5620/* File: armv5te/binop2addr.S */ 5621 /* 5622 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5623 * that specifies an instruction that performs "result = r0 op r1". 5624 * This could be an ARM instruction or a function call. (If the result 5625 * comes back in a register other than r0, you can override "result".) 5626 * 5627 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5628 * vCC (r1). Useful for integer division and modulus. 5629 * 5630 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5631 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5632 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5633 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5634 */ 5635 /* binop/2addr vA, vB */ 5636 mov r9, rINST, lsr #8 @ r9<- A+ 5637 mov r3, rINST, lsr #12 @ r3<- B 5638 and r9, r9, #15 5639 GET_VREG(r1, r3) @ r1<- vB 5640 GET_VREG(r0, r9) @ r0<- vA 5641 .if 0 5642 cmp r1, #0 @ is second operand zero? 5643 beq common_errDivideByZero 5644 .endif 5645 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5646 5647 and r1, r1, #31 @ optional op; may set condition codes 5648 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5649 GET_INST_OPCODE(ip) @ extract opcode from rINST 5650 SET_VREG(r0, r9) @ vAA<- r0 5651 GOTO_OPCODE(ip) @ jump to next instruction 5652 /* 10-13 instructions */ 5653 5654 5655/* ------------------------------ */ 5656 .balign 64 5657.L_OP_USHR_INT_2ADDR: /* 0xba */ 5658/* File: armv5te/OP_USHR_INT_2ADDR.S */ 5659/* File: armv5te/binop2addr.S */ 5660 /* 5661 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5662 * that specifies an instruction that performs "result = r0 op r1". 5663 * This could be an ARM instruction or a function call. (If the result 5664 * comes back in a register other than r0, you can override "result".) 5665 * 5666 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5667 * vCC (r1). Useful for integer division and modulus. 5668 * 5669 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5670 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5671 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5672 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5673 */ 5674 /* binop/2addr vA, vB */ 5675 mov r9, rINST, lsr #8 @ r9<- A+ 5676 mov r3, rINST, lsr #12 @ r3<- B 5677 and r9, r9, #15 5678 GET_VREG(r1, r3) @ r1<- vB 5679 GET_VREG(r0, r9) @ r0<- vA 5680 .if 0 5681 cmp r1, #0 @ is second operand zero? 5682 beq common_errDivideByZero 5683 .endif 5684 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5685 5686 and r1, r1, #31 @ optional op; may set condition codes 5687 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5688 GET_INST_OPCODE(ip) @ extract opcode from rINST 5689 SET_VREG(r0, r9) @ vAA<- r0 5690 GOTO_OPCODE(ip) @ jump to next instruction 5691 /* 10-13 instructions */ 5692 5693 5694/* ------------------------------ */ 5695 .balign 64 5696.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5697/* File: armv5te/OP_ADD_LONG_2ADDR.S */ 5698/* File: armv5te/binopWide2addr.S */ 5699 /* 5700 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5701 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5702 * This could be an ARM instruction or a function call. (If the result 5703 * comes back in a register other than r0, you can override "result".) 5704 * 5705 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5706 * vCC (r1). Useful for integer division and modulus. 5707 * 5708 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5709 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5710 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5711 * rem-double/2addr 5712 */ 5713 /* binop/2addr vA, vB */ 5714 mov r9, rINST, lsr #8 @ r9<- A+ 5715 mov r1, rINST, lsr #12 @ r1<- B 5716 and r9, r9, #15 5717 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5718 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5719 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5720 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5721 .if 0 5722 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5723 beq common_errDivideByZero 5724 .endif 5725 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5726 5727 adds r0, r0, r2 @ optional op; may set condition codes 5728 adc r1, r1, r3 @ result<- op, r0-r3 changed 5729 GET_INST_OPCODE(ip) @ extract opcode from rINST 5730 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5731 GOTO_OPCODE(ip) @ jump to next instruction 5732 /* 12-15 instructions */ 5733 5734 5735/* ------------------------------ */ 5736 .balign 64 5737.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5738/* File: armv5te/OP_SUB_LONG_2ADDR.S */ 5739/* File: armv5te/binopWide2addr.S */ 5740 /* 5741 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5742 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5743 * This could be an ARM instruction or a function call. (If the result 5744 * comes back in a register other than r0, you can override "result".) 5745 * 5746 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5747 * vCC (r1). Useful for integer division and modulus. 5748 * 5749 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5750 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5751 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5752 * rem-double/2addr 5753 */ 5754 /* binop/2addr vA, vB */ 5755 mov r9, rINST, lsr #8 @ r9<- A+ 5756 mov r1, rINST, lsr #12 @ r1<- B 5757 and r9, r9, #15 5758 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5759 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5760 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5761 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5762 .if 0 5763 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5764 beq common_errDivideByZero 5765 .endif 5766 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5767 5768 subs r0, r0, r2 @ optional op; may set condition codes 5769 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5770 GET_INST_OPCODE(ip) @ extract opcode from rINST 5771 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5772 GOTO_OPCODE(ip) @ jump to next instruction 5773 /* 12-15 instructions */ 5774 5775 5776/* ------------------------------ */ 5777 .balign 64 5778.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 5779/* File: armv5te/OP_MUL_LONG_2ADDR.S */ 5780 /* 5781 * Signed 64-bit integer multiply, "/2addr" version. 5782 * 5783 * See OP_MUL_LONG for an explanation. 5784 * 5785 * We get a little tight on registers, so to avoid looking up &fp[A] 5786 * again we stuff it into rINST. 5787 */ 5788 /* mul-long/2addr vA, vB */ 5789 mov r9, rINST, lsr #8 @ r9<- A+ 5790 mov r1, rINST, lsr #12 @ r1<- B 5791 and r9, r9, #15 5792 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5793 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 5794 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5795 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 5796 mul ip, r2, r1 @ ip<- ZxW 5797 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 5798 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 5799 mov r0, rINST @ r0<- &fp[A] (free up rINST) 5800 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5801 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 5802 GET_INST_OPCODE(ip) @ extract opcode from rINST 5803 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 5804 GOTO_OPCODE(ip) @ jump to next instruction 5805 5806/* ------------------------------ */ 5807 .balign 64 5808.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 5809/* File: armv5te/OP_DIV_LONG_2ADDR.S */ 5810/* File: armv5te/binopWide2addr.S */ 5811 /* 5812 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5813 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5814 * This could be an ARM instruction or a function call. (If the result 5815 * comes back in a register other than r0, you can override "result".) 5816 * 5817 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5818 * vCC (r1). Useful for integer division and modulus. 5819 * 5820 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5821 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5822 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5823 * rem-double/2addr 5824 */ 5825 /* binop/2addr vA, vB */ 5826 mov r9, rINST, lsr #8 @ r9<- A+ 5827 mov r1, rINST, lsr #12 @ r1<- B 5828 and r9, r9, #15 5829 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5830 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5831 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5832 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5833 .if 1 5834 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5835 beq common_errDivideByZero 5836 .endif 5837 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5838 5839 @ optional op; may set condition codes 5840 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5841 GET_INST_OPCODE(ip) @ extract opcode from rINST 5842 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5843 GOTO_OPCODE(ip) @ jump to next instruction 5844 /* 12-15 instructions */ 5845 5846 5847/* ------------------------------ */ 5848 .balign 64 5849.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5850/* File: armv5te/OP_REM_LONG_2ADDR.S */ 5851/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 5852/* File: armv5te/binopWide2addr.S */ 5853 /* 5854 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5855 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5856 * This could be an ARM instruction or a function call. (If the result 5857 * comes back in a register other than r0, you can override "result".) 5858 * 5859 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5860 * vCC (r1). Useful for integer division and modulus. 5861 * 5862 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5863 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5864 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5865 * rem-double/2addr 5866 */ 5867 /* binop/2addr vA, vB */ 5868 mov r9, rINST, lsr #8 @ r9<- A+ 5869 mov r1, rINST, lsr #12 @ r1<- B 5870 and r9, r9, #15 5871 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5872 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5873 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5874 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5875 .if 1 5876 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5877 beq common_errDivideByZero 5878 .endif 5879 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5880 5881 @ optional op; may set condition codes 5882 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5883 GET_INST_OPCODE(ip) @ extract opcode from rINST 5884 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 5885 GOTO_OPCODE(ip) @ jump to next instruction 5886 /* 12-15 instructions */ 5887 5888 5889/* ------------------------------ */ 5890 .balign 64 5891.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 5892/* File: armv5te/OP_AND_LONG_2ADDR.S */ 5893/* File: armv5te/binopWide2addr.S */ 5894 /* 5895 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5896 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5897 * This could be an ARM instruction or a function call. (If the result 5898 * comes back in a register other than r0, you can override "result".) 5899 * 5900 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5901 * vCC (r1). Useful for integer division and modulus. 5902 * 5903 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5904 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5905 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5906 * rem-double/2addr 5907 */ 5908 /* binop/2addr vA, vB */ 5909 mov r9, rINST, lsr #8 @ r9<- A+ 5910 mov r1, rINST, lsr #12 @ r1<- B 5911 and r9, r9, #15 5912 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5913 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5914 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5915 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5916 .if 0 5917 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5918 beq common_errDivideByZero 5919 .endif 5920 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5921 5922 and r0, r0, r2 @ optional op; may set condition codes 5923 and r1, r1, r3 @ result<- op, r0-r3 changed 5924 GET_INST_OPCODE(ip) @ extract opcode from rINST 5925 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5926 GOTO_OPCODE(ip) @ jump to next instruction 5927 /* 12-15 instructions */ 5928 5929 5930/* ------------------------------ */ 5931 .balign 64 5932.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 5933/* File: armv5te/OP_OR_LONG_2ADDR.S */ 5934/* File: armv5te/binopWide2addr.S */ 5935 /* 5936 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5937 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5938 * This could be an ARM instruction or a function call. (If the result 5939 * comes back in a register other than r0, you can override "result".) 5940 * 5941 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5942 * vCC (r1). Useful for integer division and modulus. 5943 * 5944 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5945 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5946 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5947 * rem-double/2addr 5948 */ 5949 /* binop/2addr vA, vB */ 5950 mov r9, rINST, lsr #8 @ r9<- A+ 5951 mov r1, rINST, lsr #12 @ r1<- B 5952 and r9, r9, #15 5953 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5954 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5955 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5956 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5957 .if 0 5958 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5959 beq common_errDivideByZero 5960 .endif 5961 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5962 5963 orr r0, r0, r2 @ optional op; may set condition codes 5964 orr r1, r1, r3 @ result<- op, r0-r3 changed 5965 GET_INST_OPCODE(ip) @ extract opcode from rINST 5966 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5967 GOTO_OPCODE(ip) @ jump to next instruction 5968 /* 12-15 instructions */ 5969 5970 5971/* ------------------------------ */ 5972 .balign 64 5973.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 5974/* File: armv5te/OP_XOR_LONG_2ADDR.S */ 5975/* File: armv5te/binopWide2addr.S */ 5976 /* 5977 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5978 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5979 * This could be an ARM instruction or a function call. (If the result 5980 * comes back in a register other than r0, you can override "result".) 5981 * 5982 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5983 * vCC (r1). Useful for integer division and modulus. 5984 * 5985 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5986 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5987 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5988 * rem-double/2addr 5989 */ 5990 /* binop/2addr vA, vB */ 5991 mov r9, rINST, lsr #8 @ r9<- A+ 5992 mov r1, rINST, lsr #12 @ r1<- B 5993 and r9, r9, #15 5994 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5995 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5996 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5997 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5998 .if 0 5999 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6000 beq common_errDivideByZero 6001 .endif 6002 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6003 6004 eor r0, r0, r2 @ optional op; may set condition codes 6005 eor r1, r1, r3 @ result<- op, r0-r3 changed 6006 GET_INST_OPCODE(ip) @ extract opcode from rINST 6007 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6008 GOTO_OPCODE(ip) @ jump to next instruction 6009 /* 12-15 instructions */ 6010 6011 6012/* ------------------------------ */ 6013 .balign 64 6014.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 6015/* File: armv5te/OP_SHL_LONG_2ADDR.S */ 6016 /* 6017 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6018 * 32-bit shift distance. 6019 */ 6020 /* shl-long/2addr vA, vB */ 6021 mov r9, rINST, lsr #8 @ r9<- A+ 6022 mov r3, rINST, lsr #12 @ r3<- B 6023 and r9, r9, #15 6024 GET_VREG(r2, r3) @ r2<- vB 6025 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6026 and r2, r2, #63 @ r2<- r2 & 0x3f 6027 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6028 6029 mov r1, r1, asl r2 @ r1<- r1 << r2 6030 rsb r3, r2, #32 @ r3<- 32 - r2 6031 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 6032 subs ip, r2, #32 @ ip<- r2 - 32 6033 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6034 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 6035 mov r0, r0, asl r2 @ r0<- r0 << r2 6036 b .LOP_SHL_LONG_2ADDR_finish 6037 6038/* ------------------------------ */ 6039 .balign 64 6040.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 6041/* File: armv5te/OP_SHR_LONG_2ADDR.S */ 6042 /* 6043 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6044 * 32-bit shift distance. 6045 */ 6046 /* shr-long/2addr vA, vB */ 6047 mov r9, rINST, lsr #8 @ r9<- A+ 6048 mov r3, rINST, lsr #12 @ r3<- B 6049 and r9, r9, #15 6050 GET_VREG(r2, r3) @ r2<- vB 6051 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6052 and r2, r2, #63 @ r2<- r2 & 0x3f 6053 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6054 6055 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6056 rsb r3, r2, #32 @ r3<- 32 - r2 6057 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6058 subs ip, r2, #32 @ ip<- r2 - 32 6059 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6060 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6061 mov r1, r1, asr r2 @ r1<- r1 >> r2 6062 b .LOP_SHR_LONG_2ADDR_finish 6063 6064/* ------------------------------ */ 6065 .balign 64 6066.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6067/* File: armv5te/OP_USHR_LONG_2ADDR.S */ 6068 /* 6069 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6070 * 32-bit shift distance. 6071 */ 6072 /* ushr-long/2addr vA, vB */ 6073 mov r9, rINST, lsr #8 @ r9<- A+ 6074 mov r3, rINST, lsr #12 @ r3<- B 6075 and r9, r9, #15 6076 GET_VREG(r2, r3) @ r2<- vB 6077 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6078 and r2, r2, #63 @ r2<- r2 & 0x3f 6079 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6080 6081 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6082 rsb r3, r2, #32 @ r3<- 32 - r2 6083 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6084 subs ip, r2, #32 @ ip<- r2 - 32 6085 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6086 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6087 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6088 b .LOP_USHR_LONG_2ADDR_finish 6089 6090/* ------------------------------ */ 6091 .balign 64 6092.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6093/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */ 6094/* File: arm-vfp/fbinop2addr.S */ 6095 /* 6096 * Generic 32-bit floating point "/2addr" binary operation. Provide 6097 * an "instr" line that specifies an instruction that performs 6098 * "s2 = s0 op s1". 6099 * 6100 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6101 */ 6102 /* binop/2addr vA, vB */ 6103 mov r3, rINST, lsr #12 @ r3<- B 6104 mov r9, rINST, lsr #8 @ r9<- A+ 6105 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6106 and r9, r9, #15 @ r9<- A 6107 flds s1, [r3] @ s1<- vB 6108 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6109 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6110 flds s0, [r9] @ s0<- vA 6111 6112 fadds s2, s0, s1 @ s2<- op 6113 GET_INST_OPCODE(ip) @ extract opcode from rINST 6114 fsts s2, [r9] @ vAA<- s2 6115 GOTO_OPCODE(ip) @ jump to next instruction 6116 6117 6118/* ------------------------------ */ 6119 .balign 64 6120.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6121/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */ 6122/* File: arm-vfp/fbinop2addr.S */ 6123 /* 6124 * Generic 32-bit floating point "/2addr" binary operation. Provide 6125 * an "instr" line that specifies an instruction that performs 6126 * "s2 = s0 op s1". 6127 * 6128 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6129 */ 6130 /* binop/2addr vA, vB */ 6131 mov r3, rINST, lsr #12 @ r3<- B 6132 mov r9, rINST, lsr #8 @ r9<- A+ 6133 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6134 and r9, r9, #15 @ r9<- A 6135 flds s1, [r3] @ s1<- vB 6136 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6137 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6138 flds s0, [r9] @ s0<- vA 6139 6140 fsubs s2, s0, s1 @ s2<- op 6141 GET_INST_OPCODE(ip) @ extract opcode from rINST 6142 fsts s2, [r9] @ vAA<- s2 6143 GOTO_OPCODE(ip) @ jump to next instruction 6144 6145 6146/* ------------------------------ */ 6147 .balign 64 6148.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6149/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */ 6150/* File: arm-vfp/fbinop2addr.S */ 6151 /* 6152 * Generic 32-bit floating point "/2addr" binary operation. Provide 6153 * an "instr" line that specifies an instruction that performs 6154 * "s2 = s0 op s1". 6155 * 6156 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6157 */ 6158 /* binop/2addr vA, vB */ 6159 mov r3, rINST, lsr #12 @ r3<- B 6160 mov r9, rINST, lsr #8 @ r9<- A+ 6161 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6162 and r9, r9, #15 @ r9<- A 6163 flds s1, [r3] @ s1<- vB 6164 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6165 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6166 flds s0, [r9] @ s0<- vA 6167 6168 fmuls s2, s0, s1 @ s2<- op 6169 GET_INST_OPCODE(ip) @ extract opcode from rINST 6170 fsts s2, [r9] @ vAA<- s2 6171 GOTO_OPCODE(ip) @ jump to next instruction 6172 6173 6174/* ------------------------------ */ 6175 .balign 64 6176.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6177/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */ 6178/* File: arm-vfp/fbinop2addr.S */ 6179 /* 6180 * Generic 32-bit floating point "/2addr" binary operation. Provide 6181 * an "instr" line that specifies an instruction that performs 6182 * "s2 = s0 op s1". 6183 * 6184 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6185 */ 6186 /* binop/2addr vA, vB */ 6187 mov r3, rINST, lsr #12 @ r3<- B 6188 mov r9, rINST, lsr #8 @ r9<- A+ 6189 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6190 and r9, r9, #15 @ r9<- A 6191 flds s1, [r3] @ s1<- vB 6192 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6193 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6194 flds s0, [r9] @ s0<- vA 6195 6196 fdivs s2, s0, s1 @ s2<- op 6197 GET_INST_OPCODE(ip) @ extract opcode from rINST 6198 fsts s2, [r9] @ vAA<- s2 6199 GOTO_OPCODE(ip) @ jump to next instruction 6200 6201 6202/* ------------------------------ */ 6203 .balign 64 6204.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6205/* File: armv5te/OP_REM_FLOAT_2ADDR.S */ 6206/* EABI doesn't define a float remainder function, but libm does */ 6207/* File: armv5te/binop2addr.S */ 6208 /* 6209 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6210 * that specifies an instruction that performs "result = r0 op r1". 6211 * This could be an ARM instruction or a function call. (If the result 6212 * comes back in a register other than r0, you can override "result".) 6213 * 6214 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6215 * vCC (r1). Useful for integer division and modulus. 6216 * 6217 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6218 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6219 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6220 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6221 */ 6222 /* binop/2addr vA, vB */ 6223 mov r9, rINST, lsr #8 @ r9<- A+ 6224 mov r3, rINST, lsr #12 @ r3<- B 6225 and r9, r9, #15 6226 GET_VREG(r1, r3) @ r1<- vB 6227 GET_VREG(r0, r9) @ r0<- vA 6228 .if 0 6229 cmp r1, #0 @ is second operand zero? 6230 beq common_errDivideByZero 6231 .endif 6232 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6233 6234 @ optional op; may set condition codes 6235 bl fmodf @ r0<- op, r0-r3 changed 6236 GET_INST_OPCODE(ip) @ extract opcode from rINST 6237 SET_VREG(r0, r9) @ vAA<- r0 6238 GOTO_OPCODE(ip) @ jump to next instruction 6239 /* 10-13 instructions */ 6240 6241 6242/* ------------------------------ */ 6243 .balign 64 6244.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6245/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */ 6246/* File: arm-vfp/fbinopWide2addr.S */ 6247 /* 6248 * Generic 64-bit floating point "/2addr" binary operation. Provide 6249 * an "instr" line that specifies an instruction that performs 6250 * "d2 = d0 op d1". 6251 * 6252 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6253 * div-double/2addr 6254 */ 6255 /* binop/2addr vA, vB */ 6256 mov r3, rINST, lsr #12 @ r3<- B 6257 mov r9, rINST, lsr #8 @ r9<- A+ 6258 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6259 and r9, r9, #15 @ r9<- A 6260 fldd d1, [r3] @ d1<- vB 6261 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6262 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6263 fldd d0, [r9] @ d0<- vA 6264 6265 faddd d2, d0, d1 @ d2<- op 6266 GET_INST_OPCODE(ip) @ extract opcode from rINST 6267 fstd d2, [r9] @ vAA<- d2 6268 GOTO_OPCODE(ip) @ jump to next instruction 6269 6270 6271/* ------------------------------ */ 6272 .balign 64 6273.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6274/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */ 6275/* File: arm-vfp/fbinopWide2addr.S */ 6276 /* 6277 * Generic 64-bit floating point "/2addr" binary operation. Provide 6278 * an "instr" line that specifies an instruction that performs 6279 * "d2 = d0 op d1". 6280 * 6281 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6282 * div-double/2addr 6283 */ 6284 /* binop/2addr vA, vB */ 6285 mov r3, rINST, lsr #12 @ r3<- B 6286 mov r9, rINST, lsr #8 @ r9<- A+ 6287 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6288 and r9, r9, #15 @ r9<- A 6289 fldd d1, [r3] @ d1<- vB 6290 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6291 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6292 fldd d0, [r9] @ d0<- vA 6293 6294 fsubd d2, d0, d1 @ d2<- op 6295 GET_INST_OPCODE(ip) @ extract opcode from rINST 6296 fstd d2, [r9] @ vAA<- d2 6297 GOTO_OPCODE(ip) @ jump to next instruction 6298 6299 6300/* ------------------------------ */ 6301 .balign 64 6302.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6303/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */ 6304/* File: arm-vfp/fbinopWide2addr.S */ 6305 /* 6306 * Generic 64-bit floating point "/2addr" binary operation. Provide 6307 * an "instr" line that specifies an instruction that performs 6308 * "d2 = d0 op d1". 6309 * 6310 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6311 * div-double/2addr 6312 */ 6313 /* binop/2addr vA, vB */ 6314 mov r3, rINST, lsr #12 @ r3<- B 6315 mov r9, rINST, lsr #8 @ r9<- A+ 6316 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6317 and r9, r9, #15 @ r9<- A 6318 fldd d1, [r3] @ d1<- vB 6319 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6320 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6321 fldd d0, [r9] @ d0<- vA 6322 6323 fmuld d2, d0, d1 @ d2<- op 6324 GET_INST_OPCODE(ip) @ extract opcode from rINST 6325 fstd d2, [r9] @ vAA<- d2 6326 GOTO_OPCODE(ip) @ jump to next instruction 6327 6328 6329/* ------------------------------ */ 6330 .balign 64 6331.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6332/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */ 6333/* File: arm-vfp/fbinopWide2addr.S */ 6334 /* 6335 * Generic 64-bit floating point "/2addr" binary operation. Provide 6336 * an "instr" line that specifies an instruction that performs 6337 * "d2 = d0 op d1". 6338 * 6339 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6340 * div-double/2addr 6341 */ 6342 /* binop/2addr vA, vB */ 6343 mov r3, rINST, lsr #12 @ r3<- B 6344 mov r9, rINST, lsr #8 @ r9<- A+ 6345 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6346 and r9, r9, #15 @ r9<- A 6347 fldd d1, [r3] @ d1<- vB 6348 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6349 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6350 fldd d0, [r9] @ d0<- vA 6351 6352 fdivd d2, d0, d1 @ d2<- op 6353 GET_INST_OPCODE(ip) @ extract opcode from rINST 6354 fstd d2, [r9] @ vAA<- d2 6355 GOTO_OPCODE(ip) @ jump to next instruction 6356 6357 6358/* ------------------------------ */ 6359 .balign 64 6360.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6361/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */ 6362/* EABI doesn't define a double remainder function, but libm does */ 6363/* File: armv5te/binopWide2addr.S */ 6364 /* 6365 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6366 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6367 * This could be an ARM instruction or a function call. (If the result 6368 * comes back in a register other than r0, you can override "result".) 6369 * 6370 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6371 * vCC (r1). Useful for integer division and modulus. 6372 * 6373 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6374 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6375 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6376 * rem-double/2addr 6377 */ 6378 /* binop/2addr vA, vB */ 6379 mov r9, rINST, lsr #8 @ r9<- A+ 6380 mov r1, rINST, lsr #12 @ r1<- B 6381 and r9, r9, #15 6382 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6383 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6384 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6385 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6386 .if 0 6387 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6388 beq common_errDivideByZero 6389 .endif 6390 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6391 6392 @ optional op; may set condition codes 6393 bl fmod @ result<- op, r0-r3 changed 6394 GET_INST_OPCODE(ip) @ extract opcode from rINST 6395 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6396 GOTO_OPCODE(ip) @ jump to next instruction 6397 /* 12-15 instructions */ 6398 6399 6400/* ------------------------------ */ 6401 .balign 64 6402.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6403/* File: armv5te/OP_ADD_INT_LIT16.S */ 6404/* File: armv5te/binopLit16.S */ 6405 /* 6406 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6407 * that specifies an instruction that performs "result = r0 op r1". 6408 * This could be an ARM instruction or a function call. (If the result 6409 * comes back in a register other than r0, you can override "result".) 6410 * 6411 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6412 * vCC (r1). Useful for integer division and modulus. 6413 * 6414 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6415 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6416 */ 6417 /* binop/lit16 vA, vB, #+CCCC */ 6418 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6419 mov r2, rINST, lsr #12 @ r2<- B 6420 mov r9, rINST, lsr #8 @ r9<- A+ 6421 GET_VREG(r0, r2) @ r0<- vB 6422 and r9, r9, #15 6423 .if 0 6424 cmp r1, #0 @ is second operand zero? 6425 beq common_errDivideByZero 6426 .endif 6427 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6428 6429 add r0, r0, r1 @ r0<- op, r0-r3 changed 6430 GET_INST_OPCODE(ip) @ extract opcode from rINST 6431 SET_VREG(r0, r9) @ vAA<- r0 6432 GOTO_OPCODE(ip) @ jump to next instruction 6433 /* 10-13 instructions */ 6434 6435 6436/* ------------------------------ */ 6437 .balign 64 6438.L_OP_RSUB_INT: /* 0xd1 */ 6439/* File: armv5te/OP_RSUB_INT.S */ 6440/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6441/* File: armv5te/binopLit16.S */ 6442 /* 6443 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6444 * that specifies an instruction that performs "result = r0 op r1". 6445 * This could be an ARM instruction or a function call. (If the result 6446 * comes back in a register other than r0, you can override "result".) 6447 * 6448 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6449 * vCC (r1). Useful for integer division and modulus. 6450 * 6451 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6452 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6453 */ 6454 /* binop/lit16 vA, vB, #+CCCC */ 6455 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6456 mov r2, rINST, lsr #12 @ r2<- B 6457 mov r9, rINST, lsr #8 @ r9<- A+ 6458 GET_VREG(r0, r2) @ r0<- vB 6459 and r9, r9, #15 6460 .if 0 6461 cmp r1, #0 @ is second operand zero? 6462 beq common_errDivideByZero 6463 .endif 6464 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6465 6466 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6467 GET_INST_OPCODE(ip) @ extract opcode from rINST 6468 SET_VREG(r0, r9) @ vAA<- r0 6469 GOTO_OPCODE(ip) @ jump to next instruction 6470 /* 10-13 instructions */ 6471 6472 6473/* ------------------------------ */ 6474 .balign 64 6475.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6476/* File: armv5te/OP_MUL_INT_LIT16.S */ 6477/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6478/* File: armv5te/binopLit16.S */ 6479 /* 6480 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6481 * that specifies an instruction that performs "result = r0 op r1". 6482 * This could be an ARM instruction or a function call. (If the result 6483 * comes back in a register other than r0, you can override "result".) 6484 * 6485 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6486 * vCC (r1). Useful for integer division and modulus. 6487 * 6488 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6489 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6490 */ 6491 /* binop/lit16 vA, vB, #+CCCC */ 6492 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6493 mov r2, rINST, lsr #12 @ r2<- B 6494 mov r9, rINST, lsr #8 @ r9<- A+ 6495 GET_VREG(r0, r2) @ r0<- vB 6496 and r9, r9, #15 6497 .if 0 6498 cmp r1, #0 @ is second operand zero? 6499 beq common_errDivideByZero 6500 .endif 6501 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6502 6503 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6504 GET_INST_OPCODE(ip) @ extract opcode from rINST 6505 SET_VREG(r0, r9) @ vAA<- r0 6506 GOTO_OPCODE(ip) @ jump to next instruction 6507 /* 10-13 instructions */ 6508 6509 6510/* ------------------------------ */ 6511 .balign 64 6512.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6513/* File: armv5te/OP_DIV_INT_LIT16.S */ 6514/* File: armv5te/binopLit16.S */ 6515 /* 6516 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6517 * that specifies an instruction that performs "result = r0 op r1". 6518 * This could be an ARM instruction or a function call. (If the result 6519 * comes back in a register other than r0, you can override "result".) 6520 * 6521 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6522 * vCC (r1). Useful for integer division and modulus. 6523 * 6524 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6525 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6526 */ 6527 /* binop/lit16 vA, vB, #+CCCC */ 6528 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6529 mov r2, rINST, lsr #12 @ r2<- B 6530 mov r9, rINST, lsr #8 @ r9<- A+ 6531 GET_VREG(r0, r2) @ r0<- vB 6532 and r9, r9, #15 6533 .if 1 6534 cmp r1, #0 @ is second operand zero? 6535 beq common_errDivideByZero 6536 .endif 6537 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6538 6539 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6540 GET_INST_OPCODE(ip) @ extract opcode from rINST 6541 SET_VREG(r0, r9) @ vAA<- r0 6542 GOTO_OPCODE(ip) @ jump to next instruction 6543 /* 10-13 instructions */ 6544 6545 6546/* ------------------------------ */ 6547 .balign 64 6548.L_OP_REM_INT_LIT16: /* 0xd4 */ 6549/* File: armv5te/OP_REM_INT_LIT16.S */ 6550/* idivmod returns quotient in r0 and remainder in r1 */ 6551/* File: armv5te/binopLit16.S */ 6552 /* 6553 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6554 * that specifies an instruction that performs "result = r0 op r1". 6555 * This could be an ARM instruction or a function call. (If the result 6556 * comes back in a register other than r0, you can override "result".) 6557 * 6558 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6559 * vCC (r1). Useful for integer division and modulus. 6560 * 6561 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6562 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6563 */ 6564 /* binop/lit16 vA, vB, #+CCCC */ 6565 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6566 mov r2, rINST, lsr #12 @ r2<- B 6567 mov r9, rINST, lsr #8 @ r9<- A+ 6568 GET_VREG(r0, r2) @ r0<- vB 6569 and r9, r9, #15 6570 .if 1 6571 cmp r1, #0 @ is second operand zero? 6572 beq common_errDivideByZero 6573 .endif 6574 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6575 6576 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6577 GET_INST_OPCODE(ip) @ extract opcode from rINST 6578 SET_VREG(r1, r9) @ vAA<- r1 6579 GOTO_OPCODE(ip) @ jump to next instruction 6580 /* 10-13 instructions */ 6581 6582 6583/* ------------------------------ */ 6584 .balign 64 6585.L_OP_AND_INT_LIT16: /* 0xd5 */ 6586/* File: armv5te/OP_AND_INT_LIT16.S */ 6587/* File: armv5te/binopLit16.S */ 6588 /* 6589 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6590 * that specifies an instruction that performs "result = r0 op r1". 6591 * This could be an ARM instruction or a function call. (If the result 6592 * comes back in a register other than r0, you can override "result".) 6593 * 6594 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6595 * vCC (r1). Useful for integer division and modulus. 6596 * 6597 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6598 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6599 */ 6600 /* binop/lit16 vA, vB, #+CCCC */ 6601 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6602 mov r2, rINST, lsr #12 @ r2<- B 6603 mov r9, rINST, lsr #8 @ r9<- A+ 6604 GET_VREG(r0, r2) @ r0<- vB 6605 and r9, r9, #15 6606 .if 0 6607 cmp r1, #0 @ is second operand zero? 6608 beq common_errDivideByZero 6609 .endif 6610 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6611 6612 and r0, r0, r1 @ r0<- op, r0-r3 changed 6613 GET_INST_OPCODE(ip) @ extract opcode from rINST 6614 SET_VREG(r0, r9) @ vAA<- r0 6615 GOTO_OPCODE(ip) @ jump to next instruction 6616 /* 10-13 instructions */ 6617 6618 6619/* ------------------------------ */ 6620 .balign 64 6621.L_OP_OR_INT_LIT16: /* 0xd6 */ 6622/* File: armv5te/OP_OR_INT_LIT16.S */ 6623/* File: armv5te/binopLit16.S */ 6624 /* 6625 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6626 * that specifies an instruction that performs "result = r0 op r1". 6627 * This could be an ARM instruction or a function call. (If the result 6628 * comes back in a register other than r0, you can override "result".) 6629 * 6630 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6631 * vCC (r1). Useful for integer division and modulus. 6632 * 6633 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6634 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6635 */ 6636 /* binop/lit16 vA, vB, #+CCCC */ 6637 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6638 mov r2, rINST, lsr #12 @ r2<- B 6639 mov r9, rINST, lsr #8 @ r9<- A+ 6640 GET_VREG(r0, r2) @ r0<- vB 6641 and r9, r9, #15 6642 .if 0 6643 cmp r1, #0 @ is second operand zero? 6644 beq common_errDivideByZero 6645 .endif 6646 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6647 6648 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6649 GET_INST_OPCODE(ip) @ extract opcode from rINST 6650 SET_VREG(r0, r9) @ vAA<- r0 6651 GOTO_OPCODE(ip) @ jump to next instruction 6652 /* 10-13 instructions */ 6653 6654 6655/* ------------------------------ */ 6656 .balign 64 6657.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6658/* File: armv5te/OP_XOR_INT_LIT16.S */ 6659/* File: armv5te/binopLit16.S */ 6660 /* 6661 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6662 * that specifies an instruction that performs "result = r0 op r1". 6663 * This could be an ARM instruction or a function call. (If the result 6664 * comes back in a register other than r0, you can override "result".) 6665 * 6666 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6667 * vCC (r1). Useful for integer division and modulus. 6668 * 6669 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6670 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6671 */ 6672 /* binop/lit16 vA, vB, #+CCCC */ 6673 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6674 mov r2, rINST, lsr #12 @ r2<- B 6675 mov r9, rINST, lsr #8 @ r9<- A+ 6676 GET_VREG(r0, r2) @ r0<- vB 6677 and r9, r9, #15 6678 .if 0 6679 cmp r1, #0 @ is second operand zero? 6680 beq common_errDivideByZero 6681 .endif 6682 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6683 6684 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6685 GET_INST_OPCODE(ip) @ extract opcode from rINST 6686 SET_VREG(r0, r9) @ vAA<- r0 6687 GOTO_OPCODE(ip) @ jump to next instruction 6688 /* 10-13 instructions */ 6689 6690 6691/* ------------------------------ */ 6692 .balign 64 6693.L_OP_ADD_INT_LIT8: /* 0xd8 */ 6694/* File: armv5te/OP_ADD_INT_LIT8.S */ 6695/* File: armv5te/binopLit8.S */ 6696 /* 6697 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6698 * that specifies an instruction that performs "result = r0 op r1". 6699 * This could be an ARM instruction or a function call. (If the result 6700 * comes back in a register other than r0, you can override "result".) 6701 * 6702 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6703 * vCC (r1). Useful for integer division and modulus. 6704 * 6705 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6706 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6707 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6708 */ 6709 /* binop/lit8 vAA, vBB, #+CC */ 6710 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6711 mov r9, rINST, lsr #8 @ r9<- AA 6712 and r2, r3, #255 @ r2<- BB 6713 GET_VREG(r0, r2) @ r0<- vBB 6714 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6715 .if 0 6716 @cmp r1, #0 @ is second operand zero? 6717 beq common_errDivideByZero 6718 .endif 6719 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6720 6721 @ optional op; may set condition codes 6722 add r0, r0, r1 @ r0<- op, r0-r3 changed 6723 GET_INST_OPCODE(ip) @ extract opcode from rINST 6724 SET_VREG(r0, r9) @ vAA<- r0 6725 GOTO_OPCODE(ip) @ jump to next instruction 6726 /* 10-12 instructions */ 6727 6728 6729/* ------------------------------ */ 6730 .balign 64 6731.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 6732/* File: armv5te/OP_RSUB_INT_LIT8.S */ 6733/* File: armv5te/binopLit8.S */ 6734 /* 6735 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6736 * that specifies an instruction that performs "result = r0 op r1". 6737 * This could be an ARM instruction or a function call. (If the result 6738 * comes back in a register other than r0, you can override "result".) 6739 * 6740 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6741 * vCC (r1). Useful for integer division and modulus. 6742 * 6743 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6744 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6745 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6746 */ 6747 /* binop/lit8 vAA, vBB, #+CC */ 6748 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6749 mov r9, rINST, lsr #8 @ r9<- AA 6750 and r2, r3, #255 @ r2<- BB 6751 GET_VREG(r0, r2) @ r0<- vBB 6752 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6753 .if 0 6754 @cmp r1, #0 @ is second operand zero? 6755 beq common_errDivideByZero 6756 .endif 6757 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6758 6759 @ optional op; may set condition codes 6760 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6761 GET_INST_OPCODE(ip) @ extract opcode from rINST 6762 SET_VREG(r0, r9) @ vAA<- r0 6763 GOTO_OPCODE(ip) @ jump to next instruction 6764 /* 10-12 instructions */ 6765 6766 6767/* ------------------------------ */ 6768 .balign 64 6769.L_OP_MUL_INT_LIT8: /* 0xda */ 6770/* File: armv5te/OP_MUL_INT_LIT8.S */ 6771/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6772/* File: armv5te/binopLit8.S */ 6773 /* 6774 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6775 * that specifies an instruction that performs "result = r0 op r1". 6776 * This could be an ARM instruction or a function call. (If the result 6777 * comes back in a register other than r0, you can override "result".) 6778 * 6779 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6780 * vCC (r1). Useful for integer division and modulus. 6781 * 6782 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6783 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6784 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6785 */ 6786 /* binop/lit8 vAA, vBB, #+CC */ 6787 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6788 mov r9, rINST, lsr #8 @ r9<- AA 6789 and r2, r3, #255 @ r2<- BB 6790 GET_VREG(r0, r2) @ r0<- vBB 6791 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6792 .if 0 6793 @cmp r1, #0 @ is second operand zero? 6794 beq common_errDivideByZero 6795 .endif 6796 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6797 6798 @ optional op; may set condition codes 6799 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6800 GET_INST_OPCODE(ip) @ extract opcode from rINST 6801 SET_VREG(r0, r9) @ vAA<- r0 6802 GOTO_OPCODE(ip) @ jump to next instruction 6803 /* 10-12 instructions */ 6804 6805 6806/* ------------------------------ */ 6807 .balign 64 6808.L_OP_DIV_INT_LIT8: /* 0xdb */ 6809/* File: armv5te/OP_DIV_INT_LIT8.S */ 6810/* File: armv5te/binopLit8.S */ 6811 /* 6812 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6813 * that specifies an instruction that performs "result = r0 op r1". 6814 * This could be an ARM instruction or a function call. (If the result 6815 * comes back in a register other than r0, you can override "result".) 6816 * 6817 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6818 * vCC (r1). Useful for integer division and modulus. 6819 * 6820 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6821 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6822 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6823 */ 6824 /* binop/lit8 vAA, vBB, #+CC */ 6825 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6826 mov r9, rINST, lsr #8 @ r9<- AA 6827 and r2, r3, #255 @ r2<- BB 6828 GET_VREG(r0, r2) @ r0<- vBB 6829 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6830 .if 1 6831 @cmp r1, #0 @ is second operand zero? 6832 beq common_errDivideByZero 6833 .endif 6834 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6835 6836 @ optional op; may set condition codes 6837 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6838 GET_INST_OPCODE(ip) @ extract opcode from rINST 6839 SET_VREG(r0, r9) @ vAA<- r0 6840 GOTO_OPCODE(ip) @ jump to next instruction 6841 /* 10-12 instructions */ 6842 6843 6844/* ------------------------------ */ 6845 .balign 64 6846.L_OP_REM_INT_LIT8: /* 0xdc */ 6847/* File: armv5te/OP_REM_INT_LIT8.S */ 6848/* idivmod returns quotient in r0 and remainder in r1 */ 6849/* File: armv5te/binopLit8.S */ 6850 /* 6851 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6852 * that specifies an instruction that performs "result = r0 op r1". 6853 * This could be an ARM instruction or a function call. (If the result 6854 * comes back in a register other than r0, you can override "result".) 6855 * 6856 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6857 * vCC (r1). Useful for integer division and modulus. 6858 * 6859 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6860 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6861 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6862 */ 6863 /* binop/lit8 vAA, vBB, #+CC */ 6864 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6865 mov r9, rINST, lsr #8 @ r9<- AA 6866 and r2, r3, #255 @ r2<- BB 6867 GET_VREG(r0, r2) @ r0<- vBB 6868 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6869 .if 1 6870 @cmp r1, #0 @ is second operand zero? 6871 beq common_errDivideByZero 6872 .endif 6873 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6874 6875 @ optional op; may set condition codes 6876 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6877 GET_INST_OPCODE(ip) @ extract opcode from rINST 6878 SET_VREG(r1, r9) @ vAA<- r1 6879 GOTO_OPCODE(ip) @ jump to next instruction 6880 /* 10-12 instructions */ 6881 6882 6883/* ------------------------------ */ 6884 .balign 64 6885.L_OP_AND_INT_LIT8: /* 0xdd */ 6886/* File: armv5te/OP_AND_INT_LIT8.S */ 6887/* File: armv5te/binopLit8.S */ 6888 /* 6889 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6890 * that specifies an instruction that performs "result = r0 op r1". 6891 * This could be an ARM instruction or a function call. (If the result 6892 * comes back in a register other than r0, you can override "result".) 6893 * 6894 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6895 * vCC (r1). Useful for integer division and modulus. 6896 * 6897 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6898 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6899 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6900 */ 6901 /* binop/lit8 vAA, vBB, #+CC */ 6902 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6903 mov r9, rINST, lsr #8 @ r9<- AA 6904 and r2, r3, #255 @ r2<- BB 6905 GET_VREG(r0, r2) @ r0<- vBB 6906 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6907 .if 0 6908 @cmp r1, #0 @ is second operand zero? 6909 beq common_errDivideByZero 6910 .endif 6911 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6912 6913 @ optional op; may set condition codes 6914 and r0, r0, r1 @ r0<- op, r0-r3 changed 6915 GET_INST_OPCODE(ip) @ extract opcode from rINST 6916 SET_VREG(r0, r9) @ vAA<- r0 6917 GOTO_OPCODE(ip) @ jump to next instruction 6918 /* 10-12 instructions */ 6919 6920 6921/* ------------------------------ */ 6922 .balign 64 6923.L_OP_OR_INT_LIT8: /* 0xde */ 6924/* File: armv5te/OP_OR_INT_LIT8.S */ 6925/* File: armv5te/binopLit8.S */ 6926 /* 6927 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6928 * that specifies an instruction that performs "result = r0 op r1". 6929 * This could be an ARM instruction or a function call. (If the result 6930 * comes back in a register other than r0, you can override "result".) 6931 * 6932 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6933 * vCC (r1). Useful for integer division and modulus. 6934 * 6935 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6936 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6937 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6938 */ 6939 /* binop/lit8 vAA, vBB, #+CC */ 6940 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6941 mov r9, rINST, lsr #8 @ r9<- AA 6942 and r2, r3, #255 @ r2<- BB 6943 GET_VREG(r0, r2) @ r0<- vBB 6944 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6945 .if 0 6946 @cmp r1, #0 @ is second operand zero? 6947 beq common_errDivideByZero 6948 .endif 6949 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6950 6951 @ optional op; may set condition codes 6952 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6953 GET_INST_OPCODE(ip) @ extract opcode from rINST 6954 SET_VREG(r0, r9) @ vAA<- r0 6955 GOTO_OPCODE(ip) @ jump to next instruction 6956 /* 10-12 instructions */ 6957 6958 6959/* ------------------------------ */ 6960 .balign 64 6961.L_OP_XOR_INT_LIT8: /* 0xdf */ 6962/* File: armv5te/OP_XOR_INT_LIT8.S */ 6963/* File: armv5te/binopLit8.S */ 6964 /* 6965 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6966 * that specifies an instruction that performs "result = r0 op r1". 6967 * This could be an ARM instruction or a function call. (If the result 6968 * comes back in a register other than r0, you can override "result".) 6969 * 6970 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6971 * vCC (r1). Useful for integer division and modulus. 6972 * 6973 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6974 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6975 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6976 */ 6977 /* binop/lit8 vAA, vBB, #+CC */ 6978 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6979 mov r9, rINST, lsr #8 @ r9<- AA 6980 and r2, r3, #255 @ r2<- BB 6981 GET_VREG(r0, r2) @ r0<- vBB 6982 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6983 .if 0 6984 @cmp r1, #0 @ is second operand zero? 6985 beq common_errDivideByZero 6986 .endif 6987 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6988 6989 @ optional op; may set condition codes 6990 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6991 GET_INST_OPCODE(ip) @ extract opcode from rINST 6992 SET_VREG(r0, r9) @ vAA<- r0 6993 GOTO_OPCODE(ip) @ jump to next instruction 6994 /* 10-12 instructions */ 6995 6996 6997/* ------------------------------ */ 6998 .balign 64 6999.L_OP_SHL_INT_LIT8: /* 0xe0 */ 7000/* File: armv5te/OP_SHL_INT_LIT8.S */ 7001/* File: armv5te/binopLit8.S */ 7002 /* 7003 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7004 * that specifies an instruction that performs "result = r0 op r1". 7005 * This could be an ARM instruction or a function call. (If the result 7006 * comes back in a register other than r0, you can override "result".) 7007 * 7008 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7009 * vCC (r1). Useful for integer division and modulus. 7010 * 7011 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7012 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7013 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7014 */ 7015 /* binop/lit8 vAA, vBB, #+CC */ 7016 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7017 mov r9, rINST, lsr #8 @ r9<- AA 7018 and r2, r3, #255 @ r2<- BB 7019 GET_VREG(r0, r2) @ r0<- vBB 7020 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7021 .if 0 7022 @cmp r1, #0 @ is second operand zero? 7023 beq common_errDivideByZero 7024 .endif 7025 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7026 7027 and r1, r1, #31 @ optional op; may set condition codes 7028 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 7029 GET_INST_OPCODE(ip) @ extract opcode from rINST 7030 SET_VREG(r0, r9) @ vAA<- r0 7031 GOTO_OPCODE(ip) @ jump to next instruction 7032 /* 10-12 instructions */ 7033 7034 7035/* ------------------------------ */ 7036 .balign 64 7037.L_OP_SHR_INT_LIT8: /* 0xe1 */ 7038/* File: armv5te/OP_SHR_INT_LIT8.S */ 7039/* File: armv5te/binopLit8.S */ 7040 /* 7041 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7042 * that specifies an instruction that performs "result = r0 op r1". 7043 * This could be an ARM instruction or a function call. (If the result 7044 * comes back in a register other than r0, you can override "result".) 7045 * 7046 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7047 * vCC (r1). Useful for integer division and modulus. 7048 * 7049 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7050 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7051 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7052 */ 7053 /* binop/lit8 vAA, vBB, #+CC */ 7054 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7055 mov r9, rINST, lsr #8 @ r9<- AA 7056 and r2, r3, #255 @ r2<- BB 7057 GET_VREG(r0, r2) @ r0<- vBB 7058 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7059 .if 0 7060 @cmp r1, #0 @ is second operand zero? 7061 beq common_errDivideByZero 7062 .endif 7063 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7064 7065 and r1, r1, #31 @ optional op; may set condition codes 7066 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7067 GET_INST_OPCODE(ip) @ extract opcode from rINST 7068 SET_VREG(r0, r9) @ vAA<- r0 7069 GOTO_OPCODE(ip) @ jump to next instruction 7070 /* 10-12 instructions */ 7071 7072 7073/* ------------------------------ */ 7074 .balign 64 7075.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7076/* File: armv5te/OP_USHR_INT_LIT8.S */ 7077/* File: armv5te/binopLit8.S */ 7078 /* 7079 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7080 * that specifies an instruction that performs "result = r0 op r1". 7081 * This could be an ARM instruction or a function call. (If the result 7082 * comes back in a register other than r0, you can override "result".) 7083 * 7084 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7085 * vCC (r1). Useful for integer division and modulus. 7086 * 7087 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7088 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7089 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7090 */ 7091 /* binop/lit8 vAA, vBB, #+CC */ 7092 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7093 mov r9, rINST, lsr #8 @ r9<- AA 7094 and r2, r3, #255 @ r2<- BB 7095 GET_VREG(r0, r2) @ r0<- vBB 7096 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7097 .if 0 7098 @cmp r1, #0 @ is second operand zero? 7099 beq common_errDivideByZero 7100 .endif 7101 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7102 7103 and r1, r1, #31 @ optional op; may set condition codes 7104 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7105 GET_INST_OPCODE(ip) @ extract opcode from rINST 7106 SET_VREG(r0, r9) @ vAA<- r0 7107 GOTO_OPCODE(ip) @ jump to next instruction 7108 /* 10-12 instructions */ 7109 7110 7111/* ------------------------------ */ 7112 .balign 64 7113.L_OP_IGET_VOLATILE: /* 0xe3 */ 7114/* File: armv5te/OP_IGET_VOLATILE.S */ 7115/* File: armv5te/OP_IGET.S */ 7116 /* 7117 * General 32-bit instance field get. 7118 * 7119 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7120 */ 7121 /* op vA, vB, field@CCCC */ 7122 mov r0, rINST, lsr #12 @ r0<- B 7123 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7124 FETCH(r1, 1) @ r1<- field ref CCCC 7125 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7126 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7127 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7128 cmp r0, #0 @ is resolved entry null? 7129 bne .LOP_IGET_VOLATILE_finish @ no, already resolved 71308: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7131 EXPORT_PC() @ resolve() could throw 7132 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7133 bl dvmResolveInstField @ r0<- resolved InstField ptr 7134 cmp r0, #0 7135 bne .LOP_IGET_VOLATILE_finish 7136 b common_exceptionThrown 7137 7138 7139/* ------------------------------ */ 7140 .balign 64 7141.L_OP_IPUT_VOLATILE: /* 0xe4 */ 7142/* File: armv5te/OP_IPUT_VOLATILE.S */ 7143/* File: armv5te/OP_IPUT.S */ 7144 /* 7145 * General 32-bit instance field put. 7146 * 7147 * for: iput, iput-boolean, iput-byte, iput-char, iput-short 7148 */ 7149 /* op vA, vB, field@CCCC */ 7150 mov r0, rINST, lsr #12 @ r0<- B 7151 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7152 FETCH(r1, 1) @ r1<- field ref CCCC 7153 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7154 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7155 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7156 cmp r0, #0 @ is resolved entry null? 7157 bne .LOP_IPUT_VOLATILE_finish @ no, already resolved 71588: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7159 EXPORT_PC() @ resolve() could throw 7160 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7161 bl dvmResolveInstField @ r0<- resolved InstField ptr 7162 cmp r0, #0 @ success? 7163 bne .LOP_IPUT_VOLATILE_finish @ yes, finish up 7164 b common_exceptionThrown 7165 7166 7167/* ------------------------------ */ 7168 .balign 64 7169.L_OP_SGET_VOLATILE: /* 0xe5 */ 7170/* File: armv5te/OP_SGET_VOLATILE.S */ 7171/* File: armv5te/OP_SGET.S */ 7172 /* 7173 * General 32-bit SGET handler. 7174 * 7175 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7176 */ 7177 /* op vAA, field@BBBB */ 7178 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7179 FETCH(r1, 1) @ r1<- field ref BBBB 7180 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7181 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7182 cmp r0, #0 @ is resolved entry null? 7183 beq .LOP_SGET_VOLATILE_resolve @ yes, do resolve 7184.LOP_SGET_VOLATILE_finish: @ field ptr in r0 7185 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7186 SMP_DMB @ acquiring load 7187 mov r2, rINST, lsr #8 @ r2<- AA 7188 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7189 SET_VREG(r1, r2) @ fp[AA]<- r1 7190 GET_INST_OPCODE(ip) @ extract opcode from rINST 7191 GOTO_OPCODE(ip) @ jump to next instruction 7192 7193 7194/* ------------------------------ */ 7195 .balign 64 7196.L_OP_SPUT_VOLATILE: /* 0xe6 */ 7197/* File: armv5te/OP_SPUT_VOLATILE.S */ 7198/* File: armv5te/OP_SPUT.S */ 7199 /* 7200 * General 32-bit SPUT handler. 7201 * 7202 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 7203 */ 7204 /* op vAA, field@BBBB */ 7205 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7206 FETCH(r1, 1) @ r1<- field ref BBBB 7207 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7208 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7209 cmp r0, #0 @ is resolved entry null? 7210 beq .LOP_SPUT_VOLATILE_resolve @ yes, do resolve 7211.LOP_SPUT_VOLATILE_finish: @ field ptr in r0 7212 mov r2, rINST, lsr #8 @ r2<- AA 7213 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7214 GET_VREG(r1, r2) @ r1<- fp[AA] 7215 GET_INST_OPCODE(ip) @ extract opcode from rINST 7216 SMP_DMB @ releasing store 7217 str r1, [r0, #offStaticField_value] @ field<- vAA 7218 GOTO_OPCODE(ip) @ jump to next instruction 7219 7220 7221/* ------------------------------ */ 7222 .balign 64 7223.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ 7224/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */ 7225/* File: armv5te/OP_IGET.S */ 7226 /* 7227 * General 32-bit instance field get. 7228 * 7229 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 7230 */ 7231 /* op vA, vB, field@CCCC */ 7232 mov r0, rINST, lsr #12 @ r0<- B 7233 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7234 FETCH(r1, 1) @ r1<- field ref CCCC 7235 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7236 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7237 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7238 cmp r0, #0 @ is resolved entry null? 7239 bne .LOP_IGET_OBJECT_VOLATILE_finish @ no, already resolved 72408: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7241 EXPORT_PC() @ resolve() could throw 7242 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7243 bl dvmResolveInstField @ r0<- resolved InstField ptr 7244 cmp r0, #0 7245 bne .LOP_IGET_OBJECT_VOLATILE_finish 7246 b common_exceptionThrown 7247 7248 7249/* ------------------------------ */ 7250 .balign 64 7251.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */ 7252/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */ 7253/* File: armv5te/OP_IGET_WIDE.S */ 7254 /* 7255 * Wide 32-bit instance field get. 7256 */ 7257 /* iget-wide vA, vB, field@CCCC */ 7258 mov r0, rINST, lsr #12 @ r0<- B 7259 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7260 FETCH(r1, 1) @ r1<- field ref CCCC 7261 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7262 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7263 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7264 cmp r0, #0 @ is resolved entry null? 7265 bne .LOP_IGET_WIDE_VOLATILE_finish @ no, already resolved 72668: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7267 EXPORT_PC() @ resolve() could throw 7268 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7269 bl dvmResolveInstField @ r0<- resolved InstField ptr 7270 cmp r0, #0 7271 bne .LOP_IGET_WIDE_VOLATILE_finish 7272 b common_exceptionThrown 7273 7274 7275/* ------------------------------ */ 7276 .balign 64 7277.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */ 7278/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */ 7279/* File: armv5te/OP_IPUT_WIDE.S */ 7280 /* iput-wide vA, vB, field@CCCC */ 7281 mov r0, rINST, lsr #12 @ r0<- B 7282 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7283 FETCH(r1, 1) @ r1<- field ref CCCC 7284 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7285 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7286 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7287 cmp r0, #0 @ is resolved entry null? 7288 bne .LOP_IPUT_WIDE_VOLATILE_finish @ no, already resolved 72898: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7290 EXPORT_PC() @ resolve() could throw 7291 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7292 bl dvmResolveInstField @ r0<- resolved InstField ptr 7293 cmp r0, #0 @ success? 7294 bne .LOP_IPUT_WIDE_VOLATILE_finish @ yes, finish up 7295 b common_exceptionThrown 7296 7297 7298/* ------------------------------ */ 7299 .balign 64 7300.L_OP_SGET_WIDE_VOLATILE: /* 0xea */ 7301/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */ 7302/* File: armv5te/OP_SGET_WIDE.S */ 7303 /* 7304 * 64-bit SGET handler. 7305 */ 7306 /* sget-wide vAA, field@BBBB */ 7307 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7308 FETCH(r1, 1) @ r1<- field ref BBBB 7309 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7310 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7311 cmp r0, #0 @ is resolved entry null? 7312 beq .LOP_SGET_WIDE_VOLATILE_resolve @ yes, do resolve 7313.LOP_SGET_WIDE_VOLATILE_finish: 7314 mov r9, rINST, lsr #8 @ r9<- AA 7315 .if 1 7316 add r0, r0, #offStaticField_value @ r0<- pointer to data 7317 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 7318 .else 7319 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 7320 .endif 7321 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7322 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7323 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 7324 GET_INST_OPCODE(ip) @ extract opcode from rINST 7325 GOTO_OPCODE(ip) @ jump to next instruction 7326 7327 7328/* ------------------------------ */ 7329 .balign 64 7330.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */ 7331/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */ 7332/* File: armv5te/OP_SPUT_WIDE.S */ 7333 /* 7334 * 64-bit SPUT handler. 7335 */ 7336 /* sput-wide vAA, field@BBBB */ 7337 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 7338 FETCH(r1, 1) @ r1<- field ref BBBB 7339 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 7340 mov r9, rINST, lsr #8 @ r9<- AA 7341 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 7342 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7343 cmp r2, #0 @ is resolved entry null? 7344 beq .LOP_SPUT_WIDE_VOLATILE_resolve @ yes, do resolve 7345.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9 7346 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7347 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 7348 GET_INST_OPCODE(r10) @ extract opcode from rINST 7349 .if 1 7350 add r2, r2, #offStaticField_value @ r2<- pointer to data 7351 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 7352 .else 7353 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 7354 .endif 7355 GOTO_OPCODE(r10) @ jump to next instruction 7356 7357 7358/* ------------------------------ */ 7359 .balign 64 7360.L_OP_BREAKPOINT: /* 0xec */ 7361/* File: armv5te/OP_BREAKPOINT.S */ 7362/* File: armv5te/unused.S */ 7363 bl common_abort 7364 7365 7366/* ------------------------------ */ 7367 .balign 64 7368.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7369/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7370 /* 7371 * Handle a throw-verification-error instruction. This throws an 7372 * exception for an error discovered during verification. The 7373 * exception is indicated by AA, with some detail provided by BBBB. 7374 */ 7375 /* op AA, ref@BBBB */ 7376 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7377 FETCH(r2, 1) @ r2<- BBBB 7378 EXPORT_PC() @ export the PC 7379 mov r1, rINST, lsr #8 @ r1<- AA 7380 bl dvmThrowVerificationError @ always throws 7381 b common_exceptionThrown @ handle exception 7382 7383/* ------------------------------ */ 7384 .balign 64 7385.L_OP_EXECUTE_INLINE: /* 0xee */ 7386/* File: armv5te/OP_EXECUTE_INLINE.S */ 7387 /* 7388 * Execute a "native inline" instruction. 7389 * 7390 * We need to call an InlineOp4Func: 7391 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7392 * 7393 * The first four args are in r0-r3, pointer to return value storage 7394 * is on the stack. The function's return value is a flag that tells 7395 * us if an exception was thrown. 7396 */ 7397 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7398 FETCH(r10, 1) @ r10<- BBBB 7399 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7400 EXPORT_PC() @ can throw 7401 sub sp, sp, #8 @ make room for arg, +64 bit align 7402 mov r0, rINST, lsr #12 @ r0<- B 7403 str r1, [sp] @ push &glue->retval 7404 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7405 add sp, sp, #8 @ pop stack 7406 cmp r0, #0 @ test boolean result of inline 7407 beq common_exceptionThrown @ returned false, handle exception 7408 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7409 GET_INST_OPCODE(ip) @ extract opcode from rINST 7410 GOTO_OPCODE(ip) @ jump to next instruction 7411 7412/* ------------------------------ */ 7413 .balign 64 7414.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ 7415/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */ 7416 /* 7417 * Execute a "native inline" instruction, using "/range" semantics. 7418 * Same idea as execute-inline, but we get the args differently. 7419 * 7420 * We need to call an InlineOp4Func: 7421 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7422 * 7423 * The first four args are in r0-r3, pointer to return value storage 7424 * is on the stack. The function's return value is a flag that tells 7425 * us if an exception was thrown. 7426 */ 7427 /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */ 7428 FETCH(r10, 1) @ r10<- BBBB 7429 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7430 EXPORT_PC() @ can throw 7431 sub sp, sp, #8 @ make room for arg, +64 bit align 7432 mov r0, rINST, lsr #8 @ r0<- AA 7433 str r1, [sp] @ push &glue->retval 7434 bl .LOP_EXECUTE_INLINE_RANGE_continue @ make call; will return after 7435 add sp, sp, #8 @ pop stack 7436 cmp r0, #0 @ test boolean result of inline 7437 beq common_exceptionThrown @ returned false, handle exception 7438 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7439 GET_INST_OPCODE(ip) @ extract opcode from rINST 7440 GOTO_OPCODE(ip) @ jump to next instruction 7441 7442/* ------------------------------ */ 7443 .balign 64 7444.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7445/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7446 /* 7447 * invoke-direct-empty is a no-op in a "standard" interpreter. 7448 */ 7449 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7450 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7451 GOTO_OPCODE(ip) @ execute it 7452 7453/* ------------------------------ */ 7454 .balign 64 7455.L_OP_RETURN_VOID_BARRIER: /* 0xf1 */ 7456/* File: armv5te/OP_RETURN_VOID_BARRIER.S */ 7457 SMP_DMB @ TODO: want "DMB ST" 7458 b common_returnFromMethod 7459 7460/* ------------------------------ */ 7461 .balign 64 7462.L_OP_IGET_QUICK: /* 0xf2 */ 7463/* File: armv5te/OP_IGET_QUICK.S */ 7464 /* For: iget-quick, iget-object-quick */ 7465 /* op vA, vB, offset@CCCC */ 7466 mov r2, rINST, lsr #12 @ r2<- B 7467 GET_VREG(r3, r2) @ r3<- object we're operating on 7468 FETCH(r1, 1) @ r1<- field byte offset 7469 cmp r3, #0 @ check object for null 7470 mov r2, rINST, lsr #8 @ r2<- A(+) 7471 beq common_errNullObject @ object was null 7472 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7473 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7474 and r2, r2, #15 7475 GET_INST_OPCODE(ip) @ extract opcode from rINST 7476 SET_VREG(r0, r2) @ fp[A]<- r0 7477 GOTO_OPCODE(ip) @ jump to next instruction 7478 7479/* ------------------------------ */ 7480 .balign 64 7481.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7482/* File: armv5te/OP_IGET_WIDE_QUICK.S */ 7483 /* iget-wide-quick vA, vB, offset@CCCC */ 7484 mov r2, rINST, lsr #12 @ r2<- B 7485 GET_VREG(r3, r2) @ r3<- object we're operating on 7486 FETCH(ip, 1) @ ip<- field byte offset 7487 cmp r3, #0 @ check object for null 7488 mov r2, rINST, lsr #8 @ r2<- A(+) 7489 beq common_errNullObject @ object was null 7490 ldrd r0, [r3, ip] @ r0<- obj.field (64 bits, aligned) 7491 and r2, r2, #15 7492 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7493 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7494 GET_INST_OPCODE(ip) @ extract opcode from rINST 7495 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7496 GOTO_OPCODE(ip) @ jump to next instruction 7497 7498/* ------------------------------ */ 7499 .balign 64 7500.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7501/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7502/* File: armv5te/OP_IGET_QUICK.S */ 7503 /* For: iget-quick, iget-object-quick */ 7504 /* op vA, vB, offset@CCCC */ 7505 mov r2, rINST, lsr #12 @ r2<- B 7506 GET_VREG(r3, r2) @ r3<- object we're operating on 7507 FETCH(r1, 1) @ r1<- field byte offset 7508 cmp r3, #0 @ check object for null 7509 mov r2, rINST, lsr #8 @ r2<- A(+) 7510 beq common_errNullObject @ object was null 7511 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7512 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7513 and r2, r2, #15 7514 GET_INST_OPCODE(ip) @ extract opcode from rINST 7515 SET_VREG(r0, r2) @ fp[A]<- r0 7516 GOTO_OPCODE(ip) @ jump to next instruction 7517 7518 7519/* ------------------------------ */ 7520 .balign 64 7521.L_OP_IPUT_QUICK: /* 0xf5 */ 7522/* File: armv5te/OP_IPUT_QUICK.S */ 7523 /* For: iput-quick */ 7524 /* op vA, vB, offset@CCCC */ 7525 mov r2, rINST, lsr #12 @ r2<- B 7526 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7527 FETCH(r1, 1) @ r1<- field byte offset 7528 cmp r3, #0 @ check object for null 7529 mov r2, rINST, lsr #8 @ r2<- A(+) 7530 beq common_errNullObject @ object was null 7531 and r2, r2, #15 7532 GET_VREG(r0, r2) @ r0<- fp[A] 7533 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7534 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7535 GET_INST_OPCODE(ip) @ extract opcode from rINST 7536 GOTO_OPCODE(ip) @ jump to next instruction 7537 7538/* ------------------------------ */ 7539 .balign 64 7540.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7541/* File: armv5te/OP_IPUT_WIDE_QUICK.S */ 7542 /* iput-wide-quick vA, vB, offset@CCCC */ 7543 mov r0, rINST, lsr #8 @ r0<- A(+) 7544 mov r1, rINST, lsr #12 @ r1<- B 7545 and r0, r0, #15 7546 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7547 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7548 cmp r2, #0 @ check object for null 7549 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7550 beq common_errNullObject @ object was null 7551 FETCH(r3, 1) @ r3<- field byte offset 7552 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7553 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7554 GET_INST_OPCODE(ip) @ extract opcode from rINST 7555 GOTO_OPCODE(ip) @ jump to next instruction 7556 7557/* ------------------------------ */ 7558 .balign 64 7559.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7560/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7561 /* For: iput-object-quick */ 7562 /* op vA, vB, offset@CCCC */ 7563 mov r2, rINST, lsr #12 @ r2<- B 7564 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7565 FETCH(r1, 1) @ r1<- field byte offset 7566 cmp r3, #0 @ check object for null 7567 mov r2, rINST, lsr #8 @ r2<- A(+) 7568 beq common_errNullObject @ object was null 7569 and r2, r2, #15 7570 GET_VREG(r0, r2) @ r0<- fp[A] 7571 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 7572 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7573 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7574 cmp r0, #0 7575 strneb r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card on non-null store 7576 GET_INST_OPCODE(ip) @ extract opcode from rINST 7577 GOTO_OPCODE(ip) @ jump to next instruction 7578 7579/* ------------------------------ */ 7580 .balign 64 7581.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7582/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7583 /* 7584 * Handle an optimized virtual method call. 7585 * 7586 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7587 */ 7588 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7589 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7590 FETCH(r3, 2) @ r3<- FEDC or CCCC 7591 FETCH(r1, 1) @ r1<- BBBB 7592 .if (!0) 7593 and r3, r3, #15 @ r3<- C (or stays CCCC) 7594 .endif 7595 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7596 cmp r2, #0 @ is "this" null? 7597 beq common_errNullObject @ null "this", throw exception 7598 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7599 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7600 EXPORT_PC() @ invoke must export 7601 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7602 bl common_invokeMethodNoRange @ continue on 7603 7604/* ------------------------------ */ 7605 .balign 64 7606.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7607/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7608/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7609 /* 7610 * Handle an optimized virtual method call. 7611 * 7612 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7613 */ 7614 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7615 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7616 FETCH(r3, 2) @ r3<- FEDC or CCCC 7617 FETCH(r1, 1) @ r1<- BBBB 7618 .if (!1) 7619 and r3, r3, #15 @ r3<- C (or stays CCCC) 7620 .endif 7621 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7622 cmp r2, #0 @ is "this" null? 7623 beq common_errNullObject @ null "this", throw exception 7624 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7625 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7626 EXPORT_PC() @ invoke must export 7627 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7628 bl common_invokeMethodRange @ continue on 7629 7630 7631/* ------------------------------ */ 7632 .balign 64 7633.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7634/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7635 /* 7636 * Handle an optimized "super" method call. 7637 * 7638 * for: [opt] invoke-super-quick, invoke-super-quick/range 7639 */ 7640 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7641 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7642 FETCH(r10, 2) @ r10<- GFED or CCCC 7643 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7644 .if (!0) 7645 and r10, r10, #15 @ r10<- D (or stays CCCC) 7646 .endif 7647 FETCH(r1, 1) @ r1<- BBBB 7648 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7649 EXPORT_PC() @ must export for invoke 7650 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7651 GET_VREG(r3, r10) @ r3<- "this" 7652 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7653 cmp r3, #0 @ null "this" ref? 7654 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7655 beq common_errNullObject @ "this" is null, throw exception 7656 bl common_invokeMethodNoRange @ continue on 7657 7658/* ------------------------------ */ 7659 .balign 64 7660.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7661/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7662/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7663 /* 7664 * Handle an optimized "super" method call. 7665 * 7666 * for: [opt] invoke-super-quick, invoke-super-quick/range 7667 */ 7668 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7669 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7670 FETCH(r10, 2) @ r10<- GFED or CCCC 7671 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7672 .if (!1) 7673 and r10, r10, #15 @ r10<- D (or stays CCCC) 7674 .endif 7675 FETCH(r1, 1) @ r1<- BBBB 7676 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7677 EXPORT_PC() @ must export for invoke 7678 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7679 GET_VREG(r3, r10) @ r3<- "this" 7680 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7681 cmp r3, #0 @ null "this" ref? 7682 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7683 beq common_errNullObject @ "this" is null, throw exception 7684 bl common_invokeMethodRange @ continue on 7685 7686 7687/* ------------------------------ */ 7688 .balign 64 7689.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ 7690/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */ 7691/* File: armv5te/OP_IPUT_OBJECT.S */ 7692 /* 7693 * 32-bit instance field put. 7694 * 7695 * for: iput-object, iput-object-volatile 7696 */ 7697 /* op vA, vB, field@CCCC */ 7698 mov r0, rINST, lsr #12 @ r0<- B 7699 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7700 FETCH(r1, 1) @ r1<- field ref CCCC 7701 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7702 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7703 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7704 cmp r0, #0 @ is resolved entry null? 7705 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ no, already resolved 77068: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7707 EXPORT_PC() @ resolve() could throw 7708 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7709 bl dvmResolveInstField @ r0<- resolved InstField ptr 7710 cmp r0, #0 @ success? 7711 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ yes, finish up 7712 b common_exceptionThrown 7713 7714 7715/* ------------------------------ */ 7716 .balign 64 7717.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ 7718/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */ 7719/* File: armv5te/OP_SGET.S */ 7720 /* 7721 * General 32-bit SGET handler. 7722 * 7723 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7724 */ 7725 /* op vAA, field@BBBB */ 7726 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7727 FETCH(r1, 1) @ r1<- field ref BBBB 7728 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7729 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7730 cmp r0, #0 @ is resolved entry null? 7731 beq .LOP_SGET_OBJECT_VOLATILE_resolve @ yes, do resolve 7732.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0 7733 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7734 SMP_DMB @ acquiring load 7735 mov r2, rINST, lsr #8 @ r2<- AA 7736 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7737 SET_VREG(r1, r2) @ fp[AA]<- r1 7738 GET_INST_OPCODE(ip) @ extract opcode from rINST 7739 GOTO_OPCODE(ip) @ jump to next instruction 7740 7741 7742/* ------------------------------ */ 7743 .balign 64 7744.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ 7745/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */ 7746/* File: armv5te/OP_SPUT_OBJECT.S */ 7747 /* 7748 * 32-bit SPUT handler for objects 7749 * 7750 * for: sput-object, sput-object-volatile 7751 */ 7752 /* op vAA, field@BBBB */ 7753 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7754 FETCH(r1, 1) @ r1<- field ref BBBB 7755 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7756 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7757 cmp r0, #0 @ is resolved entry null? 7758 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ no, continue 7759 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7760 EXPORT_PC() @ resolve() could throw, so export now 7761 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7762 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 7763 cmp r0, #0 @ success? 7764 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish 7765 b common_exceptionThrown @ no, handle exception 7766 7767 7768 7769/* ------------------------------ */ 7770 .balign 64 7771.L_OP_UNUSED_FF: /* 0xff */ 7772/* File: armv5te/OP_UNUSED_FF.S */ 7773/* File: armv5te/unused.S */ 7774 bl common_abort 7775 7776 7777 7778 .balign 64 7779 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7780 .global dvmAsmInstructionEnd 7781dvmAsmInstructionEnd: 7782 7783/* 7784 * =========================================================================== 7785 * Sister implementations 7786 * =========================================================================== 7787 */ 7788 .global dvmAsmSisterStart 7789 .type dvmAsmSisterStart, %function 7790 .text 7791 .balign 4 7792dvmAsmSisterStart: 7793 7794/* continuation for OP_CONST_STRING */ 7795 7796 /* 7797 * Continuation if the String has not yet been resolved. 7798 * r1: BBBB (String ref) 7799 * r9: target register 7800 */ 7801.LOP_CONST_STRING_resolve: 7802 EXPORT_PC() 7803 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7804 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7805 bl dvmResolveString @ r0<- String reference 7806 cmp r0, #0 @ failed? 7807 beq common_exceptionThrown @ yup, handle the exception 7808 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7809 GET_INST_OPCODE(ip) @ extract opcode from rINST 7810 SET_VREG(r0, r9) @ vAA<- r0 7811 GOTO_OPCODE(ip) @ jump to next instruction 7812 7813/* continuation for OP_CONST_STRING_JUMBO */ 7814 7815 /* 7816 * Continuation if the String has not yet been resolved. 7817 * r1: BBBBBBBB (String ref) 7818 * r9: target register 7819 */ 7820.LOP_CONST_STRING_JUMBO_resolve: 7821 EXPORT_PC() 7822 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7823 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7824 bl dvmResolveString @ r0<- String reference 7825 cmp r0, #0 @ failed? 7826 beq common_exceptionThrown @ yup, handle the exception 7827 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7828 GET_INST_OPCODE(ip) @ extract opcode from rINST 7829 SET_VREG(r0, r9) @ vAA<- r0 7830 GOTO_OPCODE(ip) @ jump to next instruction 7831 7832/* continuation for OP_CONST_CLASS */ 7833 7834 /* 7835 * Continuation if the Class has not yet been resolved. 7836 * r1: BBBB (Class ref) 7837 * r9: target register 7838 */ 7839.LOP_CONST_CLASS_resolve: 7840 EXPORT_PC() 7841 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7842 mov r2, #1 @ r2<- true 7843 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7844 bl dvmResolveClass @ r0<- Class reference 7845 cmp r0, #0 @ failed? 7846 beq common_exceptionThrown @ yup, handle the exception 7847 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7848 GET_INST_OPCODE(ip) @ extract opcode from rINST 7849 SET_VREG(r0, r9) @ vAA<- r0 7850 GOTO_OPCODE(ip) @ jump to next instruction 7851 7852/* continuation for OP_CHECK_CAST */ 7853 7854 /* 7855 * Trivial test failed, need to perform full check. This is common. 7856 * r0 holds obj->clazz 7857 * r1 holds class resolved from BBBB 7858 * r9 holds object 7859 */ 7860.LOP_CHECK_CAST_fullcheck: 7861 bl dvmInstanceofNonTrivial @ r0<- boolean result 7862 cmp r0, #0 @ failed? 7863 bne .LOP_CHECK_CAST_okay @ no, success 7864 7865 @ A cast has failed. We need to throw a ClassCastException with the 7866 @ class of the object that failed to be cast. 7867 EXPORT_PC() @ about to throw 7868 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 7869 ldr r0, .LstrClassCastExceptionPtr 7870 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 7871 bl dvmThrowExceptionWithClassMessage 7872 b common_exceptionThrown 7873 7874 /* 7875 * Resolution required. This is the least-likely path. 7876 * 7877 * r2 holds BBBB 7878 * r9 holds object 7879 */ 7880.LOP_CHECK_CAST_resolve: 7881 EXPORT_PC() @ resolve() could throw 7882 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7883 mov r1, r2 @ r1<- BBBB 7884 mov r2, #0 @ r2<- false 7885 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7886 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7887 cmp r0, #0 @ got null? 7888 beq common_exceptionThrown @ yes, handle exception 7889 mov r1, r0 @ r1<- class resolved from BBB 7890 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7891 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7892 7893.LstrClassCastExceptionPtr: 7894 .word .LstrClassCastException 7895 7896/* continuation for OP_INSTANCE_OF */ 7897 7898 /* 7899 * Trivial test failed, need to perform full check. This is common. 7900 * r0 holds obj->clazz 7901 * r1 holds class resolved from BBBB 7902 * r9 holds A 7903 */ 7904.LOP_INSTANCE_OF_fullcheck: 7905 bl dvmInstanceofNonTrivial @ r0<- boolean result 7906 @ fall through to OP_INSTANCE_OF_store 7907 7908 /* 7909 * r0 holds boolean result 7910 * r9 holds A 7911 */ 7912.LOP_INSTANCE_OF_store: 7913 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7914 SET_VREG(r0, r9) @ vA<- r0 7915 GET_INST_OPCODE(ip) @ extract opcode from rINST 7916 GOTO_OPCODE(ip) @ jump to next instruction 7917 7918 /* 7919 * Trivial test succeeded, save and bail. 7920 * r9 holds A 7921 */ 7922.LOP_INSTANCE_OF_trivial: 7923 mov r0, #1 @ indicate success 7924 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7925 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7926 SET_VREG(r0, r9) @ vA<- r0 7927 GET_INST_OPCODE(ip) @ extract opcode from rINST 7928 GOTO_OPCODE(ip) @ jump to next instruction 7929 7930 /* 7931 * Resolution required. This is the least-likely path. 7932 * 7933 * r3 holds BBBB 7934 * r9 holds A 7935 */ 7936.LOP_INSTANCE_OF_resolve: 7937 EXPORT_PC() @ resolve() could throw 7938 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7939 mov r1, r3 @ r1<- BBBB 7940 mov r2, #1 @ r2<- true 7941 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7942 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7943 cmp r0, #0 @ got null? 7944 beq common_exceptionThrown @ yes, handle exception 7945 mov r1, r0 @ r1<- class resolved from BBB 7946 mov r3, rINST, lsr #12 @ r3<- B 7947 GET_VREG(r0, r3) @ r0<- vB (object) 7948 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7949 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7950 7951/* continuation for OP_NEW_INSTANCE */ 7952 7953 .balign 32 @ minimize cache lines 7954.LOP_NEW_INSTANCE_finish: @ r0=new object 7955 mov r3, rINST, lsr #8 @ r3<- AA 7956 cmp r0, #0 @ failed? 7957 beq common_exceptionThrown @ yes, handle the exception 7958 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7959 GET_INST_OPCODE(ip) @ extract opcode from rINST 7960 SET_VREG(r0, r3) @ vAA<- r0 7961 GOTO_OPCODE(ip) @ jump to next instruction 7962 7963 /* 7964 * Class initialization required. 7965 * 7966 * r0 holds class object 7967 */ 7968.LOP_NEW_INSTANCE_needinit: 7969 mov r9, r0 @ save r0 7970 bl dvmInitClass @ initialize class 7971 cmp r0, #0 @ check boolean result 7972 mov r0, r9 @ restore r0 7973 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7974 b common_exceptionThrown @ failed, deal with init exception 7975 7976 /* 7977 * Resolution required. This is the least-likely path. 7978 * 7979 * r1 holds BBBB 7980 */ 7981.LOP_NEW_INSTANCE_resolve: 7982 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7983 mov r2, #0 @ r2<- false 7984 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7985 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7986 cmp r0, #0 @ got null? 7987 bne .LOP_NEW_INSTANCE_resolved @ no, continue 7988 b common_exceptionThrown @ yes, handle exception 7989 7990.LstrInstantiationErrorPtr: 7991 .word .LstrInstantiationError 7992 7993/* continuation for OP_NEW_ARRAY */ 7994 7995 7996 /* 7997 * Resolve class. (This is an uncommon case.) 7998 * 7999 * r1 holds array length 8000 * r2 holds class ref CCCC 8001 */ 8002.LOP_NEW_ARRAY_resolve: 8003 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8004 mov r9, r1 @ r9<- length (save) 8005 mov r1, r2 @ r1<- CCCC 8006 mov r2, #0 @ r2<- false 8007 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8008 bl dvmResolveClass @ r0<- call(clazz, ref) 8009 cmp r0, #0 @ got null? 8010 mov r1, r9 @ r1<- length (restore) 8011 beq common_exceptionThrown @ yes, handle exception 8012 @ fall through to OP_NEW_ARRAY_finish 8013 8014 /* 8015 * Finish allocation. 8016 * 8017 * r0 holds class 8018 * r1 holds array length 8019 */ 8020.LOP_NEW_ARRAY_finish: 8021 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 8022 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 8023 cmp r0, #0 @ failed? 8024 mov r2, rINST, lsr #8 @ r2<- A+ 8025 beq common_exceptionThrown @ yes, handle the exception 8026 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8027 and r2, r2, #15 @ r2<- A 8028 GET_INST_OPCODE(ip) @ extract opcode from rINST 8029 SET_VREG(r0, r2) @ vA<- r0 8030 GOTO_OPCODE(ip) @ jump to next instruction 8031 8032/* continuation for OP_FILLED_NEW_ARRAY */ 8033 8034 /* 8035 * On entry: 8036 * r0 holds array class 8037 * r10 holds AA or BA 8038 */ 8039.LOP_FILLED_NEW_ARRAY_continue: 8040 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8041 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8042 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 8043 .if 0 8044 mov r1, r10 @ r1<- AA (length) 8045 .else 8046 mov r1, r10, lsr #4 @ r1<- B (length) 8047 .endif 8048 cmp rINST, #'I' @ array of ints? 8049 cmpne rINST, #'L' @ array of objects? 8050 cmpne rINST, #'[' @ array of arrays? 8051 mov r9, r1 @ save length in r9 8052 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 8053 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8054 cmp r0, #0 @ null return? 8055 beq common_exceptionThrown @ alloc failed, handle exception 8056 8057 FETCH(r1, 2) @ r1<- FEDC or CCCC 8058 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8059 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 8060 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8061 subs r9, r9, #1 @ length--, check for neg 8062 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8063 bmi 2f @ was zero, bail 8064 8065 @ copy values from registers into the array 8066 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8067 .if 0 8068 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 80691: ldr r3, [r2], #4 @ r3<- *r2++ 8070 subs r9, r9, #1 @ count-- 8071 str r3, [r0], #4 @ *contents++ = vX 8072 bpl 1b 8073 @ continue at 2 8074 .else 8075 cmp r9, #4 @ length was initially 5? 8076 and r2, r10, #15 @ r2<- A 8077 bne 1f @ <= 4 args, branch 8078 GET_VREG(r3, r2) @ r3<- vA 8079 sub r9, r9, #1 @ count-- 8080 str r3, [r0, #16] @ contents[4] = vA 80811: and r2, r1, #15 @ r2<- F/E/D/C 8082 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8083 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8084 subs r9, r9, #1 @ count-- 8085 str r3, [r0], #4 @ *contents++ = vX 8086 bpl 1b 8087 @ continue at 2 8088 .endif 8089 80902: 8091 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 8092 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 8093 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8094 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8095 cmp r1, #'I' @ Is int array? 8096 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card if not 8097 GOTO_OPCODE(ip) @ execute it 8098 8099 /* 8100 * Throw an exception indicating that we have not implemented this 8101 * mode of filled-new-array. 8102 */ 8103.LOP_FILLED_NEW_ARRAY_notimpl: 8104 ldr r0, .L_strInternalError 8105 ldr r1, .L_strFilledNewArrayNotImpl 8106 bl dvmThrowException 8107 b common_exceptionThrown 8108 8109 .if (!0) @ define in one or the other, not both 8110.L_strFilledNewArrayNotImpl: 8111 .word .LstrFilledNewArrayNotImpl 8112.L_strInternalError: 8113 .word .LstrInternalError 8114 .endif 8115 8116/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 8117 8118 /* 8119 * On entry: 8120 * r0 holds array class 8121 * r10 holds AA or BA 8122 */ 8123.LOP_FILLED_NEW_ARRAY_RANGE_continue: 8124 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8125 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8126 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 8127 .if 1 8128 mov r1, r10 @ r1<- AA (length) 8129 .else 8130 mov r1, r10, lsr #4 @ r1<- B (length) 8131 .endif 8132 cmp rINST, #'I' @ array of ints? 8133 cmpne rINST, #'L' @ array of objects? 8134 cmpne rINST, #'[' @ array of arrays? 8135 mov r9, r1 @ save length in r9 8136 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 8137 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8138 cmp r0, #0 @ null return? 8139 beq common_exceptionThrown @ alloc failed, handle exception 8140 8141 FETCH(r1, 2) @ r1<- FEDC or CCCC 8142 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8143 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 8144 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8145 subs r9, r9, #1 @ length--, check for neg 8146 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8147 bmi 2f @ was zero, bail 8148 8149 @ copy values from registers into the array 8150 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8151 .if 1 8152 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 81531: ldr r3, [r2], #4 @ r3<- *r2++ 8154 subs r9, r9, #1 @ count-- 8155 str r3, [r0], #4 @ *contents++ = vX 8156 bpl 1b 8157 @ continue at 2 8158 .else 8159 cmp r9, #4 @ length was initially 5? 8160 and r2, r10, #15 @ r2<- A 8161 bne 1f @ <= 4 args, branch 8162 GET_VREG(r3, r2) @ r3<- vA 8163 sub r9, r9, #1 @ count-- 8164 str r3, [r0, #16] @ contents[4] = vA 81651: and r2, r1, #15 @ r2<- F/E/D/C 8166 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8167 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8168 subs r9, r9, #1 @ count-- 8169 str r3, [r0], #4 @ *contents++ = vX 8170 bpl 1b 8171 @ continue at 2 8172 .endif 8173 81742: 8175 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 8176 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 8177 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8178 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8179 cmp r1, #'I' @ Is int array? 8180 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card if not 8181 GOTO_OPCODE(ip) @ execute it 8182 8183 /* 8184 * Throw an exception indicating that we have not implemented this 8185 * mode of filled-new-array. 8186 */ 8187.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8188 ldr r0, .L_strInternalError 8189 ldr r1, .L_strFilledNewArrayNotImpl 8190 bl dvmThrowException 8191 b common_exceptionThrown 8192 8193 .if (!1) @ define in one or the other, not both 8194.L_strFilledNewArrayNotImpl: 8195 .word .LstrFilledNewArrayNotImpl 8196.L_strInternalError: 8197 .word .LstrInternalError 8198 .endif 8199 8200/* continuation for OP_CMPL_FLOAT */ 8201.LOP_CMPL_FLOAT_finish: 8202 SET_VREG(r0, r9) @ vAA<- r0 8203 GOTO_OPCODE(ip) @ jump to next instruction 8204 8205/* continuation for OP_CMPG_FLOAT */ 8206.LOP_CMPG_FLOAT_finish: 8207 SET_VREG(r0, r9) @ vAA<- r0 8208 GOTO_OPCODE(ip) @ jump to next instruction 8209 8210/* continuation for OP_CMPL_DOUBLE */ 8211.LOP_CMPL_DOUBLE_finish: 8212 SET_VREG(r0, r9) @ vAA<- r0 8213 GOTO_OPCODE(ip) @ jump to next instruction 8214 8215/* continuation for OP_CMPG_DOUBLE */ 8216.LOP_CMPG_DOUBLE_finish: 8217 SET_VREG(r0, r9) @ vAA<- r0 8218 GOTO_OPCODE(ip) @ jump to next instruction 8219 8220/* continuation for OP_CMP_LONG */ 8221 8222.LOP_CMP_LONG_less: 8223 mvn r1, #0 @ r1<- -1 8224 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8225 @ instead, we just replicate the tail end. 8226 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8227 SET_VREG(r1, r9) @ vAA<- r1 8228 GET_INST_OPCODE(ip) @ extract opcode from rINST 8229 GOTO_OPCODE(ip) @ jump to next instruction 8230 8231.LOP_CMP_LONG_greater: 8232 mov r1, #1 @ r1<- 1 8233 @ fall through to _finish 8234 8235.LOP_CMP_LONG_finish: 8236 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8237 SET_VREG(r1, r9) @ vAA<- r1 8238 GET_INST_OPCODE(ip) @ extract opcode from rINST 8239 GOTO_OPCODE(ip) @ jump to next instruction 8240 8241/* continuation for OP_AGET_WIDE */ 8242 8243.LOP_AGET_WIDE_finish: 8244 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8245 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8246 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8247 GET_INST_OPCODE(ip) @ extract opcode from rINST 8248 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8249 GOTO_OPCODE(ip) @ jump to next instruction 8250 8251/* continuation for OP_APUT_WIDE */ 8252 8253.LOP_APUT_WIDE_finish: 8254 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8255 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8256 GET_INST_OPCODE(ip) @ extract opcode from rINST 8257 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8258 GOTO_OPCODE(ip) @ jump to next instruction 8259 8260/* continuation for OP_APUT_OBJECT */ 8261 /* 8262 * On entry: 8263 * r1 = vBB (arrayObj) 8264 * r9 = vAA (obj) 8265 * r10 = offset into array (vBB + vCC * width) 8266 */ 8267.LOP_APUT_OBJECT_finish: 8268 cmp r9, #0 @ storing null reference? 8269 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8270 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8271 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz 8272 bl dvmCanPutArrayElement @ test object type vs. array type 8273 cmp r0, #0 @ okay? 8274 beq common_errArrayStore @ no 8275 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8276 ldr r2, [rGLUE, #offGlue_cardTable] @ get biased CT base 8277 add r10, #offArrayObject_contents @ r0<- pointer to slot 8278 GET_INST_OPCODE(ip) @ extract opcode from rINST 8279 str r9, [r10] @ vBB[vCC]<- vAA 8280 strb r2, [r2, r10, lsr #GC_CARD_SHIFT] @ mark card 8281 GOTO_OPCODE(ip) @ jump to next instruction 8282.LOP_APUT_OBJECT_skip_check: 8283 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8284 GET_INST_OPCODE(ip) @ extract opcode from rINST 8285 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8286 GOTO_OPCODE(ip) @ jump to next instruction 8287 8288/* continuation for OP_IGET */ 8289 8290 /* 8291 * Currently: 8292 * r0 holds resolved field 8293 * r9 holds object 8294 */ 8295.LOP_IGET_finish: 8296 @bl common_squeak0 8297 cmp r9, #0 @ check object for null 8298 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8299 beq common_errNullObject @ object was null 8300 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8301 @ no-op @ acquiring load 8302 mov r2, rINST, lsr #8 @ r2<- A+ 8303 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8304 and r2, r2, #15 @ r2<- A 8305 GET_INST_OPCODE(ip) @ extract opcode from rINST 8306 SET_VREG(r0, r2) @ fp[A]<- r0 8307 GOTO_OPCODE(ip) @ jump to next instruction 8308 8309/* continuation for OP_IGET_WIDE */ 8310 8311 /* 8312 * Currently: 8313 * r0 holds resolved field 8314 * r9 holds object 8315 */ 8316.LOP_IGET_WIDE_finish: 8317 cmp r9, #0 @ check object for null 8318 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8319 beq common_errNullObject @ object was null 8320 .if 0 8321 add r0, r9, r3 @ r0<- address of field 8322 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 8323 .else 8324 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8325 .endif 8326 mov r2, rINST, lsr #8 @ r2<- A+ 8327 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8328 and r2, r2, #15 @ r2<- A 8329 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8330 GET_INST_OPCODE(ip) @ extract opcode from rINST 8331 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8332 GOTO_OPCODE(ip) @ jump to next instruction 8333 8334/* continuation for OP_IGET_OBJECT */ 8335 8336 /* 8337 * Currently: 8338 * r0 holds resolved field 8339 * r9 holds object 8340 */ 8341.LOP_IGET_OBJECT_finish: 8342 @bl common_squeak0 8343 cmp r9, #0 @ check object for null 8344 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8345 beq common_errNullObject @ object was null 8346 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8347 @ no-op @ acquiring load 8348 mov r2, rINST, lsr #8 @ r2<- A+ 8349 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8350 and r2, r2, #15 @ r2<- A 8351 GET_INST_OPCODE(ip) @ extract opcode from rINST 8352 SET_VREG(r0, r2) @ fp[A]<- r0 8353 GOTO_OPCODE(ip) @ jump to next instruction 8354 8355/* continuation for OP_IGET_BOOLEAN */ 8356 8357 /* 8358 * Currently: 8359 * r0 holds resolved field 8360 * r9 holds object 8361 */ 8362.LOP_IGET_BOOLEAN_finish: 8363 @bl common_squeak1 8364 cmp r9, #0 @ check object for null 8365 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8366 beq common_errNullObject @ object was null 8367 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8368 @ no-op @ acquiring load 8369 mov r2, rINST, lsr #8 @ r2<- A+ 8370 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8371 and r2, r2, #15 @ r2<- A 8372 GET_INST_OPCODE(ip) @ extract opcode from rINST 8373 SET_VREG(r0, r2) @ fp[A]<- r0 8374 GOTO_OPCODE(ip) @ jump to next instruction 8375 8376/* continuation for OP_IGET_BYTE */ 8377 8378 /* 8379 * Currently: 8380 * r0 holds resolved field 8381 * r9 holds object 8382 */ 8383.LOP_IGET_BYTE_finish: 8384 @bl common_squeak2 8385 cmp r9, #0 @ check object for null 8386 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8387 beq common_errNullObject @ object was null 8388 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8389 @ no-op @ acquiring load 8390 mov r2, rINST, lsr #8 @ r2<- A+ 8391 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8392 and r2, r2, #15 @ r2<- A 8393 GET_INST_OPCODE(ip) @ extract opcode from rINST 8394 SET_VREG(r0, r2) @ fp[A]<- r0 8395 GOTO_OPCODE(ip) @ jump to next instruction 8396 8397/* continuation for OP_IGET_CHAR */ 8398 8399 /* 8400 * Currently: 8401 * r0 holds resolved field 8402 * r9 holds object 8403 */ 8404.LOP_IGET_CHAR_finish: 8405 @bl common_squeak3 8406 cmp r9, #0 @ check object for null 8407 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8408 beq common_errNullObject @ object was null 8409 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8410 @ no-op @ acquiring load 8411 mov r2, rINST, lsr #8 @ r2<- A+ 8412 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8413 and r2, r2, #15 @ r2<- A 8414 GET_INST_OPCODE(ip) @ extract opcode from rINST 8415 SET_VREG(r0, r2) @ fp[A]<- r0 8416 GOTO_OPCODE(ip) @ jump to next instruction 8417 8418/* continuation for OP_IGET_SHORT */ 8419 8420 /* 8421 * Currently: 8422 * r0 holds resolved field 8423 * r9 holds object 8424 */ 8425.LOP_IGET_SHORT_finish: 8426 @bl common_squeak4 8427 cmp r9, #0 @ check object for null 8428 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8429 beq common_errNullObject @ object was null 8430 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8431 @ no-op @ acquiring load 8432 mov r2, rINST, lsr #8 @ r2<- A+ 8433 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8434 and r2, r2, #15 @ r2<- A 8435 GET_INST_OPCODE(ip) @ extract opcode from rINST 8436 SET_VREG(r0, r2) @ fp[A]<- r0 8437 GOTO_OPCODE(ip) @ jump to next instruction 8438 8439/* continuation for OP_IPUT */ 8440 8441 /* 8442 * Currently: 8443 * r0 holds resolved field 8444 * r9 holds object 8445 */ 8446.LOP_IPUT_finish: 8447 @bl common_squeak0 8448 mov r1, rINST, lsr #8 @ r1<- A+ 8449 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8450 and r1, r1, #15 @ r1<- A 8451 cmp r9, #0 @ check object for null 8452 GET_VREG(r0, r1) @ r0<- fp[A] 8453 beq common_errNullObject @ object was null 8454 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8455 GET_INST_OPCODE(ip) @ extract opcode from rINST 8456 @ no-op @ releasing store 8457 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8458 GOTO_OPCODE(ip) @ jump to next instruction 8459 8460/* continuation for OP_IPUT_WIDE */ 8461 8462 /* 8463 * Currently: 8464 * r0 holds resolved field 8465 * r9 holds object 8466 */ 8467.LOP_IPUT_WIDE_finish: 8468 mov r2, rINST, lsr #8 @ r2<- A+ 8469 cmp r9, #0 @ check object for null 8470 and r2, r2, #15 @ r2<- A 8471 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8472 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8473 beq common_errNullObject @ object was null 8474 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8475 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8476 GET_INST_OPCODE(r10) @ extract opcode from rINST 8477 .if 0 8478 add r2, r9, r3 @ r2<- target address 8479 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 8480 .else 8481 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 8482 .endif 8483 GOTO_OPCODE(r10) @ jump to next instruction 8484 8485/* continuation for OP_IPUT_OBJECT */ 8486 8487 /* 8488 * Currently: 8489 * r0 holds resolved field 8490 * r9 holds object 8491 */ 8492.LOP_IPUT_OBJECT_finish: 8493 @bl common_squeak0 8494 mov r1, rINST, lsr #8 @ r1<- A+ 8495 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8496 and r1, r1, #15 @ r1<- A 8497 cmp r9, #0 @ check object for null 8498 GET_VREG(r0, r1) @ r0<- fp[A] 8499 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8500 beq common_errNullObject @ object was null 8501 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8502 add r9, r3 @ r9<- direct ptr to target location 8503 GET_INST_OPCODE(ip) @ extract opcode from rINST 8504 @ no-op @ releasing store 8505 str r0, [r9] @ obj.field (8/16/32 bits)<- r0 8506 cmp r0, #0 @ stored a null reference? 8507 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 8508 GOTO_OPCODE(ip) @ jump to next instruction 8509 8510/* continuation for OP_IPUT_BOOLEAN */ 8511 8512 /* 8513 * Currently: 8514 * r0 holds resolved field 8515 * r9 holds object 8516 */ 8517.LOP_IPUT_BOOLEAN_finish: 8518 @bl common_squeak1 8519 mov r1, rINST, lsr #8 @ r1<- A+ 8520 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8521 and r1, r1, #15 @ r1<- A 8522 cmp r9, #0 @ check object for null 8523 GET_VREG(r0, r1) @ r0<- fp[A] 8524 beq common_errNullObject @ object was null 8525 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8526 GET_INST_OPCODE(ip) @ extract opcode from rINST 8527 @ no-op @ releasing store 8528 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8529 GOTO_OPCODE(ip) @ jump to next instruction 8530 8531/* continuation for OP_IPUT_BYTE */ 8532 8533 /* 8534 * Currently: 8535 * r0 holds resolved field 8536 * r9 holds object 8537 */ 8538.LOP_IPUT_BYTE_finish: 8539 @bl common_squeak2 8540 mov r1, rINST, lsr #8 @ r1<- A+ 8541 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8542 and r1, r1, #15 @ r1<- A 8543 cmp r9, #0 @ check object for null 8544 GET_VREG(r0, r1) @ r0<- fp[A] 8545 beq common_errNullObject @ object was null 8546 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8547 GET_INST_OPCODE(ip) @ extract opcode from rINST 8548 @ no-op @ releasing store 8549 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8550 GOTO_OPCODE(ip) @ jump to next instruction 8551 8552/* continuation for OP_IPUT_CHAR */ 8553 8554 /* 8555 * Currently: 8556 * r0 holds resolved field 8557 * r9 holds object 8558 */ 8559.LOP_IPUT_CHAR_finish: 8560 @bl common_squeak3 8561 mov r1, rINST, lsr #8 @ r1<- A+ 8562 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8563 and r1, r1, #15 @ r1<- A 8564 cmp r9, #0 @ check object for null 8565 GET_VREG(r0, r1) @ r0<- fp[A] 8566 beq common_errNullObject @ object was null 8567 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8568 GET_INST_OPCODE(ip) @ extract opcode from rINST 8569 @ no-op @ releasing store 8570 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8571 GOTO_OPCODE(ip) @ jump to next instruction 8572 8573/* continuation for OP_IPUT_SHORT */ 8574 8575 /* 8576 * Currently: 8577 * r0 holds resolved field 8578 * r9 holds object 8579 */ 8580.LOP_IPUT_SHORT_finish: 8581 @bl common_squeak4 8582 mov r1, rINST, lsr #8 @ r1<- A+ 8583 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8584 and r1, r1, #15 @ r1<- A 8585 cmp r9, #0 @ check object for null 8586 GET_VREG(r0, r1) @ r0<- fp[A] 8587 beq common_errNullObject @ object was null 8588 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8589 GET_INST_OPCODE(ip) @ extract opcode from rINST 8590 @ no-op @ releasing store 8591 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8592 GOTO_OPCODE(ip) @ jump to next instruction 8593 8594/* continuation for OP_SGET */ 8595 8596 /* 8597 * Continuation if the field has not yet been resolved. 8598 * r1: BBBB field ref 8599 */ 8600.LOP_SGET_resolve: 8601 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8602 EXPORT_PC() @ resolve() could throw, so export now 8603 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8604 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8605 cmp r0, #0 @ success? 8606 bne .LOP_SGET_finish @ yes, finish 8607 b common_exceptionThrown @ no, handle exception 8608 8609/* continuation for OP_SGET_WIDE */ 8610 8611 /* 8612 * Continuation if the field has not yet been resolved. 8613 * r1: BBBB field ref 8614 * 8615 * Returns StaticField pointer in r0. 8616 */ 8617.LOP_SGET_WIDE_resolve: 8618 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8619 EXPORT_PC() @ resolve() could throw, so export now 8620 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8621 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8622 cmp r0, #0 @ success? 8623 bne .LOP_SGET_WIDE_finish @ yes, finish 8624 b common_exceptionThrown @ no, handle exception 8625 8626/* continuation for OP_SGET_OBJECT */ 8627 8628 /* 8629 * Continuation if the field has not yet been resolved. 8630 * r1: BBBB field ref 8631 */ 8632.LOP_SGET_OBJECT_resolve: 8633 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8634 EXPORT_PC() @ resolve() could throw, so export now 8635 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8636 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8637 cmp r0, #0 @ success? 8638 bne .LOP_SGET_OBJECT_finish @ yes, finish 8639 b common_exceptionThrown @ no, handle exception 8640 8641/* continuation for OP_SGET_BOOLEAN */ 8642 8643 /* 8644 * Continuation if the field has not yet been resolved. 8645 * r1: BBBB field ref 8646 */ 8647.LOP_SGET_BOOLEAN_resolve: 8648 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8649 EXPORT_PC() @ resolve() could throw, so export now 8650 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8651 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8652 cmp r0, #0 @ success? 8653 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8654 b common_exceptionThrown @ no, handle exception 8655 8656/* continuation for OP_SGET_BYTE */ 8657 8658 /* 8659 * Continuation if the field has not yet been resolved. 8660 * r1: BBBB field ref 8661 */ 8662.LOP_SGET_BYTE_resolve: 8663 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8664 EXPORT_PC() @ resolve() could throw, so export now 8665 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8666 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8667 cmp r0, #0 @ success? 8668 bne .LOP_SGET_BYTE_finish @ yes, finish 8669 b common_exceptionThrown @ no, handle exception 8670 8671/* continuation for OP_SGET_CHAR */ 8672 8673 /* 8674 * Continuation if the field has not yet been resolved. 8675 * r1: BBBB field ref 8676 */ 8677.LOP_SGET_CHAR_resolve: 8678 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8679 EXPORT_PC() @ resolve() could throw, so export now 8680 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8681 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8682 cmp r0, #0 @ success? 8683 bne .LOP_SGET_CHAR_finish @ yes, finish 8684 b common_exceptionThrown @ no, handle exception 8685 8686/* continuation for OP_SGET_SHORT */ 8687 8688 /* 8689 * Continuation if the field has not yet been resolved. 8690 * r1: BBBB field ref 8691 */ 8692.LOP_SGET_SHORT_resolve: 8693 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8694 EXPORT_PC() @ resolve() could throw, so export now 8695 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8696 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8697 cmp r0, #0 @ success? 8698 bne .LOP_SGET_SHORT_finish @ yes, finish 8699 b common_exceptionThrown @ no, handle exception 8700 8701/* continuation for OP_SPUT */ 8702 8703 /* 8704 * Continuation if the field has not yet been resolved. 8705 * r1: BBBB field ref 8706 */ 8707.LOP_SPUT_resolve: 8708 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8709 EXPORT_PC() @ resolve() could throw, so export now 8710 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8711 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8712 cmp r0, #0 @ success? 8713 bne .LOP_SPUT_finish @ yes, finish 8714 b common_exceptionThrown @ no, handle exception 8715 8716/* continuation for OP_SPUT_WIDE */ 8717 8718 /* 8719 * Continuation if the field has not yet been resolved. 8720 * r1: BBBB field ref 8721 * r9: &fp[AA] 8722 * 8723 * Returns StaticField pointer in r2. 8724 */ 8725.LOP_SPUT_WIDE_resolve: 8726 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8727 EXPORT_PC() @ resolve() could throw, so export now 8728 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8729 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8730 cmp r0, #0 @ success? 8731 mov r2, r0 @ copy to r2 8732 bne .LOP_SPUT_WIDE_finish @ yes, finish 8733 b common_exceptionThrown @ no, handle exception 8734 8735/* continuation for OP_SPUT_OBJECT */ 8736.LOP_SPUT_OBJECT_finish: @ field ptr in r0 8737 mov r2, rINST, lsr #8 @ r2<- AA 8738 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8739 GET_VREG(r1, r2) @ r1<- fp[AA] 8740 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8741 GET_INST_OPCODE(ip) @ extract opcode from rINST 8742 add r0, #offStaticField_value @ r0<- pointer to store target 8743 @ no-op @ releasing store 8744 str r1, [r0] @ field<- vAA 8745 cmp r1, #0 @ stored a null object? 8746 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ mark card if not 8747 GOTO_OPCODE(ip) @ jump to next instruction 8748 8749/* continuation for OP_SPUT_BOOLEAN */ 8750 8751 /* 8752 * Continuation if the field has not yet been resolved. 8753 * r1: BBBB field ref 8754 */ 8755.LOP_SPUT_BOOLEAN_resolve: 8756 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8757 EXPORT_PC() @ resolve() could throw, so export now 8758 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8759 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8760 cmp r0, #0 @ success? 8761 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 8762 b common_exceptionThrown @ no, handle exception 8763 8764/* continuation for OP_SPUT_BYTE */ 8765 8766 /* 8767 * Continuation if the field has not yet been resolved. 8768 * r1: BBBB field ref 8769 */ 8770.LOP_SPUT_BYTE_resolve: 8771 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8772 EXPORT_PC() @ resolve() could throw, so export now 8773 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8774 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8775 cmp r0, #0 @ success? 8776 bne .LOP_SPUT_BYTE_finish @ yes, finish 8777 b common_exceptionThrown @ no, handle exception 8778 8779/* continuation for OP_SPUT_CHAR */ 8780 8781 /* 8782 * Continuation if the field has not yet been resolved. 8783 * r1: BBBB field ref 8784 */ 8785.LOP_SPUT_CHAR_resolve: 8786 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8787 EXPORT_PC() @ resolve() could throw, so export now 8788 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8789 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8790 cmp r0, #0 @ success? 8791 bne .LOP_SPUT_CHAR_finish @ yes, finish 8792 b common_exceptionThrown @ no, handle exception 8793 8794/* continuation for OP_SPUT_SHORT */ 8795 8796 /* 8797 * Continuation if the field has not yet been resolved. 8798 * r1: BBBB field ref 8799 */ 8800.LOP_SPUT_SHORT_resolve: 8801 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8802 EXPORT_PC() @ resolve() could throw, so export now 8803 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8804 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8805 cmp r0, #0 @ success? 8806 bne .LOP_SPUT_SHORT_finish @ yes, finish 8807 b common_exceptionThrown @ no, handle exception 8808 8809/* continuation for OP_INVOKE_VIRTUAL */ 8810 8811 /* 8812 * At this point: 8813 * r0 = resolved base method 8814 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8815 */ 8816.LOP_INVOKE_VIRTUAL_continue: 8817 GET_VREG(r1, r10) @ r1<- "this" ptr 8818 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8819 cmp r1, #0 @ is "this" null? 8820 beq common_errNullObject @ null "this", throw exception 8821 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8822 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8823 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8824 bl common_invokeMethodNoRange @ continue on 8825 8826/* continuation for OP_INVOKE_SUPER */ 8827 8828 /* 8829 * At this point: 8830 * r0 = resolved base method 8831 * r9 = method->clazz 8832 */ 8833.LOP_INVOKE_SUPER_continue: 8834 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8835 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8836 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8837 EXPORT_PC() @ must export for invoke 8838 cmp r2, r3 @ compare (methodIndex, vtableCount) 8839 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 8840 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8841 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8842 bl common_invokeMethodNoRange @ continue on 8843 8844.LOP_INVOKE_SUPER_resolve: 8845 mov r0, r9 @ r0<- method->clazz 8846 mov r2, #METHOD_VIRTUAL @ resolver method type 8847 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8848 cmp r0, #0 @ got null? 8849 bne .LOP_INVOKE_SUPER_continue @ no, continue 8850 b common_exceptionThrown @ yes, handle exception 8851 8852 /* 8853 * Throw a NoSuchMethodError with the method name as the message. 8854 * r0 = resolved base method 8855 */ 8856.LOP_INVOKE_SUPER_nsm: 8857 ldr r1, [r0, #offMethod_name] @ r1<- method name 8858 b common_errNoSuchMethod 8859 8860/* continuation for OP_INVOKE_DIRECT */ 8861 8862 /* 8863 * On entry: 8864 * r1 = reference (BBBB or CCCC) 8865 * r10 = "this" register 8866 */ 8867.LOP_INVOKE_DIRECT_resolve: 8868 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8869 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8870 mov r2, #METHOD_DIRECT @ resolver method type 8871 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8872 cmp r0, #0 @ got null? 8873 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8874 bne .LOP_INVOKE_DIRECT_finish @ no, continue 8875 b common_exceptionThrown @ yes, handle exception 8876 8877/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 8878 8879 /* 8880 * At this point: 8881 * r0 = resolved base method 8882 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8883 */ 8884.LOP_INVOKE_VIRTUAL_RANGE_continue: 8885 GET_VREG(r1, r10) @ r1<- "this" ptr 8886 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8887 cmp r1, #0 @ is "this" null? 8888 beq common_errNullObject @ null "this", throw exception 8889 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8890 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8891 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8892 bl common_invokeMethodRange @ continue on 8893 8894/* continuation for OP_INVOKE_SUPER_RANGE */ 8895 8896 /* 8897 * At this point: 8898 * r0 = resolved base method 8899 * r9 = method->clazz 8900 */ 8901.LOP_INVOKE_SUPER_RANGE_continue: 8902 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8903 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8904 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8905 EXPORT_PC() @ must export for invoke 8906 cmp r2, r3 @ compare (methodIndex, vtableCount) 8907 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 8908 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8909 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8910 bl common_invokeMethodRange @ continue on 8911 8912.LOP_INVOKE_SUPER_RANGE_resolve: 8913 mov r0, r9 @ r0<- method->clazz 8914 mov r2, #METHOD_VIRTUAL @ resolver method type 8915 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8916 cmp r0, #0 @ got null? 8917 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 8918 b common_exceptionThrown @ yes, handle exception 8919 8920 /* 8921 * Throw a NoSuchMethodError with the method name as the message. 8922 * r0 = resolved base method 8923 */ 8924.LOP_INVOKE_SUPER_RANGE_nsm: 8925 ldr r1, [r0, #offMethod_name] @ r1<- method name 8926 b common_errNoSuchMethod 8927 8928/* continuation for OP_INVOKE_DIRECT_RANGE */ 8929 8930 /* 8931 * On entry: 8932 * r1 = reference (BBBB or CCCC) 8933 * r10 = "this" register 8934 */ 8935.LOP_INVOKE_DIRECT_RANGE_resolve: 8936 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8937 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8938 mov r2, #METHOD_DIRECT @ resolver method type 8939 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8940 cmp r0, #0 @ got null? 8941 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8942 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 8943 b common_exceptionThrown @ yes, handle exception 8944 8945/* continuation for OP_FLOAT_TO_LONG */ 8946/* 8947 * Convert the float in r0 to a long in r0/r1. 8948 * 8949 * We have to clip values to long min/max per the specification. The 8950 * expected common case is a "reasonable" value that converts directly 8951 * to modest integer. The EABI convert function isn't doing this for us. 8952 */ 8953f2l_doconv: 8954 stmfd sp!, {r4, lr} 8955 mov r1, #0x5f000000 @ (float)maxlong 8956 mov r4, r0 8957 bl __aeabi_fcmpge @ is arg >= maxlong? 8958 cmp r0, #0 @ nonzero == yes 8959 mvnne r0, #0 @ return maxlong (7fffffff) 8960 mvnne r1, #0x80000000 8961 ldmnefd sp!, {r4, pc} 8962 8963 mov r0, r4 @ recover arg 8964 mov r1, #0xdf000000 @ (float)minlong 8965 bl __aeabi_fcmple @ is arg <= minlong? 8966 cmp r0, #0 @ nonzero == yes 8967 movne r0, #0 @ return minlong (80000000) 8968 movne r1, #0x80000000 8969 ldmnefd sp!, {r4, pc} 8970 8971 mov r0, r4 @ recover arg 8972 mov r1, r4 8973 bl __aeabi_fcmpeq @ is arg == self? 8974 cmp r0, #0 @ zero == no 8975 moveq r1, #0 @ return zero for NaN 8976 ldmeqfd sp!, {r4, pc} 8977 8978 mov r0, r4 @ recover arg 8979 bl __aeabi_f2lz @ convert float to long 8980 ldmfd sp!, {r4, pc} 8981 8982/* continuation for OP_DOUBLE_TO_LONG */ 8983/* 8984 * Convert the double in r0/r1 to a long in r0/r1. 8985 * 8986 * We have to clip values to long min/max per the specification. The 8987 * expected common case is a "reasonable" value that converts directly 8988 * to modest integer. The EABI convert function isn't doing this for us. 8989 */ 8990d2l_doconv: 8991 stmfd sp!, {r4, r5, lr} @ save regs 8992 mov r3, #0x43000000 @ maxlong, as a double (high word) 8993 add r3, #0x00e00000 @ 0x43e00000 8994 mov r2, #0 @ maxlong, as a double (low word) 8995 sub sp, sp, #4 @ align for EABI 8996 mov r4, r0 @ save a copy of r0 8997 mov r5, r1 @ and r1 8998 bl __aeabi_dcmpge @ is arg >= maxlong? 8999 cmp r0, #0 @ nonzero == yes 9000 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 9001 mvnne r1, #0x80000000 9002 bne 1f 9003 9004 mov r0, r4 @ recover arg 9005 mov r1, r5 9006 mov r3, #0xc3000000 @ minlong, as a double (high word) 9007 add r3, #0x00e00000 @ 0xc3e00000 9008 mov r2, #0 @ minlong, as a double (low word) 9009 bl __aeabi_dcmple @ is arg <= minlong? 9010 cmp r0, #0 @ nonzero == yes 9011 movne r0, #0 @ return minlong (8000000000000000) 9012 movne r1, #0x80000000 9013 bne 1f 9014 9015 mov r0, r4 @ recover arg 9016 mov r1, r5 9017 mov r2, r4 @ compare against self 9018 mov r3, r5 9019 bl __aeabi_dcmpeq @ is arg == self? 9020 cmp r0, #0 @ zero == no 9021 moveq r1, #0 @ return zero for NaN 9022 beq 1f 9023 9024 mov r0, r4 @ recover arg 9025 mov r1, r5 9026 bl __aeabi_d2lz @ convert double to long 9027 90281: 9029 add sp, sp, #4 9030 ldmfd sp!, {r4, r5, pc} 9031 9032/* continuation for OP_MUL_LONG */ 9033 9034.LOP_MUL_LONG_finish: 9035 GET_INST_OPCODE(ip) @ extract opcode from rINST 9036 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 9037 GOTO_OPCODE(ip) @ jump to next instruction 9038 9039/* continuation for OP_SHL_LONG */ 9040 9041.LOP_SHL_LONG_finish: 9042 mov r0, r0, asl r2 @ r0<- r0 << r2 9043 GET_INST_OPCODE(ip) @ extract opcode from rINST 9044 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9045 GOTO_OPCODE(ip) @ jump to next instruction 9046 9047/* continuation for OP_SHR_LONG */ 9048 9049.LOP_SHR_LONG_finish: 9050 mov r1, r1, asr r2 @ r1<- r1 >> r2 9051 GET_INST_OPCODE(ip) @ extract opcode from rINST 9052 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9053 GOTO_OPCODE(ip) @ jump to next instruction 9054 9055/* continuation for OP_USHR_LONG */ 9056 9057.LOP_USHR_LONG_finish: 9058 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 9059 GET_INST_OPCODE(ip) @ extract opcode from rINST 9060 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9061 GOTO_OPCODE(ip) @ jump to next instruction 9062 9063/* continuation for OP_SHL_LONG_2ADDR */ 9064 9065.LOP_SHL_LONG_2ADDR_finish: 9066 GET_INST_OPCODE(ip) @ extract opcode from rINST 9067 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9068 GOTO_OPCODE(ip) @ jump to next instruction 9069 9070/* continuation for OP_SHR_LONG_2ADDR */ 9071 9072.LOP_SHR_LONG_2ADDR_finish: 9073 GET_INST_OPCODE(ip) @ extract opcode from rINST 9074 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9075 GOTO_OPCODE(ip) @ jump to next instruction 9076 9077/* continuation for OP_USHR_LONG_2ADDR */ 9078 9079.LOP_USHR_LONG_2ADDR_finish: 9080 GET_INST_OPCODE(ip) @ extract opcode from rINST 9081 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9082 GOTO_OPCODE(ip) @ jump to next instruction 9083 9084/* continuation for OP_IGET_VOLATILE */ 9085 9086 /* 9087 * Currently: 9088 * r0 holds resolved field 9089 * r9 holds object 9090 */ 9091.LOP_IGET_VOLATILE_finish: 9092 @bl common_squeak0 9093 cmp r9, #0 @ check object for null 9094 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9095 beq common_errNullObject @ object was null 9096 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9097 SMP_DMB @ acquiring load 9098 mov r2, rINST, lsr #8 @ r2<- A+ 9099 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9100 and r2, r2, #15 @ r2<- A 9101 GET_INST_OPCODE(ip) @ extract opcode from rINST 9102 SET_VREG(r0, r2) @ fp[A]<- r0 9103 GOTO_OPCODE(ip) @ jump to next instruction 9104 9105/* continuation for OP_IPUT_VOLATILE */ 9106 9107 /* 9108 * Currently: 9109 * r0 holds resolved field 9110 * r9 holds object 9111 */ 9112.LOP_IPUT_VOLATILE_finish: 9113 @bl common_squeak0 9114 mov r1, rINST, lsr #8 @ r1<- A+ 9115 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9116 and r1, r1, #15 @ r1<- A 9117 cmp r9, #0 @ check object for null 9118 GET_VREG(r0, r1) @ r0<- fp[A] 9119 beq common_errNullObject @ object was null 9120 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9121 GET_INST_OPCODE(ip) @ extract opcode from rINST 9122 SMP_DMB @ releasing store 9123 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 9124 GOTO_OPCODE(ip) @ jump to next instruction 9125 9126/* continuation for OP_SGET_VOLATILE */ 9127 9128 /* 9129 * Continuation if the field has not yet been resolved. 9130 * r1: BBBB field ref 9131 */ 9132.LOP_SGET_VOLATILE_resolve: 9133 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9134 EXPORT_PC() @ resolve() could throw, so export now 9135 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9136 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9137 cmp r0, #0 @ success? 9138 bne .LOP_SGET_VOLATILE_finish @ yes, finish 9139 b common_exceptionThrown @ no, handle exception 9140 9141/* continuation for OP_SPUT_VOLATILE */ 9142 9143 /* 9144 * Continuation if the field has not yet been resolved. 9145 * r1: BBBB field ref 9146 */ 9147.LOP_SPUT_VOLATILE_resolve: 9148 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9149 EXPORT_PC() @ resolve() could throw, so export now 9150 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9151 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9152 cmp r0, #0 @ success? 9153 bne .LOP_SPUT_VOLATILE_finish @ yes, finish 9154 b common_exceptionThrown @ no, handle exception 9155 9156/* continuation for OP_IGET_OBJECT_VOLATILE */ 9157 9158 /* 9159 * Currently: 9160 * r0 holds resolved field 9161 * r9 holds object 9162 */ 9163.LOP_IGET_OBJECT_VOLATILE_finish: 9164 @bl common_squeak0 9165 cmp r9, #0 @ check object for null 9166 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9167 beq common_errNullObject @ object was null 9168 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9169 SMP_DMB @ acquiring load 9170 mov r2, rINST, lsr #8 @ r2<- A+ 9171 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9172 and r2, r2, #15 @ r2<- A 9173 GET_INST_OPCODE(ip) @ extract opcode from rINST 9174 SET_VREG(r0, r2) @ fp[A]<- r0 9175 GOTO_OPCODE(ip) @ jump to next instruction 9176 9177/* continuation for OP_IGET_WIDE_VOLATILE */ 9178 9179 /* 9180 * Currently: 9181 * r0 holds resolved field 9182 * r9 holds object 9183 */ 9184.LOP_IGET_WIDE_VOLATILE_finish: 9185 cmp r9, #0 @ check object for null 9186 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9187 beq common_errNullObject @ object was null 9188 .if 1 9189 add r0, r9, r3 @ r0<- address of field 9190 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 9191 .else 9192 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 9193 .endif 9194 mov r2, rINST, lsr #8 @ r2<- A+ 9195 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9196 and r2, r2, #15 @ r2<- A 9197 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 9198 GET_INST_OPCODE(ip) @ extract opcode from rINST 9199 stmia r3, {r0-r1} @ fp[A]<- r0/r1 9200 GOTO_OPCODE(ip) @ jump to next instruction 9201 9202/* continuation for OP_IPUT_WIDE_VOLATILE */ 9203 9204 /* 9205 * Currently: 9206 * r0 holds resolved field 9207 * r9 holds object 9208 */ 9209.LOP_IPUT_WIDE_VOLATILE_finish: 9210 mov r2, rINST, lsr #8 @ r2<- A+ 9211 cmp r9, #0 @ check object for null 9212 and r2, r2, #15 @ r2<- A 9213 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9214 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 9215 beq common_errNullObject @ object was null 9216 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9217 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 9218 GET_INST_OPCODE(r10) @ extract opcode from rINST 9219 .if 1 9220 add r2, r9, r3 @ r2<- target address 9221 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 9222 .else 9223 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 9224 .endif 9225 GOTO_OPCODE(r10) @ jump to next instruction 9226 9227/* continuation for OP_SGET_WIDE_VOLATILE */ 9228 9229 /* 9230 * Continuation if the field has not yet been resolved. 9231 * r1: BBBB field ref 9232 * 9233 * Returns StaticField pointer in r0. 9234 */ 9235.LOP_SGET_WIDE_VOLATILE_resolve: 9236 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9237 EXPORT_PC() @ resolve() could throw, so export now 9238 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9239 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9240 cmp r0, #0 @ success? 9241 bne .LOP_SGET_WIDE_VOLATILE_finish @ yes, finish 9242 b common_exceptionThrown @ no, handle exception 9243 9244/* continuation for OP_SPUT_WIDE_VOLATILE */ 9245 9246 /* 9247 * Continuation if the field has not yet been resolved. 9248 * r1: BBBB field ref 9249 * r9: &fp[AA] 9250 * 9251 * Returns StaticField pointer in r2. 9252 */ 9253.LOP_SPUT_WIDE_VOLATILE_resolve: 9254 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9255 EXPORT_PC() @ resolve() could throw, so export now 9256 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9257 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9258 cmp r0, #0 @ success? 9259 mov r2, r0 @ copy to r2 9260 bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish 9261 b common_exceptionThrown @ no, handle exception 9262 9263/* continuation for OP_EXECUTE_INLINE */ 9264 9265 /* 9266 * Extract args, call function. 9267 * r0 = #of args (0-4) 9268 * r10 = call index 9269 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9270 * 9271 * Other ideas: 9272 * - Use a jump table from the main piece to jump directly into the 9273 * AND/LDR pairs. Costs a data load, saves a branch. 9274 * - Have five separate pieces that do the loading, so we can work the 9275 * interleave a little better. Increases code size. 9276 */ 9277.LOP_EXECUTE_INLINE_continue: 9278 rsb r0, r0, #4 @ r0<- 4-r0 9279 FETCH(r9, 2) @ r9<- FEDC 9280 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9281 bl common_abort @ (skipped due to ARM prefetch) 92824: and ip, r9, #0xf000 @ isolate F 9283 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 92843: and ip, r9, #0x0f00 @ isolate E 9285 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 92862: and ip, r9, #0x00f0 @ isolate D 9287 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 92881: and ip, r9, #0x000f @ isolate C 9289 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 92900: 9291 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 9292 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9293 @ (not reached) 9294 9295.LOP_EXECUTE_INLINE_table: 9296 .word gDvmInlineOpsTable 9297 9298/* continuation for OP_EXECUTE_INLINE_RANGE */ 9299 9300 /* 9301 * Extract args, call function. 9302 * r0 = #of args (0-4) 9303 * r10 = call index 9304 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9305 */ 9306.LOP_EXECUTE_INLINE_RANGE_continue: 9307 rsb r0, r0, #4 @ r0<- 4-r0 9308 FETCH(r9, 2) @ r9<- CCCC 9309 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9310 bl common_abort @ (skipped due to ARM prefetch) 93114: add ip, r9, #3 @ base+3 9312 GET_VREG(r3, ip) @ r3<- vBase[3] 93133: add ip, r9, #2 @ base+2 9314 GET_VREG(r2, ip) @ r2<- vBase[2] 93152: add ip, r9, #1 @ base+1 9316 GET_VREG(r1, ip) @ r1<- vBase[1] 93171: add ip, r9, #0 @ (nop) 9318 GET_VREG(r0, ip) @ r0<- vBase[0] 93190: 9320 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation 9321 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9322 @ (not reached) 9323 9324.LOP_EXECUTE_INLINE_RANGE_table: 9325 .word gDvmInlineOpsTable 9326 9327/* continuation for OP_IPUT_OBJECT_VOLATILE */ 9328 9329 /* 9330 * Currently: 9331 * r0 holds resolved field 9332 * r9 holds object 9333 */ 9334.LOP_IPUT_OBJECT_VOLATILE_finish: 9335 @bl common_squeak0 9336 mov r1, rINST, lsr #8 @ r1<- A+ 9337 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9338 and r1, r1, #15 @ r1<- A 9339 cmp r9, #0 @ check object for null 9340 GET_VREG(r0, r1) @ r0<- fp[A] 9341 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 9342 beq common_errNullObject @ object was null 9343 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9344 add r9, r3 @ r9<- direct ptr to target location 9345 GET_INST_OPCODE(ip) @ extract opcode from rINST 9346 SMP_DMB @ releasing store 9347 str r0, [r9] @ obj.field (8/16/32 bits)<- r0 9348 cmp r0, #0 @ stored a null reference? 9349 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 9350 GOTO_OPCODE(ip) @ jump to next instruction 9351 9352/* continuation for OP_SGET_OBJECT_VOLATILE */ 9353 9354 /* 9355 * Continuation if the field has not yet been resolved. 9356 * r1: BBBB field ref 9357 */ 9358.LOP_SGET_OBJECT_VOLATILE_resolve: 9359 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9360 EXPORT_PC() @ resolve() could throw, so export now 9361 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9362 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9363 cmp r0, #0 @ success? 9364 bne .LOP_SGET_OBJECT_VOLATILE_finish @ yes, finish 9365 b common_exceptionThrown @ no, handle exception 9366 9367/* continuation for OP_SPUT_OBJECT_VOLATILE */ 9368.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0 9369 mov r2, rINST, lsr #8 @ r2<- AA 9370 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9371 GET_VREG(r1, r2) @ r1<- fp[AA] 9372 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 9373 GET_INST_OPCODE(ip) @ extract opcode from rINST 9374 add r0, #offStaticField_value @ r0<- pointer to store target 9375 SMP_DMB @ releasing store 9376 str r1, [r0] @ field<- vAA 9377 cmp r1, #0 @ stored a null object? 9378 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ mark card if not 9379 GOTO_OPCODE(ip) @ jump to next instruction 9380 9381 .size dvmAsmSisterStart, .-dvmAsmSisterStart 9382 .global dvmAsmSisterEnd 9383dvmAsmSisterEnd: 9384 9385/* File: armv5te/footer.S */ 9386 9387/* 9388 * =========================================================================== 9389 * Common subroutines and data 9390 * =========================================================================== 9391 */ 9392 9393 9394 9395 .text 9396 .align 2 9397 9398#if defined(WITH_JIT) 9399#if defined(WITH_SELF_VERIFICATION) 9400 .global dvmJitToInterpPunt 9401dvmJitToInterpPunt: 9402 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9403 mov r2,#kSVSPunt @ r2<- interpreter entry point 9404 mov r3, #0 9405 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9406 b jitSVShadowRunEnd @ doesn't return 9407 9408 .global dvmJitToInterpSingleStep 9409dvmJitToInterpSingleStep: 9410 str lr,[rGLUE,#offGlue_jitResumeNPC] 9411 str r1,[rGLUE,#offGlue_jitResumeDPC] 9412 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 9413 b jitSVShadowRunEnd @ doesn't return 9414 9415 .global dvmJitToInterpNoChainNoProfile 9416dvmJitToInterpNoChainNoProfile: 9417 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9418 mov r0,rPC @ pass our target PC 9419 mov r2,#kSVSNoProfile @ r2<- interpreter entry point 9420 mov r3, #0 @ 0 means !inJitCodeCache 9421 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land 9422 b jitSVShadowRunEnd @ doesn't return 9423 9424 .global dvmJitToInterpTraceSelectNoChain 9425dvmJitToInterpTraceSelectNoChain: 9426 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9427 mov r0,rPC @ pass our target PC 9428 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9429 mov r3, #0 @ 0 means !inJitCodeCache 9430 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9431 b jitSVShadowRunEnd @ doesn't return 9432 9433 .global dvmJitToInterpTraceSelect 9434dvmJitToInterpTraceSelect: 9435 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9436 ldr r0,[lr, #-1] @ pass our target PC 9437 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9438 mov r3, #0 @ 0 means !inJitCodeCache 9439 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9440 b jitSVShadowRunEnd @ doesn't return 9441 9442 .global dvmJitToInterpBackwardBranch 9443dvmJitToInterpBackwardBranch: 9444 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9445 ldr r0,[lr, #-1] @ pass our target PC 9446 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 9447 mov r3, #0 @ 0 means !inJitCodeCache 9448 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9449 b jitSVShadowRunEnd @ doesn't return 9450 9451 .global dvmJitToInterpNormal 9452dvmJitToInterpNormal: 9453 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9454 ldr r0,[lr, #-1] @ pass our target PC 9455 mov r2,#kSVSNormal @ r2<- interpreter entry point 9456 mov r3, #0 @ 0 means !inJitCodeCache 9457 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9458 b jitSVShadowRunEnd @ doesn't return 9459 9460 .global dvmJitToInterpNoChain 9461dvmJitToInterpNoChain: 9462 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9463 mov r0,rPC @ pass our target PC 9464 mov r2,#kSVSNoChain @ r2<- interpreter entry point 9465 mov r3, #0 @ 0 means !inJitCodeCache 9466 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9467 b jitSVShadowRunEnd @ doesn't return 9468#else 9469/* 9470 * Return from the translation cache to the interpreter when the compiler is 9471 * having issues translating/executing a Dalvik instruction. We have to skip 9472 * the code cache lookup otherwise it is possible to indefinitely bouce 9473 * between the interpreter and the code cache if the instruction that fails 9474 * to be compiled happens to be at a trace start. 9475 */ 9476 .global dvmJitToInterpPunt 9477dvmJitToInterpPunt: 9478 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9479 mov rPC, r0 9480#if defined(WITH_JIT_TUNING) 9481 mov r0,lr 9482 bl dvmBumpPunt; 9483#endif 9484 EXPORT_PC() 9485 mov r0, #0 9486 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9487 adrl rIBASE, dvmAsmInstructionStart 9488 FETCH_INST() 9489 GET_INST_OPCODE(ip) 9490 GOTO_OPCODE(ip) 9491 9492/* 9493 * Return to the interpreter to handle a single instruction. 9494 * On entry: 9495 * r0 <= PC 9496 * r1 <= PC of resume instruction 9497 * lr <= resume point in translation 9498 */ 9499 .global dvmJitToInterpSingleStep 9500dvmJitToInterpSingleStep: 9501 str lr,[rGLUE,#offGlue_jitResumeNPC] 9502 str r1,[rGLUE,#offGlue_jitResumeDPC] 9503 mov r1,#kInterpEntryInstr 9504 @ enum is 4 byte in aapcs-EABI 9505 str r1, [rGLUE, #offGlue_entryPoint] 9506 mov rPC,r0 9507 EXPORT_PC() 9508 9509 adrl rIBASE, dvmAsmInstructionStart 9510 mov r2,#kJitSingleStep @ Ask for single step and then revert 9511 str r2,[rGLUE,#offGlue_jitState] 9512 mov r1,#1 @ set changeInterp to bail to debug interp 9513 b common_gotoBail 9514 9515/* 9516 * Return from the translation cache and immediately request 9517 * a translation for the exit target. Commonly used for callees. 9518 */ 9519 .global dvmJitToInterpTraceSelectNoChain 9520dvmJitToInterpTraceSelectNoChain: 9521#if defined(WITH_JIT_TUNING) 9522 bl dvmBumpNoChain 9523#endif 9524 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9525 mov r0,rPC 9526 bl dvmJitGetCodeAddr @ Is there a translation? 9527 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9528 mov r1, rPC @ arg1 of translation may need this 9529 mov lr, #0 @ in case target is HANDLER_INTERPRET 9530 cmp r0,#0 @ !0 means translation exists 9531 bxne r0 @ continue native execution if so 9532 b 2f @ branch over to use the interpreter 9533 9534/* 9535 * Return from the translation cache and immediately request 9536 * a translation for the exit target. Commonly used following 9537 * invokes. 9538 */ 9539 .global dvmJitToInterpTraceSelect 9540dvmJitToInterpTraceSelect: 9541 ldr rPC,[lr, #-1] @ get our target PC 9542 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9543 add rINST,lr,#-5 @ save start of chain branch 9544 add rINST, #-4 @ .. which is 9 bytes back 9545 mov r0,rPC 9546 bl dvmJitGetCodeAddr @ Is there a translation? 9547 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9548 cmp r0,#0 9549 beq 2f 9550 mov r1,rINST 9551 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9552 mov r1, rPC @ arg1 of translation may need this 9553 mov lr, #0 @ in case target is HANDLER_INTERPRET 9554 cmp r0,#0 @ successful chain? 9555 bxne r0 @ continue native execution 9556 b toInterpreter @ didn't chain - resume with interpreter 9557 9558/* No translation, so request one if profiling isn't disabled*/ 95592: 9560 adrl rIBASE, dvmAsmInstructionStart 9561 GET_JIT_PROF_TABLE(r0) 9562 FETCH_INST() 9563 cmp r0, #0 9564 movne r2,#kJitTSelectRequestHot @ ask for trace selection 9565 bne common_selectTrace 9566 GET_INST_OPCODE(ip) 9567 GOTO_OPCODE(ip) 9568 9569/* 9570 * Return from the translation cache to the interpreter. 9571 * The return was done with a BLX from thumb mode, and 9572 * the following 32-bit word contains the target rPC value. 9573 * Note that lr (r14) will have its low-order bit set to denote 9574 * its thumb-mode origin. 9575 * 9576 * We'll need to stash our lr origin away, recover the new 9577 * target and then check to see if there is a translation available 9578 * for our new target. If so, we do a translation chain and 9579 * go back to native execution. Otherwise, it's back to the 9580 * interpreter (after treating this entry as a potential 9581 * trace start). 9582 */ 9583 .global dvmJitToInterpNormal 9584dvmJitToInterpNormal: 9585 ldr rPC,[lr, #-1] @ get our target PC 9586 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9587 add rINST,lr,#-5 @ save start of chain branch 9588 add rINST,#-4 @ .. which is 9 bytes back 9589#if defined(WITH_JIT_TUNING) 9590 bl dvmBumpNormal 9591#endif 9592 mov r0,rPC 9593 bl dvmJitGetCodeAddr @ Is there a translation? 9594 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9595 cmp r0,#0 9596 beq toInterpreter @ go if not, otherwise do chain 9597 mov r1,rINST 9598 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9599 mov r1, rPC @ arg1 of translation may need this 9600 mov lr, #0 @ in case target is HANDLER_INTERPRET 9601 cmp r0,#0 @ successful chain? 9602 bxne r0 @ continue native execution 9603 b toInterpreter @ didn't chain - resume with interpreter 9604 9605/* 9606 * Return from the translation cache to the interpreter to do method invocation. 9607 * Check if translation exists for the callee, but don't chain to it. 9608 */ 9609 .global dvmJitToInterpNoChainNoProfile 9610dvmJitToInterpNoChainNoProfile: 9611#if defined(WITH_JIT_TUNING) 9612 bl dvmBumpNoChain 9613#endif 9614 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9615 mov r0,rPC 9616 bl dvmJitGetCodeAddr @ Is there a translation? 9617 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9618 mov r1, rPC @ arg1 of translation may need this 9619 mov lr, #0 @ in case target is HANDLER_INTERPRET 9620 cmp r0,#0 9621 bxne r0 @ continue native execution if so 9622 EXPORT_PC() 9623 adrl rIBASE, dvmAsmInstructionStart 9624 FETCH_INST() 9625 GET_INST_OPCODE(ip) @ extract opcode from rINST 9626 GOTO_OPCODE(ip) @ jump to next instruction 9627 9628/* 9629 * Return from the translation cache to the interpreter to do method invocation. 9630 * Check if translation exists for the callee, but don't chain to it. 9631 */ 9632 .global dvmJitToInterpNoChain 9633dvmJitToInterpNoChain: 9634#if defined(WITH_JIT_TUNING) 9635 bl dvmBumpNoChain 9636#endif 9637 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9638 mov r0,rPC 9639 bl dvmJitGetCodeAddr @ Is there a translation? 9640 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9641 mov r1, rPC @ arg1 of translation may need this 9642 mov lr, #0 @ in case target is HANDLER_INTERPRET 9643 cmp r0,#0 9644 bxne r0 @ continue native execution if so 9645#endif 9646 9647/* 9648 * No translation, restore interpreter regs and start interpreting. 9649 * rGLUE & rFP were preserved in the translated code, and rPC has 9650 * already been restored by the time we get here. We'll need to set 9651 * up rIBASE & rINST, and load the address of the JitTable into r0. 9652 */ 9653toInterpreter: 9654 EXPORT_PC() 9655 adrl rIBASE, dvmAsmInstructionStart 9656 FETCH_INST() 9657 GET_JIT_PROF_TABLE(r0) 9658 @ NOTE: intended fallthrough 9659 9660/* 9661 * Common code to update potential trace start counter, and initiate 9662 * a trace-build if appropriate. On entry, rPC should point to the 9663 * next instruction to execute, and rINST should be already loaded with 9664 * the next opcode word, and r0 holds a pointer to the jit profile 9665 * table (pJitProfTable). 9666 */ 9667common_testUpdateProfile: 9668 cmp r0,#0 9669 GET_INST_OPCODE(ip) 9670 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 9671 9672common_updateProfile: 9673 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 9674 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits 9675 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter 9676 GET_INST_OPCODE(ip) 9677 subs r1,r1,#1 @ decrement counter 9678 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it 9679 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 9680 9681/* 9682 * Here, we switch to the debug interpreter to request 9683 * trace selection. First, though, check to see if there 9684 * is already a native translation in place (and, if so, 9685 * jump to it now). 9686 */ 9687 GET_JIT_THRESHOLD(r1) 9688 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9689 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter 9690 EXPORT_PC() 9691 mov r0,rPC 9692 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC) 9693 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9694 mov r1, rPC @ arg1 of translation may need this 9695 mov lr, #0 @ in case target is HANDLER_INTERPRET 9696 cmp r0,#0 9697#if !defined(WITH_SELF_VERIFICATION) 9698 bxne r0 @ jump to the translation 9699 mov r2,#kJitTSelectRequest @ ask for trace selection 9700 @ fall-through to common_selectTrace 9701#else 9702 moveq r2,#kJitTSelectRequest @ ask for trace selection 9703 beq common_selectTrace 9704 /* 9705 * At this point, we have a target translation. However, if 9706 * that translation is actually the interpret-only pseudo-translation 9707 * we want to treat it the same as no translation. 9708 */ 9709 mov r10, r0 @ save target 9710 bl dvmCompilerGetInterpretTemplate 9711 cmp r0, r10 @ special case? 9712 bne jitSVShadowRunStart @ set up self verification shadow space 9713 GET_INST_OPCODE(ip) 9714 GOTO_OPCODE(ip) 9715 /* no return */ 9716#endif 9717 9718/* 9719 * On entry: 9720 * r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot 9721 */ 9722common_selectTrace: 9723 str r2,[rGLUE,#offGlue_jitState] 9724 mov r2,#kInterpEntryInstr @ normal entry reason 9725 str r2,[rGLUE,#offGlue_entryPoint] 9726 mov r1,#1 @ set changeInterp 9727 b common_gotoBail 9728 9729#if defined(WITH_SELF_VERIFICATION) 9730/* 9731 * Save PC and registers to shadow memory for self verification mode 9732 * before jumping to native translation. 9733 * On entry: 9734 * rPC, rFP, rGLUE: the values that they should contain 9735 * r10: the address of the target translation. 9736 */ 9737jitSVShadowRunStart: 9738 mov r0,rPC @ r0<- program counter 9739 mov r1,rFP @ r1<- frame pointer 9740 mov r2,rGLUE @ r2<- InterpState pointer 9741 mov r3,r10 @ r3<- target translation 9742 bl dvmSelfVerificationSaveState @ save registers to shadow space 9743 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 9744 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 9745 bx r10 @ jump to the translation 9746 9747/* 9748 * Restore PC, registers, and interpState to original values 9749 * before jumping back to the interpreter. 9750 */ 9751jitSVShadowRunEnd: 9752 mov r1,rFP @ pass ending fp 9753 bl dvmSelfVerificationRestoreState @ restore pc and fp values 9754 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 9755 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 9756 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 9757 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 9758 cmp r1,#0 @ check for punt condition 9759 beq 1f 9760 mov r2,#kJitSelfVerification @ ask for self verification 9761 str r2,[rGLUE,#offGlue_jitState] 9762 mov r2,#kInterpEntryInstr @ normal entry reason 9763 str r2,[rGLUE,#offGlue_entryPoint] 9764 mov r1,#1 @ set changeInterp 9765 b common_gotoBail 9766 97671: @ exit to interpreter without check 9768 EXPORT_PC() 9769 adrl rIBASE, dvmAsmInstructionStart 9770 FETCH_INST() 9771 GET_INST_OPCODE(ip) 9772 GOTO_OPCODE(ip) 9773#endif 9774 9775#endif 9776 9777/* 9778 * Common code when a backward branch is taken. 9779 * 9780 * TODO: we could avoid a branch by just setting r0 and falling through 9781 * into the common_periodicChecks code, and having a test on r0 at the 9782 * end determine if we should return to the caller or update & branch to 9783 * the next instr. 9784 * 9785 * On entry: 9786 * r9 is PC adjustment *in bytes* 9787 */ 9788common_backwardBranch: 9789 mov r0, #kInterpEntryInstr 9790 bl common_periodicChecks 9791#if defined(WITH_JIT) 9792 GET_JIT_PROF_TABLE(r0) 9793 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9794 cmp r0,#0 9795 bne common_updateProfile 9796 GET_INST_OPCODE(ip) 9797 GOTO_OPCODE(ip) 9798#else 9799 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9800 GET_INST_OPCODE(ip) @ extract opcode from rINST 9801 GOTO_OPCODE(ip) @ jump to next instruction 9802#endif 9803 9804 9805/* 9806 * Need to see if the thread needs to be suspended or debugger/profiler 9807 * activity has begun. If so, we suspend the thread or side-exit to 9808 * the debug interpreter as appropriate. 9809 * 9810 * The common case is no activity on any of these, so we want to figure 9811 * that out quickly. If something is up, we can then sort out what. 9812 * 9813 * We want to be fast if the VM was built without debugger or profiler 9814 * support, but we also need to recognize that the system is usually 9815 * shipped with both of these enabled. 9816 * 9817 * TODO: reduce this so we're just checking a single location. 9818 * 9819 * On entry: 9820 * r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling) 9821 * r9 is trampoline PC adjustment *in bytes* 9822 */ 9823common_periodicChecks: 9824 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9825 9826 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9827 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9828 9829 ldr ip, [r3] @ ip<- suspendCount (int) 9830 9831 cmp r1, #0 @ debugger enabled? 9832 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9833 ldr r2, [r2] @ r2<- activeProfilers (int) 9834 orrnes ip, ip, r1 @ ip<- suspendCount | debuggerActive 9835 /* 9836 * Don't switch the interpreter in the libdvm_traceview build even if the 9837 * profiler is active. 9838 * The code here is opted for less intrusion instead of performance. 9839 * That is, *pActiveProfilers is still loaded into r2 even though it is not 9840 * used when WITH_INLINE_PROFILING is defined. 9841 */ 9842#if !defined(WITH_INLINE_PROFILING) 9843 orrs ip, ip, r2 @ ip<- suspend|debugger|profiler; set Z 9844#endif 9845 9846 9847 bxeq lr @ all zero, return 9848 9849 /* 9850 * One or more interesting events have happened. Figure out what. 9851 * 9852 * If debugging or profiling are compiled in, we need to disambiguate. 9853 * 9854 * r0 still holds the reentry type. 9855 */ 9856 ldr ip, [r3] @ ip<- suspendCount (int) 9857 cmp ip, #0 @ want suspend? 9858 beq 1f @ no, must be debugger/profiler 9859 9860 stmfd sp!, {r0, lr} @ preserve r0 and lr 9861#if defined(WITH_JIT) 9862 /* 9863 * Refresh the Jit's cached copy of profile table pointer. This pointer 9864 * doubles as the Jit's on/off switch. 9865 */ 9866 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable 9867 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9868 ldr r3, [r3] @ r3 <- pJitProfTable 9869 EXPORT_PC() @ need for precise GC 9870 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch 9871#else 9872 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9873 EXPORT_PC() @ need for precise GC 9874#endif 9875 bl dvmCheckSuspendPending @ do full check, suspend if necessary 9876 ldmfd sp!, {r0, lr} @ restore r0 and lr 9877 9878 /* 9879 * Reload the debugger/profiler enable flags. We're checking to see 9880 * if either of these got set while we were suspended. 9881 * 9882 * If WITH_INLINE_PROFILING is configured, don't check whether the profiler 9883 * is enabled or not as the profiling will be done inline. 9884 */ 9885 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9886 cmp r1, #0 @ debugger enabled? 9887 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9888 9889#if !defined(WITH_INLINE_PROFILING) 9890 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9891 ldr r2, [r2] @ r2<- activeProfilers (int) 9892 orrs r1, r1, r2 9893#else 9894 cmp r1, #0 @ only consult the debuggerActive flag 9895#endif 9896 9897 beq 2f 9898 98991: @ debugger/profiler enabled, bail out; glue->entryPoint was set above 9900 str r0, [rGLUE, #offGlue_entryPoint] @ store r0, need for debug/prof 9901 add rPC, rPC, r9 @ update rPC 9902 mov r1, #1 @ "want switch" = true 9903 b common_gotoBail @ side exit 9904 99052: 9906 bx lr @ nothing to do, return 9907 9908 9909/* 9910 * The equivalent of "goto bail", this calls through the "bail handler". 9911 * 9912 * State registers will be saved to the "glue" area before bailing. 9913 * 9914 * On entry: 9915 * r1 is "bool changeInterp", indicating if we want to switch to the 9916 * other interpreter or just bail all the way out 9917 */ 9918common_gotoBail: 9919 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9920 mov r0, rGLUE @ r0<- glue ptr 9921 b dvmMterpStdBail @ call(glue, changeInterp) 9922 9923 @add r1, r1, #1 @ using (boolean+1) 9924 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9925 @bl _longjmp @ does not return 9926 @bl common_abort 9927 9928 9929/* 9930 * Common code for method invocation with range. 9931 * 9932 * On entry: 9933 * r0 is "Method* methodToCall", the method we're trying to call 9934 */ 9935common_invokeMethodRange: 9936.LinvokeNewRange: 9937 @ prepare to copy args to "outs" area of current frame 9938 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9939 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9940 beq .LinvokeArgsDone @ if no args, skip the rest 9941 FETCH(r1, 2) @ r1<- CCCC 9942 9943 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9944 @ (very few methods have > 10 args; could unroll for common cases) 9945 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9946 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9947 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 99481: ldr r1, [r3], #4 @ val = *fp++ 9949 subs r2, r2, #1 @ count-- 9950 str r1, [r10], #4 @ *outs++ = val 9951 bne 1b @ ...while count != 0 9952 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9953 b .LinvokeArgsDone 9954 9955/* 9956 * Common code for method invocation without range. 9957 * 9958 * On entry: 9959 * r0 is "Method* methodToCall", the method we're trying to call 9960 */ 9961common_invokeMethodNoRange: 9962.LinvokeNewNoRange: 9963 @ prepare to copy args to "outs" area of current frame 9964 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9965 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9966 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9967 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9968 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9969 beq .LinvokeArgsDone 9970 9971 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9972.LinvokeNonRange: 9973 rsb r2, r2, #5 @ r2<- 5-r2 9974 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9975 bl common_abort @ (skipped due to ARM prefetch) 99765: and ip, rINST, #0x0f00 @ isolate A 9977 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 9978 mov r0, r0 @ nop 9979 str r2, [r10, #-4]! @ *--outs = vA 99804: and ip, r1, #0xf000 @ isolate G 9981 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 9982 mov r0, r0 @ nop 9983 str r2, [r10, #-4]! @ *--outs = vG 99843: and ip, r1, #0x0f00 @ isolate F 9985 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 9986 mov r0, r0 @ nop 9987 str r2, [r10, #-4]! @ *--outs = vF 99882: and ip, r1, #0x00f0 @ isolate E 9989 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 9990 mov r0, r0 @ nop 9991 str r2, [r10, #-4]! @ *--outs = vE 99921: and ip, r1, #0x000f @ isolate D 9993 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 9994 mov r0, r0 @ nop 9995 str r2, [r10, #-4]! @ *--outs = vD 99960: @ fall through to .LinvokeArgsDone 9997 9998.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 9999 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 10000 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 10001 @ find space for the new stack frame, check for overflow 10002 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 10003 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 10004 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 10005@ bl common_dumpRegs 10006 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 10007 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 10008 cmp r3, r9 @ bottom < interpStackEnd? 10009 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 10010 blo .LstackOverflow @ yes, this frame will overflow stack 10011 10012 @ set up newSaveArea 10013#ifdef EASY_GDB 10014 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 10015 str ip, [r10, #offStackSaveArea_prevSave] 10016#endif 10017 str rFP, [r10, #offStackSaveArea_prevFrame] 10018 str rPC, [r10, #offStackSaveArea_savedPc] 10019#if defined(WITH_JIT) 10020 mov r9, #0 10021 str r9, [r10, #offStackSaveArea_returnAddr] 10022#endif 10023#if defined(WITH_INLINE_PROFILING) 10024 stmfd sp!, {r0-r3} @ preserve r0-r3 10025 mov r1, r6 10026 @ r0=methodToCall, r1=rGlue 10027 bl dvmFastMethodTraceEnter 10028 ldmfd sp!, {r0-r3} @ restore r0-r3 10029#endif 10030 str r0, [r10, #offStackSaveArea_method] 10031 tst r3, #ACC_NATIVE 10032 bne .LinvokeNative 10033 10034 /* 10035 stmfd sp!, {r0-r3} 10036 bl common_printNewline 10037 mov r0, rFP 10038 mov r1, #0 10039 bl dvmDumpFp 10040 ldmfd sp!, {r0-r3} 10041 stmfd sp!, {r0-r3} 10042 mov r0, r1 10043 mov r1, r10 10044 bl dvmDumpFp 10045 bl common_printNewline 10046 ldmfd sp!, {r0-r3} 10047 */ 10048 10049 ldrh r9, [r2] @ r9 <- load INST from new PC 10050 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 10051 mov rPC, r2 @ publish new rPC 10052 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 10053 10054 @ Update "glue" values for the new method 10055 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 10056 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 10057 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 10058#if defined(WITH_JIT) 10059 GET_JIT_PROF_TABLE(r0) 10060 mov rFP, r1 @ fp = newFp 10061 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 10062 mov rINST, r9 @ publish new rINST 10063 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 10064 cmp r0,#0 10065 bne common_updateProfile 10066 GOTO_OPCODE(ip) @ jump to next instruction 10067#else 10068 mov rFP, r1 @ fp = newFp 10069 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 10070 mov rINST, r9 @ publish new rINST 10071 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 10072 GOTO_OPCODE(ip) @ jump to next instruction 10073#endif 10074 10075.LinvokeNative: 10076 @ Prep for the native call 10077 @ r0=methodToCall, r1=newFp, r10=newSaveArea 10078 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10079 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 10080 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 10081 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 10082 mov r9, r3 @ r9<- glue->self (preserve) 10083 10084 mov r2, r0 @ r2<- methodToCall 10085 mov r0, r1 @ r0<- newFp (points to args) 10086 add r1, rGLUE, #offGlue_retval @ r1<- &retval 10087 10088#ifdef ASSIST_DEBUGGER 10089 /* insert fake function header to help gdb find the stack frame */ 10090 b .Lskip 10091 .type dalvik_mterp, %function 10092dalvik_mterp: 10093 .fnstart 10094 MTERP_ENTRY1 10095 MTERP_ENTRY2 10096.Lskip: 10097#endif 10098 10099#if defined(WITH_INLINE_PROFILING) 10100 @ r2=JNIMethod, r6=rGLUE 10101 stmfd sp!, {r2,r6} 10102#endif 10103 10104 @mov lr, pc @ set return addr 10105 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 10106 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 10107 10108#if defined(WITH_INLINE_PROFILING) 10109 @ r0=JNIMethod, r1=rGLUE 10110 ldmfd sp!, {r0-r1} 10111 bl dvmFastNativeMethodTraceExit 10112#endif 10113 10114#if defined(WITH_JIT) 10115 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status 10116#endif 10117 10118 @ native return; r9=self, r10=newSaveArea 10119 @ equivalent to dvmPopJniLocals 10120 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 10121 ldr r1, [r9, #offThread_exception] @ check for exception 10122#if defined(WITH_JIT) 10123 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable 10124#endif 10125 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 10126 cmp r1, #0 @ null? 10127 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 10128#if defined(WITH_JIT) 10129 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch 10130#endif 10131 bne common_exceptionThrown @ no, handle exception 10132 10133 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 10134 GET_INST_OPCODE(ip) @ extract opcode from rINST 10135 GOTO_OPCODE(ip) @ jump to next instruction 10136 10137.LstackOverflow: @ r0=methodToCall 10138 mov r1, r0 @ r1<- methodToCall 10139 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 10140 bl dvmHandleStackOverflow 10141 b common_exceptionThrown 10142#ifdef ASSIST_DEBUGGER 10143 .fnend 10144#endif 10145 10146 10147 /* 10148 * Common code for method invocation, calling through "glue code". 10149 * 10150 * TODO: now that we have range and non-range invoke handlers, this 10151 * needs to be split into two. Maybe just create entry points 10152 * that set r9 and jump here? 10153 * 10154 * On entry: 10155 * r0 is "Method* methodToCall", the method we're trying to call 10156 * r9 is "bool methodCallRange", indicating if this is a /range variant 10157 */ 10158 .if 0 10159.LinvokeOld: 10160 sub sp, sp, #8 @ space for args + pad 10161 FETCH(ip, 2) @ ip<- FEDC or CCCC 10162 mov r2, r0 @ A2<- methodToCall 10163 mov r0, rGLUE @ A0<- glue 10164 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 10165 mov r1, r9 @ A1<- methodCallRange 10166 mov r3, rINST, lsr #8 @ A3<- AA 10167 str ip, [sp, #0] @ A4<- ip 10168 bl dvmMterp_invokeMethod @ call the C invokeMethod 10169 add sp, sp, #8 @ remove arg area 10170 b common_resumeAfterGlueCall @ continue to next instruction 10171 .endif 10172 10173 10174 10175/* 10176 * Common code for handling a return instruction. 10177 * 10178 * This does not return. 10179 */ 10180common_returnFromMethod: 10181.LreturnNew: 10182 mov r0, #kInterpEntryReturn 10183 mov r9, #0 10184 bl common_periodicChecks 10185 10186#if defined(WITH_INLINE_PROFILING) 10187 stmfd sp!, {r0-r3} @ preserve r0-r3 10188 mov r0, r6 10189 @ r0=rGlue 10190 bl dvmFastJavaMethodTraceExit 10191 ldmfd sp!, {r0-r3} @ restore r0-r3 10192#endif 10193 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 10194 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 10195 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 10196 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 10197 @ r2<- method we're returning to 10198 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10199 cmp r2, #0 @ is this a break frame? 10200 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 10201 mov r1, #0 @ "want switch" = false 10202 beq common_gotoBail @ break frame, bail out completely 10203 10204 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 10205 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 10206 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 10207 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 10208#if defined(WITH_JIT) 10209 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr 10210 mov rPC, r9 @ publish new rPC 10211 str r1, [rGLUE, #offGlue_methodClassDex] 10212 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land 10213 cmp r10, #0 @ caller is compiled code 10214 blxne r10 10215 GET_INST_OPCODE(ip) @ extract opcode from rINST 10216 GOTO_OPCODE(ip) @ jump to next instruction 10217#else 10218 GET_INST_OPCODE(ip) @ extract opcode from rINST 10219 mov rPC, r9 @ publish new rPC 10220 str r1, [rGLUE, #offGlue_methodClassDex] 10221 GOTO_OPCODE(ip) @ jump to next instruction 10222#endif 10223 10224 /* 10225 * Return handling, calls through "glue code". 10226 */ 10227 .if 0 10228.LreturnOld: 10229 SAVE_PC_FP_TO_GLUE() @ export state 10230 mov r0, rGLUE @ arg to function 10231 bl dvmMterp_returnFromMethod 10232 b common_resumeAfterGlueCall 10233 .endif 10234 10235 10236/* 10237 * Somebody has thrown an exception. Handle it. 10238 * 10239 * If the exception processing code returns to us (instead of falling 10240 * out of the interpreter), continue with whatever the next instruction 10241 * now happens to be. 10242 * 10243 * This does not return. 10244 */ 10245 .global dvmMterpCommonExceptionThrown 10246dvmMterpCommonExceptionThrown: 10247common_exceptionThrown: 10248.LexceptionNew: 10249 mov r0, #kInterpEntryThrow 10250 mov r9, #0 10251 bl common_periodicChecks 10252 10253 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 10254 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 10255 mov r1, r10 @ r1<- self 10256 mov r0, r9 @ r0<- exception 10257 bl dvmAddTrackedAlloc @ don't let the exception be GCed 10258 mov r3, #0 @ r3<- NULL 10259 str r3, [r10, #offThread_exception] @ self->exception = NULL 10260 10261 /* set up args and a local for "&fp" */ 10262 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 10263 str rFP, [sp, #-4]! @ *--sp = fp 10264 mov ip, sp @ ip<- &fp 10265 mov r3, #0 @ r3<- false 10266 str ip, [sp, #-4]! @ *--sp = &fp 10267 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 10268 mov r0, r10 @ r0<- self 10269 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 10270 mov r2, r9 @ r2<- exception 10271 sub r1, rPC, r1 @ r1<- pc - method->insns 10272 mov r1, r1, asr #1 @ r1<- offset in code units 10273 10274 /* call, r0 gets catchRelPc (a code-unit offset) */ 10275 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 10276 10277 /* fix earlier stack overflow if necessary; may trash rFP */ 10278 ldrb r1, [r10, #offThread_stackOverflowed] 10279 cmp r1, #0 @ did we overflow earlier? 10280 beq 1f @ no, skip ahead 10281 mov rFP, r0 @ save relPc result in rFP 10282 mov r0, r10 @ r0<- self 10283 mov r1, r9 @ r1<- exception 10284 bl dvmCleanupStackOverflow @ call(self) 10285 mov r0, rFP @ restore result 102861: 10287 10288 /* update frame pointer and check result from dvmFindCatchBlock */ 10289 ldr rFP, [sp, #4] @ retrieve the updated rFP 10290 cmp r0, #0 @ is catchRelPc < 0? 10291 add sp, sp, #8 @ restore stack 10292 bmi .LnotCaughtLocally 10293 10294 /* adjust locals to match self->curFrame and updated PC */ 10295 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 10296 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 10297 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 10298 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 10299 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 10300 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 10301 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 10302 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 10303 10304 /* release the tracked alloc on the exception */ 10305 mov r0, r9 @ r0<- exception 10306 mov r1, r10 @ r1<- self 10307 bl dvmReleaseTrackedAlloc @ release the exception 10308 10309 /* restore the exception if the handler wants it */ 10310 FETCH_INST() @ load rINST from rPC 10311 GET_INST_OPCODE(ip) @ extract opcode from rINST 10312 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 10313 streq r9, [r10, #offThread_exception] @ yes, restore the exception 10314 GOTO_OPCODE(ip) @ jump to next instruction 10315 10316.LnotCaughtLocally: @ r9=exception, r10=self 10317 /* fix stack overflow if necessary */ 10318 ldrb r1, [r10, #offThread_stackOverflowed] 10319 cmp r1, #0 @ did we overflow earlier? 10320 movne r0, r10 @ if yes: r0<- self 10321 movne r1, r9 @ if yes: r1<- exception 10322 blne dvmCleanupStackOverflow @ if yes: call(self) 10323 10324 @ may want to show "not caught locally" debug messages here 10325#if DVM_SHOW_EXCEPTION >= 2 10326 /* call __android_log_print(prio, tag, format, ...) */ 10327 /* "Exception %s from %s:%d not caught locally" */ 10328 @ dvmLineNumFromPC(method, pc - method->insns) 10329 ldr r0, [rGLUE, #offGlue_method] 10330 ldr r1, [r0, #offMethod_insns] 10331 sub r1, rPC, r1 10332 asr r1, r1, #1 10333 bl dvmLineNumFromPC 10334 str r0, [sp, #-4]! 10335 @ dvmGetMethodSourceFile(method) 10336 ldr r0, [rGLUE, #offGlue_method] 10337 bl dvmGetMethodSourceFile 10338 str r0, [sp, #-4]! 10339 @ exception->clazz->descriptor 10340 ldr r3, [r9, #offObject_clazz] 10341 ldr r3, [r3, #offClassObject_descriptor] 10342 @ 10343 ldr r2, strExceptionNotCaughtLocally 10344 ldr r1, strLogTag 10345 mov r0, #3 @ LOG_DEBUG 10346 bl __android_log_print 10347#endif 10348 str r9, [r10, #offThread_exception] @ restore exception 10349 mov r0, r9 @ r0<- exception 10350 mov r1, r10 @ r1<- self 10351 bl dvmReleaseTrackedAlloc @ release the exception 10352 mov r1, #0 @ "want switch" = false 10353 b common_gotoBail @ bail out 10354 10355 10356 /* 10357 * Exception handling, calls through "glue code". 10358 */ 10359 .if 0 10360.LexceptionOld: 10361 SAVE_PC_FP_TO_GLUE() @ export state 10362 mov r0, rGLUE @ arg to function 10363 bl dvmMterp_exceptionThrown 10364 b common_resumeAfterGlueCall 10365 .endif 10366 10367 10368/* 10369 * After returning from a "glued" function, pull out the updated 10370 * values and start executing at the next instruction. 10371 */ 10372common_resumeAfterGlueCall: 10373 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 10374 FETCH_INST() @ load rINST from rPC 10375 GET_INST_OPCODE(ip) @ extract opcode from rINST 10376 GOTO_OPCODE(ip) @ jump to next instruction 10377 10378/* 10379 * Invalid array index. 10380 */ 10381common_errArrayIndex: 10382 EXPORT_PC() 10383 ldr r0, strArrayIndexException 10384 mov r1, #0 10385 bl dvmThrowException 10386 b common_exceptionThrown 10387 10388/* 10389 * Invalid array value. 10390 */ 10391common_errArrayStore: 10392 EXPORT_PC() 10393 ldr r0, strArrayStoreException 10394 mov r1, #0 10395 bl dvmThrowException 10396 b common_exceptionThrown 10397 10398/* 10399 * Integer divide or mod by zero. 10400 */ 10401common_errDivideByZero: 10402 EXPORT_PC() 10403 ldr r0, strArithmeticException 10404 ldr r1, strDivideByZero 10405 bl dvmThrowException 10406 b common_exceptionThrown 10407 10408/* 10409 * Attempt to allocate an array with a negative size. 10410 */ 10411common_errNegativeArraySize: 10412 EXPORT_PC() 10413 ldr r0, strNegativeArraySizeException 10414 mov r1, #0 10415 bl dvmThrowException 10416 b common_exceptionThrown 10417 10418/* 10419 * Invocation of a non-existent method. 10420 */ 10421common_errNoSuchMethod: 10422 EXPORT_PC() 10423 ldr r0, strNoSuchMethodError 10424 mov r1, #0 10425 bl dvmThrowException 10426 b common_exceptionThrown 10427 10428/* 10429 * We encountered a null object when we weren't expecting one. We 10430 * export the PC, throw a NullPointerException, and goto the exception 10431 * processing code. 10432 */ 10433common_errNullObject: 10434 EXPORT_PC() 10435 ldr r0, strNullPointerException 10436 mov r1, #0 10437 bl dvmThrowException 10438 b common_exceptionThrown 10439 10440/* 10441 * For debugging, cause an immediate fault. The source address will 10442 * be in lr (use a bl instruction to jump here). 10443 */ 10444common_abort: 10445 ldr pc, .LdeadFood 10446.LdeadFood: 10447 .word 0xdeadf00d 10448 10449/* 10450 * Spit out a "we were here", preserving all registers. (The attempt 10451 * to save ip won't work, but we need to save an even number of 10452 * registers for EABI 64-bit stack alignment.) 10453 */ 10454 .macro SQUEAK num 10455common_squeak\num: 10456 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10457 ldr r0, strSqueak 10458 mov r1, #\num 10459 bl printf 10460 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10461 bx lr 10462 .endm 10463 10464 SQUEAK 0 10465 SQUEAK 1 10466 SQUEAK 2 10467 SQUEAK 3 10468 SQUEAK 4 10469 SQUEAK 5 10470 10471/* 10472 * Spit out the number in r0, preserving registers. 10473 */ 10474common_printNum: 10475 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10476 mov r1, r0 10477 ldr r0, strSqueak 10478 bl printf 10479 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10480 bx lr 10481 10482/* 10483 * Print a newline, preserving registers. 10484 */ 10485common_printNewline: 10486 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10487 ldr r0, strNewline 10488 bl printf 10489 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10490 bx lr 10491 10492 /* 10493 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 10494 */ 10495common_printHex: 10496 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10497 mov r1, r0 10498 ldr r0, strPrintHex 10499 bl printf 10500 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10501 bx lr 10502 10503/* 10504 * Print the 64-bit quantity in r0-r1, preserving registers. 10505 */ 10506common_printLong: 10507 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10508 mov r3, r1 10509 mov r2, r0 10510 ldr r0, strPrintLong 10511 bl printf 10512 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10513 bx lr 10514 10515/* 10516 * Print full method info. Pass the Method* in r0. Preserves regs. 10517 */ 10518common_printMethod: 10519 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10520 bl dvmMterpPrintMethod 10521 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10522 bx lr 10523 10524/* 10525 * Call a C helper function that dumps regs and possibly some 10526 * additional info. Requires the C function to be compiled in. 10527 */ 10528 .if 0 10529common_dumpRegs: 10530 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10531 bl dvmMterpDumpArmRegs 10532 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10533 bx lr 10534 .endif 10535 10536#if 0 10537/* 10538 * Experiment on VFP mode. 10539 * 10540 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 10541 * 10542 * Updates the bits specified by "mask", setting them to the values in "val". 10543 */ 10544setFPSCR: 10545 and r0, r0, r1 @ make sure no stray bits are set 10546 fmrx r2, fpscr @ get VFP reg 10547 mvn r1, r1 @ bit-invert mask 10548 and r2, r2, r1 @ clear masked bits 10549 orr r2, r2, r0 @ set specified bits 10550 fmxr fpscr, r2 @ set VFP reg 10551 mov r0, r2 @ return new value 10552 bx lr 10553 10554 .align 2 10555 .global dvmConfigureFP 10556 .type dvmConfigureFP, %function 10557dvmConfigureFP: 10558 stmfd sp!, {ip, lr} 10559 /* 0x03000000 sets DN/FZ */ 10560 /* 0x00009f00 clears the six exception enable flags */ 10561 bl common_squeak0 10562 mov r0, #0x03000000 @ r0<- 0x03000000 10563 add r1, r0, #0x9f00 @ r1<- 0x03009f00 10564 bl setFPSCR 10565 ldmfd sp!, {ip, pc} 10566#endif 10567 10568 10569/* 10570 * String references, must be close to the code that uses them. 10571 */ 10572 .align 2 10573strArithmeticException: 10574 .word .LstrArithmeticException 10575strArrayIndexException: 10576 .word .LstrArrayIndexException 10577strArrayStoreException: 10578 .word .LstrArrayStoreException 10579strDivideByZero: 10580 .word .LstrDivideByZero 10581strNegativeArraySizeException: 10582 .word .LstrNegativeArraySizeException 10583strNoSuchMethodError: 10584 .word .LstrNoSuchMethodError 10585strNullPointerException: 10586 .word .LstrNullPointerException 10587 10588strLogTag: 10589 .word .LstrLogTag 10590strExceptionNotCaughtLocally: 10591 .word .LstrExceptionNotCaughtLocally 10592 10593strNewline: 10594 .word .LstrNewline 10595strSqueak: 10596 .word .LstrSqueak 10597strPrintHex: 10598 .word .LstrPrintHex 10599strPrintLong: 10600 .word .LstrPrintLong 10601 10602/* 10603 * Zero-terminated ASCII string data. 10604 * 10605 * On ARM we have two choices: do like gcc does, and LDR from a .word 10606 * with the address, or use an ADR pseudo-op to get the address 10607 * directly. ADR saves 4 bytes and an indirection, but it's using a 10608 * PC-relative addressing mode and hence has a limited range, which 10609 * makes it not work well with mergeable string sections. 10610 */ 10611 .section .rodata.str1.4,"aMS",%progbits,1 10612 10613.LstrBadEntryPoint: 10614 .asciz "Bad entry point %d\n" 10615.LstrArithmeticException: 10616 .asciz "Ljava/lang/ArithmeticException;" 10617.LstrArrayIndexException: 10618 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 10619.LstrArrayStoreException: 10620 .asciz "Ljava/lang/ArrayStoreException;" 10621.LstrClassCastException: 10622 .asciz "Ljava/lang/ClassCastException;" 10623.LstrDivideByZero: 10624 .asciz "divide by zero" 10625.LstrFilledNewArrayNotImpl: 10626 .asciz "filled-new-array only implemented for objects and 'int'" 10627.LstrInternalError: 10628 .asciz "Ljava/lang/InternalError;" 10629.LstrInstantiationError: 10630 .asciz "Ljava/lang/InstantiationError;" 10631.LstrNegativeArraySizeException: 10632 .asciz "Ljava/lang/NegativeArraySizeException;" 10633.LstrNoSuchMethodError: 10634 .asciz "Ljava/lang/NoSuchMethodError;" 10635.LstrNullPointerException: 10636 .asciz "Ljava/lang/NullPointerException;" 10637 10638.LstrLogTag: 10639 .asciz "mterp" 10640.LstrExceptionNotCaughtLocally: 10641 .asciz "Exception %s from %s:%d not caught locally\n" 10642 10643.LstrNewline: 10644 .asciz "\n" 10645.LstrSqueak: 10646 .asciz "<%d>" 10647.LstrPrintHex: 10648 .asciz "<0x%x>" 10649.LstrPrintLong: 10650 .asciz "<%lld>" 10651 10652