InterpAsm-armv5te-vfp.S revision b78c76f88ea42e7a3b295c210ca9ee86e7290043
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(rINST, r2) @ rINST<- vBB (array object) 2268 GET_VREG(r0, r3) @ r0<- vCC (requested index) 2269 cmp rINST, #0 @ null array object? 2270 GET_VREG(r9, r9) @ r9<- vAA 2271 beq common_errNullObject @ yes, bail 2272 ldr r3, [rINST, #offArrayObject_length] @ r3<- arrayObj->length 2273 add r10, rINST, 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 r9, [rGLUE, #offGlue_method] @ r9<- current method 3048 EXPORT_PC() @ resolve() could throw, so export now 3049 ldr r0, [r9, #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_UNUSED_F1: /* 0xf1 */ 7456/* File: armv5te/OP_UNUSED_F1.S */ 7457/* File: armv5te/unused.S */ 7458 bl common_abort 7459 7460 7461/* ------------------------------ */ 7462 .balign 64 7463.L_OP_IGET_QUICK: /* 0xf2 */ 7464/* File: armv5te/OP_IGET_QUICK.S */ 7465 /* For: iget-quick, iget-object-quick */ 7466 /* op vA, vB, offset@CCCC */ 7467 mov r2, rINST, lsr #12 @ r2<- B 7468 GET_VREG(r3, r2) @ r3<- object we're operating on 7469 FETCH(r1, 1) @ r1<- field byte offset 7470 cmp r3, #0 @ check object for null 7471 mov r2, rINST, lsr #8 @ r2<- A(+) 7472 beq common_errNullObject @ object was null 7473 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7474 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7475 and r2, r2, #15 7476 GET_INST_OPCODE(ip) @ extract opcode from rINST 7477 SET_VREG(r0, r2) @ fp[A]<- r0 7478 GOTO_OPCODE(ip) @ jump to next instruction 7479 7480/* ------------------------------ */ 7481 .balign 64 7482.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7483/* File: armv5te/OP_IGET_WIDE_QUICK.S */ 7484 /* iget-wide-quick vA, vB, offset@CCCC */ 7485 mov r2, rINST, lsr #12 @ r2<- B 7486 GET_VREG(r3, r2) @ r3<- object we're operating on 7487 FETCH(ip, 1) @ ip<- field byte offset 7488 cmp r3, #0 @ check object for null 7489 mov r2, rINST, lsr #8 @ r2<- A(+) 7490 beq common_errNullObject @ object was null 7491 ldrd r0, [r3, ip] @ r0<- obj.field (64 bits, aligned) 7492 and r2, r2, #15 7493 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7494 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7495 GET_INST_OPCODE(ip) @ extract opcode from rINST 7496 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7497 GOTO_OPCODE(ip) @ jump to next instruction 7498 7499/* ------------------------------ */ 7500 .balign 64 7501.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7502/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7503/* File: armv5te/OP_IGET_QUICK.S */ 7504 /* For: iget-quick, iget-object-quick */ 7505 /* op vA, vB, offset@CCCC */ 7506 mov r2, rINST, lsr #12 @ r2<- B 7507 GET_VREG(r3, r2) @ r3<- object we're operating on 7508 FETCH(r1, 1) @ r1<- field byte offset 7509 cmp r3, #0 @ check object for null 7510 mov r2, rINST, lsr #8 @ r2<- A(+) 7511 beq common_errNullObject @ object was null 7512 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7513 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7514 and r2, r2, #15 7515 GET_INST_OPCODE(ip) @ extract opcode from rINST 7516 SET_VREG(r0, r2) @ fp[A]<- r0 7517 GOTO_OPCODE(ip) @ jump to next instruction 7518 7519 7520/* ------------------------------ */ 7521 .balign 64 7522.L_OP_IPUT_QUICK: /* 0xf5 */ 7523/* File: armv5te/OP_IPUT_QUICK.S */ 7524 /* For: iput-quick */ 7525 /* op vA, vB, offset@CCCC */ 7526 mov r2, rINST, lsr #12 @ r2<- B 7527 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7528 FETCH(r1, 1) @ r1<- field byte offset 7529 cmp r3, #0 @ check object for null 7530 mov r2, rINST, lsr #8 @ r2<- A(+) 7531 beq common_errNullObject @ object was null 7532 and r2, r2, #15 7533 GET_VREG(r0, r2) @ r0<- fp[A] 7534 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7535 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7536 GET_INST_OPCODE(ip) @ extract opcode from rINST 7537 GOTO_OPCODE(ip) @ jump to next instruction 7538 7539/* ------------------------------ */ 7540 .balign 64 7541.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7542/* File: armv5te/OP_IPUT_WIDE_QUICK.S */ 7543 /* iput-wide-quick vA, vB, offset@CCCC */ 7544 mov r0, rINST, lsr #8 @ r0<- A(+) 7545 mov r1, rINST, lsr #12 @ r1<- B 7546 and r0, r0, #15 7547 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7548 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7549 cmp r2, #0 @ check object for null 7550 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7551 beq common_errNullObject @ object was null 7552 FETCH(r3, 1) @ r3<- field byte offset 7553 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7554 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7555 GET_INST_OPCODE(ip) @ extract opcode from rINST 7556 GOTO_OPCODE(ip) @ jump to next instruction 7557 7558/* ------------------------------ */ 7559 .balign 64 7560.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7561/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7562 /* For: iput-object-quick */ 7563 /* op vA, vB, offset@CCCC */ 7564 mov r2, rINST, lsr #12 @ r2<- B 7565 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7566 FETCH(r1, 1) @ r1<- field byte offset 7567 cmp r3, #0 @ check object for null 7568 mov r2, rINST, lsr #8 @ r2<- A(+) 7569 beq common_errNullObject @ object was null 7570 and r2, r2, #15 7571 GET_VREG(r0, r2) @ r0<- fp[A] 7572 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 7573 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7574 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7575 cmp r0, #0 7576 strneb r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head 7577 GET_INST_OPCODE(ip) @ extract opcode from rINST 7578 GOTO_OPCODE(ip) @ jump to next instruction 7579 7580/* ------------------------------ */ 7581 .balign 64 7582.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7583/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7584 /* 7585 * Handle an optimized virtual method call. 7586 * 7587 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7588 */ 7589 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7590 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7591 FETCH(r3, 2) @ r3<- FEDC or CCCC 7592 FETCH(r1, 1) @ r1<- BBBB 7593 .if (!0) 7594 and r3, r3, #15 @ r3<- C (or stays CCCC) 7595 .endif 7596 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7597 cmp r2, #0 @ is "this" null? 7598 beq common_errNullObject @ null "this", throw exception 7599 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7600 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7601 EXPORT_PC() @ invoke must export 7602 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7603 bl common_invokeMethodNoRange @ continue on 7604 7605/* ------------------------------ */ 7606 .balign 64 7607.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7608/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7609/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7610 /* 7611 * Handle an optimized virtual method call. 7612 * 7613 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7614 */ 7615 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7616 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7617 FETCH(r3, 2) @ r3<- FEDC or CCCC 7618 FETCH(r1, 1) @ r1<- BBBB 7619 .if (!1) 7620 and r3, r3, #15 @ r3<- C (or stays CCCC) 7621 .endif 7622 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7623 cmp r2, #0 @ is "this" null? 7624 beq common_errNullObject @ null "this", throw exception 7625 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7626 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7627 EXPORT_PC() @ invoke must export 7628 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7629 bl common_invokeMethodRange @ continue on 7630 7631 7632/* ------------------------------ */ 7633 .balign 64 7634.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7635/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7636 /* 7637 * Handle an optimized "super" method call. 7638 * 7639 * for: [opt] invoke-super-quick, invoke-super-quick/range 7640 */ 7641 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7642 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7643 FETCH(r10, 2) @ r10<- GFED or CCCC 7644 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7645 .if (!0) 7646 and r10, r10, #15 @ r10<- D (or stays CCCC) 7647 .endif 7648 FETCH(r1, 1) @ r1<- BBBB 7649 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7650 EXPORT_PC() @ must export for invoke 7651 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7652 GET_VREG(r3, r10) @ r3<- "this" 7653 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7654 cmp r3, #0 @ null "this" ref? 7655 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7656 beq common_errNullObject @ "this" is null, throw exception 7657 bl common_invokeMethodNoRange @ continue on 7658 7659/* ------------------------------ */ 7660 .balign 64 7661.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7662/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7663/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7664 /* 7665 * Handle an optimized "super" method call. 7666 * 7667 * for: [opt] invoke-super-quick, invoke-super-quick/range 7668 */ 7669 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7670 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7671 FETCH(r10, 2) @ r10<- GFED or CCCC 7672 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7673 .if (!1) 7674 and r10, r10, #15 @ r10<- D (or stays CCCC) 7675 .endif 7676 FETCH(r1, 1) @ r1<- BBBB 7677 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7678 EXPORT_PC() @ must export for invoke 7679 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7680 GET_VREG(r3, r10) @ r3<- "this" 7681 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7682 cmp r3, #0 @ null "this" ref? 7683 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7684 beq common_errNullObject @ "this" is null, throw exception 7685 bl common_invokeMethodRange @ continue on 7686 7687 7688/* ------------------------------ */ 7689 .balign 64 7690.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ 7691/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */ 7692/* File: armv5te/OP_IPUT_OBJECT.S */ 7693 /* 7694 * 32-bit instance field put. 7695 * 7696 * for: iput-object, iput-object-volatile 7697 */ 7698 /* op vA, vB, field@CCCC */ 7699 mov r0, rINST, lsr #12 @ r0<- B 7700 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7701 FETCH(r1, 1) @ r1<- field ref CCCC 7702 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 7703 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7704 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7705 cmp r0, #0 @ is resolved entry null? 7706 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ no, already resolved 77078: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7708 EXPORT_PC() @ resolve() could throw 7709 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7710 bl dvmResolveInstField @ r0<- resolved InstField ptr 7711 cmp r0, #0 @ success? 7712 bne .LOP_IPUT_OBJECT_VOLATILE_finish @ yes, finish up 7713 b common_exceptionThrown 7714 7715 7716/* ------------------------------ */ 7717 .balign 64 7718.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ 7719/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */ 7720/* File: armv5te/OP_SGET.S */ 7721 /* 7722 * General 32-bit SGET handler. 7723 * 7724 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 7725 */ 7726 /* op vAA, field@BBBB */ 7727 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7728 FETCH(r1, 1) @ r1<- field ref BBBB 7729 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7730 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7731 cmp r0, #0 @ is resolved entry null? 7732 beq .LOP_SGET_OBJECT_VOLATILE_resolve @ yes, do resolve 7733.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0 7734 ldr r1, [r0, #offStaticField_value] @ r1<- field value 7735 SMP_DMB @ acquiring load 7736 mov r2, rINST, lsr #8 @ r2<- AA 7737 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7738 SET_VREG(r1, r2) @ fp[AA]<- r1 7739 GET_INST_OPCODE(ip) @ extract opcode from rINST 7740 GOTO_OPCODE(ip) @ jump to next instruction 7741 7742 7743/* ------------------------------ */ 7744 .balign 64 7745.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ 7746/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */ 7747/* File: armv5te/OP_SPUT_OBJECT.S */ 7748 /* 7749 * 32-bit SPUT handler for objects 7750 * 7751 * for: sput-object, sput-object-volatile 7752 */ 7753 /* op vAA, field@BBBB */ 7754 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7755 FETCH(r1, 1) @ r1<- field ref BBBB 7756 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7757 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7758 cmp r0, #0 @ is resolved entry null? 7759 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ no, continue 7760 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 7761 EXPORT_PC() @ resolve() could throw, so export now 7762 ldr r0, [r9, #offMethod_clazz] @ r0<- method->clazz 7763 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 7764 cmp r0, #0 @ success? 7765 bne .LOP_SPUT_OBJECT_VOLATILE_finish @ yes, finish 7766 b common_exceptionThrown @ no, handle exception 7767 7768 7769 7770/* ------------------------------ */ 7771 .balign 64 7772.L_OP_UNUSED_FF: /* 0xff */ 7773/* File: armv5te/OP_UNUSED_FF.S */ 7774/* File: armv5te/unused.S */ 7775 bl common_abort 7776 7777 7778 7779 .balign 64 7780 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7781 .global dvmAsmInstructionEnd 7782dvmAsmInstructionEnd: 7783 7784/* 7785 * =========================================================================== 7786 * Sister implementations 7787 * =========================================================================== 7788 */ 7789 .global dvmAsmSisterStart 7790 .type dvmAsmSisterStart, %function 7791 .text 7792 .balign 4 7793dvmAsmSisterStart: 7794 7795/* continuation for OP_CONST_STRING */ 7796 7797 /* 7798 * Continuation if the String has not yet been resolved. 7799 * r1: BBBB (String ref) 7800 * r9: target register 7801 */ 7802.LOP_CONST_STRING_resolve: 7803 EXPORT_PC() 7804 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7805 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7806 bl dvmResolveString @ r0<- String reference 7807 cmp r0, #0 @ failed? 7808 beq common_exceptionThrown @ yup, handle the exception 7809 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7810 GET_INST_OPCODE(ip) @ extract opcode from rINST 7811 SET_VREG(r0, r9) @ vAA<- r0 7812 GOTO_OPCODE(ip) @ jump to next instruction 7813 7814/* continuation for OP_CONST_STRING_JUMBO */ 7815 7816 /* 7817 * Continuation if the String has not yet been resolved. 7818 * r1: BBBBBBBB (String ref) 7819 * r9: target register 7820 */ 7821.LOP_CONST_STRING_JUMBO_resolve: 7822 EXPORT_PC() 7823 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7824 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7825 bl dvmResolveString @ r0<- String reference 7826 cmp r0, #0 @ failed? 7827 beq common_exceptionThrown @ yup, handle the exception 7828 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7829 GET_INST_OPCODE(ip) @ extract opcode from rINST 7830 SET_VREG(r0, r9) @ vAA<- r0 7831 GOTO_OPCODE(ip) @ jump to next instruction 7832 7833/* continuation for OP_CONST_CLASS */ 7834 7835 /* 7836 * Continuation if the Class has not yet been resolved. 7837 * r1: BBBB (Class ref) 7838 * r9: target register 7839 */ 7840.LOP_CONST_CLASS_resolve: 7841 EXPORT_PC() 7842 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7843 mov r2, #1 @ r2<- true 7844 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7845 bl dvmResolveClass @ r0<- Class reference 7846 cmp r0, #0 @ failed? 7847 beq common_exceptionThrown @ yup, handle the exception 7848 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7849 GET_INST_OPCODE(ip) @ extract opcode from rINST 7850 SET_VREG(r0, r9) @ vAA<- r0 7851 GOTO_OPCODE(ip) @ jump to next instruction 7852 7853/* continuation for OP_CHECK_CAST */ 7854 7855 /* 7856 * Trivial test failed, need to perform full check. This is common. 7857 * r0 holds obj->clazz 7858 * r1 holds class resolved from BBBB 7859 * r9 holds object 7860 */ 7861.LOP_CHECK_CAST_fullcheck: 7862 bl dvmInstanceofNonTrivial @ r0<- boolean result 7863 cmp r0, #0 @ failed? 7864 bne .LOP_CHECK_CAST_okay @ no, success 7865 7866 @ A cast has failed. We need to throw a ClassCastException with the 7867 @ class of the object that failed to be cast. 7868 EXPORT_PC() @ about to throw 7869 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 7870 ldr r0, .LstrClassCastExceptionPtr 7871 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 7872 bl dvmThrowExceptionWithClassMessage 7873 b common_exceptionThrown 7874 7875 /* 7876 * Resolution required. This is the least-likely path. 7877 * 7878 * r2 holds BBBB 7879 * r9 holds object 7880 */ 7881.LOP_CHECK_CAST_resolve: 7882 EXPORT_PC() @ resolve() could throw 7883 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7884 mov r1, r2 @ r1<- BBBB 7885 mov r2, #0 @ r2<- false 7886 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7887 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7888 cmp r0, #0 @ got null? 7889 beq common_exceptionThrown @ yes, handle exception 7890 mov r1, r0 @ r1<- class resolved from BBB 7891 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7892 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7893 7894.LstrClassCastExceptionPtr: 7895 .word .LstrClassCastException 7896 7897/* continuation for OP_INSTANCE_OF */ 7898 7899 /* 7900 * Trivial test failed, need to perform full check. This is common. 7901 * r0 holds obj->clazz 7902 * r1 holds class resolved from BBBB 7903 * r9 holds A 7904 */ 7905.LOP_INSTANCE_OF_fullcheck: 7906 bl dvmInstanceofNonTrivial @ r0<- boolean result 7907 @ fall through to OP_INSTANCE_OF_store 7908 7909 /* 7910 * r0 holds boolean result 7911 * r9 holds A 7912 */ 7913.LOP_INSTANCE_OF_store: 7914 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7915 SET_VREG(r0, r9) @ vA<- r0 7916 GET_INST_OPCODE(ip) @ extract opcode from rINST 7917 GOTO_OPCODE(ip) @ jump to next instruction 7918 7919 /* 7920 * Trivial test succeeded, save and bail. 7921 * r9 holds A 7922 */ 7923.LOP_INSTANCE_OF_trivial: 7924 mov r0, #1 @ indicate success 7925 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7926 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7927 SET_VREG(r0, r9) @ vA<- r0 7928 GET_INST_OPCODE(ip) @ extract opcode from rINST 7929 GOTO_OPCODE(ip) @ jump to next instruction 7930 7931 /* 7932 * Resolution required. This is the least-likely path. 7933 * 7934 * r3 holds BBBB 7935 * r9 holds A 7936 */ 7937.LOP_INSTANCE_OF_resolve: 7938 EXPORT_PC() @ resolve() could throw 7939 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7940 mov r1, r3 @ r1<- BBBB 7941 mov r2, #1 @ r2<- true 7942 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7943 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7944 cmp r0, #0 @ got null? 7945 beq common_exceptionThrown @ yes, handle exception 7946 mov r1, r0 @ r1<- class resolved from BBB 7947 mov r3, rINST, lsr #12 @ r3<- B 7948 GET_VREG(r0, r3) @ r0<- vB (object) 7949 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7950 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7951 7952/* continuation for OP_NEW_INSTANCE */ 7953 7954 .balign 32 @ minimize cache lines 7955.LOP_NEW_INSTANCE_finish: @ r0=new object 7956 mov r3, rINST, lsr #8 @ r3<- AA 7957 cmp r0, #0 @ failed? 7958 beq common_exceptionThrown @ yes, handle the exception 7959 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7960 GET_INST_OPCODE(ip) @ extract opcode from rINST 7961 SET_VREG(r0, r3) @ vAA<- r0 7962 GOTO_OPCODE(ip) @ jump to next instruction 7963 7964 /* 7965 * Class initialization required. 7966 * 7967 * r0 holds class object 7968 */ 7969.LOP_NEW_INSTANCE_needinit: 7970 mov r9, r0 @ save r0 7971 bl dvmInitClass @ initialize class 7972 cmp r0, #0 @ check boolean result 7973 mov r0, r9 @ restore r0 7974 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7975 b common_exceptionThrown @ failed, deal with init exception 7976 7977 /* 7978 * Resolution required. This is the least-likely path. 7979 * 7980 * r1 holds BBBB 7981 */ 7982.LOP_NEW_INSTANCE_resolve: 7983 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7984 mov r2, #0 @ r2<- false 7985 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7986 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7987 cmp r0, #0 @ got null? 7988 bne .LOP_NEW_INSTANCE_resolved @ no, continue 7989 b common_exceptionThrown @ yes, handle exception 7990 7991.LstrInstantiationErrorPtr: 7992 .word .LstrInstantiationError 7993 7994/* continuation for OP_NEW_ARRAY */ 7995 7996 7997 /* 7998 * Resolve class. (This is an uncommon case.) 7999 * 8000 * r1 holds array length 8001 * r2 holds class ref CCCC 8002 */ 8003.LOP_NEW_ARRAY_resolve: 8004 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8005 mov r9, r1 @ r9<- length (save) 8006 mov r1, r2 @ r1<- CCCC 8007 mov r2, #0 @ r2<- false 8008 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8009 bl dvmResolveClass @ r0<- call(clazz, ref) 8010 cmp r0, #0 @ got null? 8011 mov r1, r9 @ r1<- length (restore) 8012 beq common_exceptionThrown @ yes, handle exception 8013 @ fall through to OP_NEW_ARRAY_finish 8014 8015 /* 8016 * Finish allocation. 8017 * 8018 * r0 holds class 8019 * r1 holds array length 8020 */ 8021.LOP_NEW_ARRAY_finish: 8022 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 8023 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 8024 cmp r0, #0 @ failed? 8025 mov r2, rINST, lsr #8 @ r2<- A+ 8026 beq common_exceptionThrown @ yes, handle the exception 8027 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8028 and r2, r2, #15 @ r2<- A 8029 GET_INST_OPCODE(ip) @ extract opcode from rINST 8030 SET_VREG(r0, r2) @ vA<- r0 8031 GOTO_OPCODE(ip) @ jump to next instruction 8032 8033/* continuation for OP_FILLED_NEW_ARRAY */ 8034 8035 /* 8036 * On entry: 8037 * r0 holds array class 8038 * r10 holds AA or BA 8039 */ 8040.LOP_FILLED_NEW_ARRAY_continue: 8041 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8042 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8043 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 8044 .if 0 8045 mov r1, r10 @ r1<- AA (length) 8046 .else 8047 mov r1, r10, lsr #4 @ r1<- B (length) 8048 .endif 8049 cmp rINST, #'I' @ array of ints? 8050 cmpne rINST, #'L' @ array of objects? 8051 cmpne rINST, #'[' @ array of arrays? 8052 mov r9, r1 @ save length in r9 8053 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 8054 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8055 cmp r0, #0 @ null return? 8056 beq common_exceptionThrown @ alloc failed, handle exception 8057 8058 FETCH(r1, 2) @ r1<- FEDC or CCCC 8059 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8060 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 8061 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8062 subs r9, r9, #1 @ length--, check for neg 8063 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8064 bmi 2f @ was zero, bail 8065 8066 @ copy values from registers into the array 8067 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8068 .if 0 8069 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 80701: ldr r3, [r2], #4 @ r3<- *r2++ 8071 subs r9, r9, #1 @ count-- 8072 str r3, [r0], #4 @ *contents++ = vX 8073 bpl 1b 8074 @ continue at 2 8075 .else 8076 cmp r9, #4 @ length was initially 5? 8077 and r2, r10, #15 @ r2<- A 8078 bne 1f @ <= 4 args, branch 8079 GET_VREG(r3, r2) @ r3<- vA 8080 sub r9, r9, #1 @ count-- 8081 str r3, [r0, #16] @ contents[4] = vA 80821: and r2, r1, #15 @ r2<- F/E/D/C 8083 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8084 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8085 subs r9, r9, #1 @ count-- 8086 str r3, [r0], #4 @ *contents++ = vX 8087 bpl 1b 8088 @ continue at 2 8089 .endif 8090 80912: 8092 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 8093 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 8094 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8095 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8096 cmp r1, #'I' @ Is int array? 8097 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 8098 GOTO_OPCODE(ip) @ execute it 8099 8100 /* 8101 * Throw an exception indicating that we have not implemented this 8102 * mode of filled-new-array. 8103 */ 8104.LOP_FILLED_NEW_ARRAY_notimpl: 8105 ldr r0, .L_strInternalError 8106 ldr r1, .L_strFilledNewArrayNotImpl 8107 bl dvmThrowException 8108 b common_exceptionThrown 8109 8110 .if (!0) @ define in one or the other, not both 8111.L_strFilledNewArrayNotImpl: 8112 .word .LstrFilledNewArrayNotImpl 8113.L_strInternalError: 8114 .word .LstrInternalError 8115 .endif 8116 8117/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 8118 8119 /* 8120 * On entry: 8121 * r0 holds array class 8122 * r10 holds AA or BA 8123 */ 8124.LOP_FILLED_NEW_ARRAY_RANGE_continue: 8125 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8126 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8127 ldrb rINST, [r3, #1] @ rINST<- descriptor[1] 8128 .if 1 8129 mov r1, r10 @ r1<- AA (length) 8130 .else 8131 mov r1, r10, lsr #4 @ r1<- B (length) 8132 .endif 8133 cmp rINST, #'I' @ array of ints? 8134 cmpne rINST, #'L' @ array of objects? 8135 cmpne rINST, #'[' @ array of arrays? 8136 mov r9, r1 @ save length in r9 8137 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 8138 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8139 cmp r0, #0 @ null return? 8140 beq common_exceptionThrown @ alloc failed, handle exception 8141 8142 FETCH(r1, 2) @ r1<- FEDC or CCCC 8143 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8144 str rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type 8145 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8146 subs r9, r9, #1 @ length--, check for neg 8147 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8148 bmi 2f @ was zero, bail 8149 8150 @ copy values from registers into the array 8151 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8152 .if 1 8153 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 81541: ldr r3, [r2], #4 @ r3<- *r2++ 8155 subs r9, r9, #1 @ count-- 8156 str r3, [r0], #4 @ *contents++ = vX 8157 bpl 1b 8158 @ continue at 2 8159 .else 8160 cmp r9, #4 @ length was initially 5? 8161 and r2, r10, #15 @ r2<- A 8162 bne 1f @ <= 4 args, branch 8163 GET_VREG(r3, r2) @ r3<- vA 8164 sub r9, r9, #1 @ count-- 8165 str r3, [r0, #16] @ contents[4] = vA 81661: and r2, r1, #15 @ r2<- F/E/D/C 8167 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8168 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8169 subs r9, r9, #1 @ count-- 8170 str r3, [r0], #4 @ *contents++ = vX 8171 bpl 1b 8172 @ continue at 2 8173 .endif 8174 81752: 8176 ldr r0, [rGLUE, #offGlue_retval] @ r0<- object 8177 ldr r1, [rGLUE, #offGlue_retval+4] @ r1<- type 8178 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8179 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8180 cmp r1, #'I' @ Is int array? 8181 strneb r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head 8182 GOTO_OPCODE(ip) @ execute it 8183 8184 /* 8185 * Throw an exception indicating that we have not implemented this 8186 * mode of filled-new-array. 8187 */ 8188.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8189 ldr r0, .L_strInternalError 8190 ldr r1, .L_strFilledNewArrayNotImpl 8191 bl dvmThrowException 8192 b common_exceptionThrown 8193 8194 .if (!1) @ define in one or the other, not both 8195.L_strFilledNewArrayNotImpl: 8196 .word .LstrFilledNewArrayNotImpl 8197.L_strInternalError: 8198 .word .LstrInternalError 8199 .endif 8200 8201/* continuation for OP_CMPL_FLOAT */ 8202.LOP_CMPL_FLOAT_finish: 8203 SET_VREG(r0, r9) @ vAA<- r0 8204 GOTO_OPCODE(ip) @ jump to next instruction 8205 8206/* continuation for OP_CMPG_FLOAT */ 8207.LOP_CMPG_FLOAT_finish: 8208 SET_VREG(r0, r9) @ vAA<- r0 8209 GOTO_OPCODE(ip) @ jump to next instruction 8210 8211/* continuation for OP_CMPL_DOUBLE */ 8212.LOP_CMPL_DOUBLE_finish: 8213 SET_VREG(r0, r9) @ vAA<- r0 8214 GOTO_OPCODE(ip) @ jump to next instruction 8215 8216/* continuation for OP_CMPG_DOUBLE */ 8217.LOP_CMPG_DOUBLE_finish: 8218 SET_VREG(r0, r9) @ vAA<- r0 8219 GOTO_OPCODE(ip) @ jump to next instruction 8220 8221/* continuation for OP_CMP_LONG */ 8222 8223.LOP_CMP_LONG_less: 8224 mvn r1, #0 @ r1<- -1 8225 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8226 @ instead, we just replicate the tail end. 8227 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8228 SET_VREG(r1, r9) @ vAA<- r1 8229 GET_INST_OPCODE(ip) @ extract opcode from rINST 8230 GOTO_OPCODE(ip) @ jump to next instruction 8231 8232.LOP_CMP_LONG_greater: 8233 mov r1, #1 @ r1<- 1 8234 @ fall through to _finish 8235 8236.LOP_CMP_LONG_finish: 8237 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8238 SET_VREG(r1, r9) @ vAA<- r1 8239 GET_INST_OPCODE(ip) @ extract opcode from rINST 8240 GOTO_OPCODE(ip) @ jump to next instruction 8241 8242/* continuation for OP_AGET_WIDE */ 8243 8244.LOP_AGET_WIDE_finish: 8245 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8246 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8247 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8248 GET_INST_OPCODE(ip) @ extract opcode from rINST 8249 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8250 GOTO_OPCODE(ip) @ jump to next instruction 8251 8252/* continuation for OP_APUT_WIDE */ 8253 8254.LOP_APUT_WIDE_finish: 8255 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8256 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8257 GET_INST_OPCODE(ip) @ extract opcode from rINST 8258 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8259 GOTO_OPCODE(ip) @ jump to next instruction 8260 8261/* continuation for OP_APUT_OBJECT */ 8262 /* 8263 * On entry: 8264 * rINST = vBB (arrayObj) 8265 * r9 = vAA (obj) 8266 * r10 = offset into array (vBB + vCC * width) 8267 */ 8268.LOP_APUT_OBJECT_finish: 8269 cmp r9, #0 @ storing null reference? 8270 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8271 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8272 ldr r1, [rINST, #offObject_clazz] @ r1<- arrayObj->clazz 8273 bl dvmCanPutArrayElement @ test object type vs. array type 8274 cmp r0, #0 @ okay? 8275 beq common_errArrayStore @ no 8276 mov r1, rINST @ r1<- arrayObj 8277 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8278 ldr r2, [rGLUE, #offGlue_cardTable] @ get biased CT base 8279 add r10, #offArrayObject_contents @ r0<- pointer to slot 8280 GET_INST_OPCODE(ip) @ extract opcode from rINST 8281 str r9, [r10] @ vBB[vCC]<- vAA 8282 strb r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head 8283 GOTO_OPCODE(ip) @ jump to next instruction 8284.LOP_APUT_OBJECT_skip_check: 8285 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8286 GET_INST_OPCODE(ip) @ extract opcode from rINST 8287 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8288 GOTO_OPCODE(ip) @ jump to next instruction 8289 8290/* continuation for OP_IGET */ 8291 8292 /* 8293 * Currently: 8294 * r0 holds resolved field 8295 * r9 holds object 8296 */ 8297.LOP_IGET_finish: 8298 @bl common_squeak0 8299 cmp r9, #0 @ check object for null 8300 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8301 beq common_errNullObject @ object was null 8302 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8303 @ no-op @ acquiring load 8304 mov r2, rINST, lsr #8 @ r2<- A+ 8305 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8306 and r2, r2, #15 @ r2<- A 8307 GET_INST_OPCODE(ip) @ extract opcode from rINST 8308 SET_VREG(r0, r2) @ fp[A]<- r0 8309 GOTO_OPCODE(ip) @ jump to next instruction 8310 8311/* continuation for OP_IGET_WIDE */ 8312 8313 /* 8314 * Currently: 8315 * r0 holds resolved field 8316 * r9 holds object 8317 */ 8318.LOP_IGET_WIDE_finish: 8319 cmp r9, #0 @ check object for null 8320 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8321 beq common_errNullObject @ object was null 8322 .if 0 8323 add r0, r9, r3 @ r0<- address of field 8324 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 8325 .else 8326 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8327 .endif 8328 mov r2, rINST, lsr #8 @ r2<- A+ 8329 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8330 and r2, r2, #15 @ r2<- A 8331 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8332 GET_INST_OPCODE(ip) @ extract opcode from rINST 8333 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8334 GOTO_OPCODE(ip) @ jump to next instruction 8335 8336/* continuation for OP_IGET_OBJECT */ 8337 8338 /* 8339 * Currently: 8340 * r0 holds resolved field 8341 * r9 holds object 8342 */ 8343.LOP_IGET_OBJECT_finish: 8344 @bl common_squeak0 8345 cmp r9, #0 @ check object for null 8346 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8347 beq common_errNullObject @ object was null 8348 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8349 @ no-op @ acquiring load 8350 mov r2, rINST, lsr #8 @ r2<- A+ 8351 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8352 and r2, r2, #15 @ r2<- A 8353 GET_INST_OPCODE(ip) @ extract opcode from rINST 8354 SET_VREG(r0, r2) @ fp[A]<- r0 8355 GOTO_OPCODE(ip) @ jump to next instruction 8356 8357/* continuation for OP_IGET_BOOLEAN */ 8358 8359 /* 8360 * Currently: 8361 * r0 holds resolved field 8362 * r9 holds object 8363 */ 8364.LOP_IGET_BOOLEAN_finish: 8365 @bl common_squeak1 8366 cmp r9, #0 @ check object for null 8367 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8368 beq common_errNullObject @ object was null 8369 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8370 @ no-op @ acquiring load 8371 mov r2, rINST, lsr #8 @ r2<- A+ 8372 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8373 and r2, r2, #15 @ r2<- A 8374 GET_INST_OPCODE(ip) @ extract opcode from rINST 8375 SET_VREG(r0, r2) @ fp[A]<- r0 8376 GOTO_OPCODE(ip) @ jump to next instruction 8377 8378/* continuation for OP_IGET_BYTE */ 8379 8380 /* 8381 * Currently: 8382 * r0 holds resolved field 8383 * r9 holds object 8384 */ 8385.LOP_IGET_BYTE_finish: 8386 @bl common_squeak2 8387 cmp r9, #0 @ check object for null 8388 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8389 beq common_errNullObject @ object was null 8390 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8391 @ no-op @ acquiring load 8392 mov r2, rINST, lsr #8 @ r2<- A+ 8393 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8394 and r2, r2, #15 @ r2<- A 8395 GET_INST_OPCODE(ip) @ extract opcode from rINST 8396 SET_VREG(r0, r2) @ fp[A]<- r0 8397 GOTO_OPCODE(ip) @ jump to next instruction 8398 8399/* continuation for OP_IGET_CHAR */ 8400 8401 /* 8402 * Currently: 8403 * r0 holds resolved field 8404 * r9 holds object 8405 */ 8406.LOP_IGET_CHAR_finish: 8407 @bl common_squeak3 8408 cmp r9, #0 @ check object for null 8409 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8410 beq common_errNullObject @ object was null 8411 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8412 @ no-op @ acquiring load 8413 mov r2, rINST, lsr #8 @ r2<- A+ 8414 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8415 and r2, r2, #15 @ r2<- A 8416 GET_INST_OPCODE(ip) @ extract opcode from rINST 8417 SET_VREG(r0, r2) @ fp[A]<- r0 8418 GOTO_OPCODE(ip) @ jump to next instruction 8419 8420/* continuation for OP_IGET_SHORT */ 8421 8422 /* 8423 * Currently: 8424 * r0 holds resolved field 8425 * r9 holds object 8426 */ 8427.LOP_IGET_SHORT_finish: 8428 @bl common_squeak4 8429 cmp r9, #0 @ check object for null 8430 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8431 beq common_errNullObject @ object was null 8432 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8433 @ no-op @ acquiring load 8434 mov r2, rINST, lsr #8 @ r2<- A+ 8435 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8436 and r2, r2, #15 @ r2<- A 8437 GET_INST_OPCODE(ip) @ extract opcode from rINST 8438 SET_VREG(r0, r2) @ fp[A]<- r0 8439 GOTO_OPCODE(ip) @ jump to next instruction 8440 8441/* continuation for OP_IPUT */ 8442 8443 /* 8444 * Currently: 8445 * r0 holds resolved field 8446 * r9 holds object 8447 */ 8448.LOP_IPUT_finish: 8449 @bl common_squeak0 8450 mov r1, rINST, lsr #8 @ r1<- A+ 8451 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8452 and r1, r1, #15 @ r1<- A 8453 cmp r9, #0 @ check object for null 8454 GET_VREG(r0, r1) @ r0<- fp[A] 8455 beq common_errNullObject @ object was null 8456 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8457 GET_INST_OPCODE(ip) @ extract opcode from rINST 8458 @ no-op @ releasing store 8459 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8460 GOTO_OPCODE(ip) @ jump to next instruction 8461 8462/* continuation for OP_IPUT_WIDE */ 8463 8464 /* 8465 * Currently: 8466 * r0 holds resolved field 8467 * r9 holds object 8468 */ 8469.LOP_IPUT_WIDE_finish: 8470 mov r2, rINST, lsr #8 @ r2<- A+ 8471 cmp r9, #0 @ check object for null 8472 and r2, r2, #15 @ r2<- A 8473 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8474 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8475 beq common_errNullObject @ object was null 8476 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8477 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8478 GET_INST_OPCODE(r10) @ extract opcode from rINST 8479 .if 0 8480 add r2, r9, r3 @ r2<- target address 8481 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 8482 .else 8483 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 8484 .endif 8485 GOTO_OPCODE(r10) @ jump to next instruction 8486 8487/* continuation for OP_IPUT_OBJECT */ 8488 8489 /* 8490 * Currently: 8491 * r0 holds resolved field 8492 * r9 holds object 8493 */ 8494.LOP_IPUT_OBJECT_finish: 8495 @bl common_squeak0 8496 mov r1, rINST, lsr #8 @ r1<- A+ 8497 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8498 and r1, r1, #15 @ r1<- A 8499 cmp r9, #0 @ check object for null 8500 GET_VREG(r0, r1) @ r0<- fp[A] 8501 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8502 beq common_errNullObject @ object was null 8503 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8504 GET_INST_OPCODE(ip) @ extract opcode from rINST 8505 @ no-op @ releasing store 8506 str r0, [r9, r3] @ obj.field (32 bits)<- r0 8507 cmp r0, #0 @ stored a null reference? 8508 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card if not 8509 GOTO_OPCODE(ip) @ jump to next instruction 8510 8511/* continuation for OP_IPUT_BOOLEAN */ 8512 8513 /* 8514 * Currently: 8515 * r0 holds resolved field 8516 * r9 holds object 8517 */ 8518.LOP_IPUT_BOOLEAN_finish: 8519 @bl common_squeak1 8520 mov r1, rINST, lsr #8 @ r1<- A+ 8521 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8522 and r1, r1, #15 @ r1<- A 8523 cmp r9, #0 @ check object for null 8524 GET_VREG(r0, r1) @ r0<- fp[A] 8525 beq common_errNullObject @ object was null 8526 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8527 GET_INST_OPCODE(ip) @ extract opcode from rINST 8528 @ no-op @ releasing store 8529 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8530 GOTO_OPCODE(ip) @ jump to next instruction 8531 8532/* continuation for OP_IPUT_BYTE */ 8533 8534 /* 8535 * Currently: 8536 * r0 holds resolved field 8537 * r9 holds object 8538 */ 8539.LOP_IPUT_BYTE_finish: 8540 @bl common_squeak2 8541 mov r1, rINST, lsr #8 @ r1<- A+ 8542 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8543 and r1, r1, #15 @ r1<- A 8544 cmp r9, #0 @ check object for null 8545 GET_VREG(r0, r1) @ r0<- fp[A] 8546 beq common_errNullObject @ object was null 8547 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8548 GET_INST_OPCODE(ip) @ extract opcode from rINST 8549 @ no-op @ releasing store 8550 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8551 GOTO_OPCODE(ip) @ jump to next instruction 8552 8553/* continuation for OP_IPUT_CHAR */ 8554 8555 /* 8556 * Currently: 8557 * r0 holds resolved field 8558 * r9 holds object 8559 */ 8560.LOP_IPUT_CHAR_finish: 8561 @bl common_squeak3 8562 mov r1, rINST, lsr #8 @ r1<- A+ 8563 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8564 and r1, r1, #15 @ r1<- A 8565 cmp r9, #0 @ check object for null 8566 GET_VREG(r0, r1) @ r0<- fp[A] 8567 beq common_errNullObject @ object was null 8568 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8569 GET_INST_OPCODE(ip) @ extract opcode from rINST 8570 @ no-op @ releasing store 8571 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8572 GOTO_OPCODE(ip) @ jump to next instruction 8573 8574/* continuation for OP_IPUT_SHORT */ 8575 8576 /* 8577 * Currently: 8578 * r0 holds resolved field 8579 * r9 holds object 8580 */ 8581.LOP_IPUT_SHORT_finish: 8582 @bl common_squeak4 8583 mov r1, rINST, lsr #8 @ r1<- A+ 8584 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8585 and r1, r1, #15 @ r1<- A 8586 cmp r9, #0 @ check object for null 8587 GET_VREG(r0, r1) @ r0<- fp[A] 8588 beq common_errNullObject @ object was null 8589 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8590 GET_INST_OPCODE(ip) @ extract opcode from rINST 8591 @ no-op @ releasing store 8592 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8593 GOTO_OPCODE(ip) @ jump to next instruction 8594 8595/* continuation for OP_SGET */ 8596 8597 /* 8598 * Continuation if the field has not yet been resolved. 8599 * r1: BBBB field ref 8600 */ 8601.LOP_SGET_resolve: 8602 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8603 EXPORT_PC() @ resolve() could throw, so export now 8604 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8605 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8606 cmp r0, #0 @ success? 8607 bne .LOP_SGET_finish @ yes, finish 8608 b common_exceptionThrown @ no, handle exception 8609 8610/* continuation for OP_SGET_WIDE */ 8611 8612 /* 8613 * Continuation if the field has not yet been resolved. 8614 * r1: BBBB field ref 8615 * 8616 * Returns StaticField pointer in r0. 8617 */ 8618.LOP_SGET_WIDE_resolve: 8619 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8620 EXPORT_PC() @ resolve() could throw, so export now 8621 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8622 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8623 cmp r0, #0 @ success? 8624 bne .LOP_SGET_WIDE_finish @ yes, finish 8625 b common_exceptionThrown @ no, handle exception 8626 8627/* continuation for OP_SGET_OBJECT */ 8628 8629 /* 8630 * Continuation if the field has not yet been resolved. 8631 * r1: BBBB field ref 8632 */ 8633.LOP_SGET_OBJECT_resolve: 8634 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8635 EXPORT_PC() @ resolve() could throw, so export now 8636 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8637 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8638 cmp r0, #0 @ success? 8639 bne .LOP_SGET_OBJECT_finish @ yes, finish 8640 b common_exceptionThrown @ no, handle exception 8641 8642/* continuation for OP_SGET_BOOLEAN */ 8643 8644 /* 8645 * Continuation if the field has not yet been resolved. 8646 * r1: BBBB field ref 8647 */ 8648.LOP_SGET_BOOLEAN_resolve: 8649 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8650 EXPORT_PC() @ resolve() could throw, so export now 8651 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8652 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8653 cmp r0, #0 @ success? 8654 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8655 b common_exceptionThrown @ no, handle exception 8656 8657/* continuation for OP_SGET_BYTE */ 8658 8659 /* 8660 * Continuation if the field has not yet been resolved. 8661 * r1: BBBB field ref 8662 */ 8663.LOP_SGET_BYTE_resolve: 8664 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8665 EXPORT_PC() @ resolve() could throw, so export now 8666 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8667 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8668 cmp r0, #0 @ success? 8669 bne .LOP_SGET_BYTE_finish @ yes, finish 8670 b common_exceptionThrown @ no, handle exception 8671 8672/* continuation for OP_SGET_CHAR */ 8673 8674 /* 8675 * Continuation if the field has not yet been resolved. 8676 * r1: BBBB field ref 8677 */ 8678.LOP_SGET_CHAR_resolve: 8679 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8680 EXPORT_PC() @ resolve() could throw, so export now 8681 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8682 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8683 cmp r0, #0 @ success? 8684 bne .LOP_SGET_CHAR_finish @ yes, finish 8685 b common_exceptionThrown @ no, handle exception 8686 8687/* continuation for OP_SGET_SHORT */ 8688 8689 /* 8690 * Continuation if the field has not yet been resolved. 8691 * r1: BBBB field ref 8692 */ 8693.LOP_SGET_SHORT_resolve: 8694 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8695 EXPORT_PC() @ resolve() could throw, so export now 8696 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8697 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8698 cmp r0, #0 @ success? 8699 bne .LOP_SGET_SHORT_finish @ yes, finish 8700 b common_exceptionThrown @ no, handle exception 8701 8702/* continuation for OP_SPUT */ 8703 8704 /* 8705 * Continuation if the field has not yet been resolved. 8706 * r1: BBBB field ref 8707 */ 8708.LOP_SPUT_resolve: 8709 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8710 EXPORT_PC() @ resolve() could throw, so export now 8711 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8712 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8713 cmp r0, #0 @ success? 8714 bne .LOP_SPUT_finish @ yes, finish 8715 b common_exceptionThrown @ no, handle exception 8716 8717/* continuation for OP_SPUT_WIDE */ 8718 8719 /* 8720 * Continuation if the field has not yet been resolved. 8721 * r1: BBBB field ref 8722 * r9: &fp[AA] 8723 * 8724 * Returns StaticField pointer in r2. 8725 */ 8726.LOP_SPUT_WIDE_resolve: 8727 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8728 EXPORT_PC() @ resolve() could throw, so export now 8729 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8730 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8731 cmp r0, #0 @ success? 8732 mov r2, r0 @ copy to r2 8733 bne .LOP_SPUT_WIDE_finish @ yes, finish 8734 b common_exceptionThrown @ no, handle exception 8735 8736/* continuation for OP_SPUT_OBJECT */ 8737.LOP_SPUT_OBJECT_finish: @ field ptr in r0 8738 mov r2, rINST, lsr #8 @ r2<- AA 8739 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8740 GET_VREG(r1, r2) @ r1<- fp[AA] 8741 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 8742 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz 8743 GET_INST_OPCODE(ip) @ extract opcode from rINST 8744 @ no-op @ releasing store 8745 str r1, [r0, #offStaticField_value] @ field<- vAA 8746 cmp r1, #0 @ stored a null object? 8747 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 8748 GOTO_OPCODE(ip) @ jump to next instruction 8749 8750/* continuation for OP_SPUT_BOOLEAN */ 8751 8752 /* 8753 * Continuation if the field has not yet been resolved. 8754 * r1: BBBB field ref 8755 */ 8756.LOP_SPUT_BOOLEAN_resolve: 8757 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8758 EXPORT_PC() @ resolve() could throw, so export now 8759 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8760 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8761 cmp r0, #0 @ success? 8762 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 8763 b common_exceptionThrown @ no, handle exception 8764 8765/* continuation for OP_SPUT_BYTE */ 8766 8767 /* 8768 * Continuation if the field has not yet been resolved. 8769 * r1: BBBB field ref 8770 */ 8771.LOP_SPUT_BYTE_resolve: 8772 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8773 EXPORT_PC() @ resolve() could throw, so export now 8774 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8775 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8776 cmp r0, #0 @ success? 8777 bne .LOP_SPUT_BYTE_finish @ yes, finish 8778 b common_exceptionThrown @ no, handle exception 8779 8780/* continuation for OP_SPUT_CHAR */ 8781 8782 /* 8783 * Continuation if the field has not yet been resolved. 8784 * r1: BBBB field ref 8785 */ 8786.LOP_SPUT_CHAR_resolve: 8787 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8788 EXPORT_PC() @ resolve() could throw, so export now 8789 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8790 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8791 cmp r0, #0 @ success? 8792 bne .LOP_SPUT_CHAR_finish @ yes, finish 8793 b common_exceptionThrown @ no, handle exception 8794 8795/* continuation for OP_SPUT_SHORT */ 8796 8797 /* 8798 * Continuation if the field has not yet been resolved. 8799 * r1: BBBB field ref 8800 */ 8801.LOP_SPUT_SHORT_resolve: 8802 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8803 EXPORT_PC() @ resolve() could throw, so export now 8804 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8805 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8806 cmp r0, #0 @ success? 8807 bne .LOP_SPUT_SHORT_finish @ yes, finish 8808 b common_exceptionThrown @ no, handle exception 8809 8810/* continuation for OP_INVOKE_VIRTUAL */ 8811 8812 /* 8813 * At this point: 8814 * r0 = resolved base method 8815 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8816 */ 8817.LOP_INVOKE_VIRTUAL_continue: 8818 GET_VREG(r1, r10) @ r1<- "this" ptr 8819 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8820 cmp r1, #0 @ is "this" null? 8821 beq common_errNullObject @ null "this", throw exception 8822 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8823 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8824 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8825 bl common_invokeMethodNoRange @ continue on 8826 8827/* continuation for OP_INVOKE_SUPER */ 8828 8829 /* 8830 * At this point: 8831 * r0 = resolved base method 8832 * r9 = method->clazz 8833 */ 8834.LOP_INVOKE_SUPER_continue: 8835 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8836 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8837 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8838 EXPORT_PC() @ must export for invoke 8839 cmp r2, r3 @ compare (methodIndex, vtableCount) 8840 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 8841 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8842 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8843 bl common_invokeMethodNoRange @ continue on 8844 8845.LOP_INVOKE_SUPER_resolve: 8846 mov r0, r9 @ r0<- method->clazz 8847 mov r2, #METHOD_VIRTUAL @ resolver method type 8848 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8849 cmp r0, #0 @ got null? 8850 bne .LOP_INVOKE_SUPER_continue @ no, continue 8851 b common_exceptionThrown @ yes, handle exception 8852 8853 /* 8854 * Throw a NoSuchMethodError with the method name as the message. 8855 * r0 = resolved base method 8856 */ 8857.LOP_INVOKE_SUPER_nsm: 8858 ldr r1, [r0, #offMethod_name] @ r1<- method name 8859 b common_errNoSuchMethod 8860 8861/* continuation for OP_INVOKE_DIRECT */ 8862 8863 /* 8864 * On entry: 8865 * r1 = reference (BBBB or CCCC) 8866 * r10 = "this" register 8867 */ 8868.LOP_INVOKE_DIRECT_resolve: 8869 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8870 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8871 mov r2, #METHOD_DIRECT @ resolver method type 8872 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8873 cmp r0, #0 @ got null? 8874 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8875 bne .LOP_INVOKE_DIRECT_finish @ no, continue 8876 b common_exceptionThrown @ yes, handle exception 8877 8878/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 8879 8880 /* 8881 * At this point: 8882 * r0 = resolved base method 8883 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8884 */ 8885.LOP_INVOKE_VIRTUAL_RANGE_continue: 8886 GET_VREG(r1, r10) @ r1<- "this" ptr 8887 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8888 cmp r1, #0 @ is "this" null? 8889 beq common_errNullObject @ null "this", throw exception 8890 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8891 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8892 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8893 bl common_invokeMethodRange @ continue on 8894 8895/* continuation for OP_INVOKE_SUPER_RANGE */ 8896 8897 /* 8898 * At this point: 8899 * r0 = resolved base method 8900 * r9 = method->clazz 8901 */ 8902.LOP_INVOKE_SUPER_RANGE_continue: 8903 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8904 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8905 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8906 EXPORT_PC() @ must export for invoke 8907 cmp r2, r3 @ compare (methodIndex, vtableCount) 8908 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 8909 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8910 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8911 bl common_invokeMethodRange @ continue on 8912 8913.LOP_INVOKE_SUPER_RANGE_resolve: 8914 mov r0, r9 @ r0<- method->clazz 8915 mov r2, #METHOD_VIRTUAL @ resolver method type 8916 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8917 cmp r0, #0 @ got null? 8918 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 8919 b common_exceptionThrown @ yes, handle exception 8920 8921 /* 8922 * Throw a NoSuchMethodError with the method name as the message. 8923 * r0 = resolved base method 8924 */ 8925.LOP_INVOKE_SUPER_RANGE_nsm: 8926 ldr r1, [r0, #offMethod_name] @ r1<- method name 8927 b common_errNoSuchMethod 8928 8929/* continuation for OP_INVOKE_DIRECT_RANGE */ 8930 8931 /* 8932 * On entry: 8933 * r1 = reference (BBBB or CCCC) 8934 * r10 = "this" register 8935 */ 8936.LOP_INVOKE_DIRECT_RANGE_resolve: 8937 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8938 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8939 mov r2, #METHOD_DIRECT @ resolver method type 8940 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8941 cmp r0, #0 @ got null? 8942 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8943 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 8944 b common_exceptionThrown @ yes, handle exception 8945 8946/* continuation for OP_FLOAT_TO_LONG */ 8947/* 8948 * Convert the float in r0 to a long in r0/r1. 8949 * 8950 * We have to clip values to long min/max per the specification. The 8951 * expected common case is a "reasonable" value that converts directly 8952 * to modest integer. The EABI convert function isn't doing this for us. 8953 */ 8954f2l_doconv: 8955 stmfd sp!, {r4, lr} 8956 mov r1, #0x5f000000 @ (float)maxlong 8957 mov r4, r0 8958 bl __aeabi_fcmpge @ is arg >= maxlong? 8959 cmp r0, #0 @ nonzero == yes 8960 mvnne r0, #0 @ return maxlong (7fffffff) 8961 mvnne r1, #0x80000000 8962 ldmnefd sp!, {r4, pc} 8963 8964 mov r0, r4 @ recover arg 8965 mov r1, #0xdf000000 @ (float)minlong 8966 bl __aeabi_fcmple @ is arg <= minlong? 8967 cmp r0, #0 @ nonzero == yes 8968 movne r0, #0 @ return minlong (80000000) 8969 movne r1, #0x80000000 8970 ldmnefd sp!, {r4, pc} 8971 8972 mov r0, r4 @ recover arg 8973 mov r1, r4 8974 bl __aeabi_fcmpeq @ is arg == self? 8975 cmp r0, #0 @ zero == no 8976 moveq r1, #0 @ return zero for NaN 8977 ldmeqfd sp!, {r4, pc} 8978 8979 mov r0, r4 @ recover arg 8980 bl __aeabi_f2lz @ convert float to long 8981 ldmfd sp!, {r4, pc} 8982 8983/* continuation for OP_DOUBLE_TO_LONG */ 8984/* 8985 * Convert the double in r0/r1 to a long in r0/r1. 8986 * 8987 * We have to clip values to long min/max per the specification. The 8988 * expected common case is a "reasonable" value that converts directly 8989 * to modest integer. The EABI convert function isn't doing this for us. 8990 */ 8991d2l_doconv: 8992 stmfd sp!, {r4, r5, lr} @ save regs 8993 mov r3, #0x43000000 @ maxlong, as a double (high word) 8994 add r3, #0x00e00000 @ 0x43e00000 8995 mov r2, #0 @ maxlong, as a double (low word) 8996 sub sp, sp, #4 @ align for EABI 8997 mov r4, r0 @ save a copy of r0 8998 mov r5, r1 @ and r1 8999 bl __aeabi_dcmpge @ is arg >= maxlong? 9000 cmp r0, #0 @ nonzero == yes 9001 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 9002 mvnne r1, #0x80000000 9003 bne 1f 9004 9005 mov r0, r4 @ recover arg 9006 mov r1, r5 9007 mov r3, #0xc3000000 @ minlong, as a double (high word) 9008 add r3, #0x00e00000 @ 0xc3e00000 9009 mov r2, #0 @ minlong, as a double (low word) 9010 bl __aeabi_dcmple @ is arg <= minlong? 9011 cmp r0, #0 @ nonzero == yes 9012 movne r0, #0 @ return minlong (8000000000000000) 9013 movne r1, #0x80000000 9014 bne 1f 9015 9016 mov r0, r4 @ recover arg 9017 mov r1, r5 9018 mov r2, r4 @ compare against self 9019 mov r3, r5 9020 bl __aeabi_dcmpeq @ is arg == self? 9021 cmp r0, #0 @ zero == no 9022 moveq r1, #0 @ return zero for NaN 9023 beq 1f 9024 9025 mov r0, r4 @ recover arg 9026 mov r1, r5 9027 bl __aeabi_d2lz @ convert double to long 9028 90291: 9030 add sp, sp, #4 9031 ldmfd sp!, {r4, r5, pc} 9032 9033/* continuation for OP_MUL_LONG */ 9034 9035.LOP_MUL_LONG_finish: 9036 GET_INST_OPCODE(ip) @ extract opcode from rINST 9037 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 9038 GOTO_OPCODE(ip) @ jump to next instruction 9039 9040/* continuation for OP_SHL_LONG */ 9041 9042.LOP_SHL_LONG_finish: 9043 mov r0, r0, asl r2 @ r0<- r0 << r2 9044 GET_INST_OPCODE(ip) @ extract opcode from rINST 9045 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9046 GOTO_OPCODE(ip) @ jump to next instruction 9047 9048/* continuation for OP_SHR_LONG */ 9049 9050.LOP_SHR_LONG_finish: 9051 mov r1, r1, asr r2 @ r1<- r1 >> r2 9052 GET_INST_OPCODE(ip) @ extract opcode from rINST 9053 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9054 GOTO_OPCODE(ip) @ jump to next instruction 9055 9056/* continuation for OP_USHR_LONG */ 9057 9058.LOP_USHR_LONG_finish: 9059 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 9060 GET_INST_OPCODE(ip) @ extract opcode from rINST 9061 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9062 GOTO_OPCODE(ip) @ jump to next instruction 9063 9064/* continuation for OP_SHL_LONG_2ADDR */ 9065 9066.LOP_SHL_LONG_2ADDR_finish: 9067 GET_INST_OPCODE(ip) @ extract opcode from rINST 9068 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9069 GOTO_OPCODE(ip) @ jump to next instruction 9070 9071/* continuation for OP_SHR_LONG_2ADDR */ 9072 9073.LOP_SHR_LONG_2ADDR_finish: 9074 GET_INST_OPCODE(ip) @ extract opcode from rINST 9075 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9076 GOTO_OPCODE(ip) @ jump to next instruction 9077 9078/* continuation for OP_USHR_LONG_2ADDR */ 9079 9080.LOP_USHR_LONG_2ADDR_finish: 9081 GET_INST_OPCODE(ip) @ extract opcode from rINST 9082 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9083 GOTO_OPCODE(ip) @ jump to next instruction 9084 9085/* continuation for OP_IGET_VOLATILE */ 9086 9087 /* 9088 * Currently: 9089 * r0 holds resolved field 9090 * r9 holds object 9091 */ 9092.LOP_IGET_VOLATILE_finish: 9093 @bl common_squeak0 9094 cmp r9, #0 @ check object for null 9095 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9096 beq common_errNullObject @ object was null 9097 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9098 SMP_DMB @ acquiring load 9099 mov r2, rINST, lsr #8 @ r2<- A+ 9100 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9101 and r2, r2, #15 @ r2<- A 9102 GET_INST_OPCODE(ip) @ extract opcode from rINST 9103 SET_VREG(r0, r2) @ fp[A]<- r0 9104 GOTO_OPCODE(ip) @ jump to next instruction 9105 9106/* continuation for OP_IPUT_VOLATILE */ 9107 9108 /* 9109 * Currently: 9110 * r0 holds resolved field 9111 * r9 holds object 9112 */ 9113.LOP_IPUT_VOLATILE_finish: 9114 @bl common_squeak0 9115 mov r1, rINST, lsr #8 @ r1<- A+ 9116 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9117 and r1, r1, #15 @ r1<- A 9118 cmp r9, #0 @ check object for null 9119 GET_VREG(r0, r1) @ r0<- fp[A] 9120 beq common_errNullObject @ object was null 9121 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9122 GET_INST_OPCODE(ip) @ extract opcode from rINST 9123 SMP_DMB @ releasing store 9124 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 9125 GOTO_OPCODE(ip) @ jump to next instruction 9126 9127/* continuation for OP_SGET_VOLATILE */ 9128 9129 /* 9130 * Continuation if the field has not yet been resolved. 9131 * r1: BBBB field ref 9132 */ 9133.LOP_SGET_VOLATILE_resolve: 9134 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9135 EXPORT_PC() @ resolve() could throw, so export now 9136 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9137 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9138 cmp r0, #0 @ success? 9139 bne .LOP_SGET_VOLATILE_finish @ yes, finish 9140 b common_exceptionThrown @ no, handle exception 9141 9142/* continuation for OP_SPUT_VOLATILE */ 9143 9144 /* 9145 * Continuation if the field has not yet been resolved. 9146 * r1: BBBB field ref 9147 */ 9148.LOP_SPUT_VOLATILE_resolve: 9149 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9150 EXPORT_PC() @ resolve() could throw, so export now 9151 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9152 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9153 cmp r0, #0 @ success? 9154 bne .LOP_SPUT_VOLATILE_finish @ yes, finish 9155 b common_exceptionThrown @ no, handle exception 9156 9157/* continuation for OP_IGET_OBJECT_VOLATILE */ 9158 9159 /* 9160 * Currently: 9161 * r0 holds resolved field 9162 * r9 holds object 9163 */ 9164.LOP_IGET_OBJECT_VOLATILE_finish: 9165 @bl common_squeak0 9166 cmp r9, #0 @ check object for null 9167 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9168 beq common_errNullObject @ object was null 9169 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 9170 SMP_DMB @ acquiring load 9171 mov r2, rINST, lsr #8 @ r2<- A+ 9172 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9173 and r2, r2, #15 @ r2<- A 9174 GET_INST_OPCODE(ip) @ extract opcode from rINST 9175 SET_VREG(r0, r2) @ fp[A]<- r0 9176 GOTO_OPCODE(ip) @ jump to next instruction 9177 9178/* continuation for OP_IGET_WIDE_VOLATILE */ 9179 9180 /* 9181 * Currently: 9182 * r0 holds resolved field 9183 * r9 holds object 9184 */ 9185.LOP_IGET_WIDE_VOLATILE_finish: 9186 cmp r9, #0 @ check object for null 9187 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9188 beq common_errNullObject @ object was null 9189 .if 1 9190 add r0, r9, r3 @ r0<- address of field 9191 bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field 9192 .else 9193 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 9194 .endif 9195 mov r2, rINST, lsr #8 @ r2<- A+ 9196 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9197 and r2, r2, #15 @ r2<- A 9198 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 9199 GET_INST_OPCODE(ip) @ extract opcode from rINST 9200 stmia r3, {r0-r1} @ fp[A]<- r0/r1 9201 GOTO_OPCODE(ip) @ jump to next instruction 9202 9203/* continuation for OP_IPUT_WIDE_VOLATILE */ 9204 9205 /* 9206 * Currently: 9207 * r0 holds resolved field 9208 * r9 holds object 9209 */ 9210.LOP_IPUT_WIDE_VOLATILE_finish: 9211 mov r2, rINST, lsr #8 @ r2<- A+ 9212 cmp r9, #0 @ check object for null 9213 and r2, r2, #15 @ r2<- A 9214 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9215 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 9216 beq common_errNullObject @ object was null 9217 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9218 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 9219 GET_INST_OPCODE(r10) @ extract opcode from rINST 9220 .if 1 9221 add r2, r9, r3 @ r2<- target address 9222 bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 9223 .else 9224 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 9225 .endif 9226 GOTO_OPCODE(r10) @ jump to next instruction 9227 9228/* continuation for OP_SGET_WIDE_VOLATILE */ 9229 9230 /* 9231 * Continuation if the field has not yet been resolved. 9232 * r1: BBBB field ref 9233 * 9234 * Returns StaticField pointer in r0. 9235 */ 9236.LOP_SGET_WIDE_VOLATILE_resolve: 9237 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9238 EXPORT_PC() @ resolve() could throw, so export now 9239 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9240 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9241 cmp r0, #0 @ success? 9242 bne .LOP_SGET_WIDE_VOLATILE_finish @ yes, finish 9243 b common_exceptionThrown @ no, handle exception 9244 9245/* continuation for OP_SPUT_WIDE_VOLATILE */ 9246 9247 /* 9248 * Continuation if the field has not yet been resolved. 9249 * r1: BBBB field ref 9250 * r9: &fp[AA] 9251 * 9252 * Returns StaticField pointer in r2. 9253 */ 9254.LOP_SPUT_WIDE_VOLATILE_resolve: 9255 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9256 EXPORT_PC() @ resolve() could throw, so export now 9257 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9258 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9259 cmp r0, #0 @ success? 9260 mov r2, r0 @ copy to r2 9261 bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish 9262 b common_exceptionThrown @ no, handle exception 9263 9264/* continuation for OP_EXECUTE_INLINE */ 9265 9266 /* 9267 * Extract args, call function. 9268 * r0 = #of args (0-4) 9269 * r10 = call index 9270 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9271 * 9272 * Other ideas: 9273 * - Use a jump table from the main piece to jump directly into the 9274 * AND/LDR pairs. Costs a data load, saves a branch. 9275 * - Have five separate pieces that do the loading, so we can work the 9276 * interleave a little better. Increases code size. 9277 */ 9278.LOP_EXECUTE_INLINE_continue: 9279 rsb r0, r0, #4 @ r0<- 4-r0 9280 FETCH(r9, 2) @ r9<- FEDC 9281 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9282 bl common_abort @ (skipped due to ARM prefetch) 92834: and ip, r9, #0xf000 @ isolate F 9284 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 92853: and ip, r9, #0x0f00 @ isolate E 9286 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 92872: and ip, r9, #0x00f0 @ isolate D 9288 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 92891: and ip, r9, #0x000f @ isolate C 9290 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 92910: 9292 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 9293 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9294 @ (not reached) 9295 9296.LOP_EXECUTE_INLINE_table: 9297 .word gDvmInlineOpsTable 9298 9299/* continuation for OP_EXECUTE_INLINE_RANGE */ 9300 9301 /* 9302 * Extract args, call function. 9303 * r0 = #of args (0-4) 9304 * r10 = call index 9305 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9306 */ 9307.LOP_EXECUTE_INLINE_RANGE_continue: 9308 rsb r0, r0, #4 @ r0<- 4-r0 9309 FETCH(r9, 2) @ r9<- CCCC 9310 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9311 bl common_abort @ (skipped due to ARM prefetch) 93124: add ip, r9, #3 @ base+3 9313 GET_VREG(r3, ip) @ r3<- vBase[3] 93143: add ip, r9, #2 @ base+2 9315 GET_VREG(r2, ip) @ r2<- vBase[2] 93162: add ip, r9, #1 @ base+1 9317 GET_VREG(r1, ip) @ r1<- vBase[1] 93181: add ip, r9, #0 @ (nop) 9319 GET_VREG(r0, ip) @ r0<- vBase[0] 93200: 9321 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation 9322 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9323 @ (not reached) 9324 9325.LOP_EXECUTE_INLINE_RANGE_table: 9326 .word gDvmInlineOpsTable 9327 9328/* continuation for OP_IPUT_OBJECT_VOLATILE */ 9329 9330 /* 9331 * Currently: 9332 * r0 holds resolved field 9333 * r9 holds object 9334 */ 9335.LOP_IPUT_OBJECT_VOLATILE_finish: 9336 @bl common_squeak0 9337 mov r1, rINST, lsr #8 @ r1<- A+ 9338 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9339 and r1, r1, #15 @ r1<- A 9340 cmp r9, #0 @ check object for null 9341 GET_VREG(r0, r1) @ r0<- fp[A] 9342 ldr r2, [rGLUE, #offGlue_cardTable] @ r2<- card table base 9343 beq common_errNullObject @ object was null 9344 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9345 GET_INST_OPCODE(ip) @ extract opcode from rINST 9346 SMP_DMB @ releasing store 9347 str r0, [r9, r3] @ obj.field (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 ldr r9, [r0, #offField_clazz] @ r9<- field->clazz 9374 GET_INST_OPCODE(ip) @ extract opcode from rINST 9375 SMP_DMB @ releasing store 9376 str r1, [r0, #offStaticField_value] @ field<- vAA 9377 cmp r1, #0 @ stored a null object? 9378 strneb r2, [r2, r9, lsr #GC_CARD_SHIFT] @ mark card based on obj head 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 @ Need to clear the inJitCodeCache flag 9714 ldr r10, [rGLUE, #offGlue_self] @ r10 <- glue->self 9715 mov r3, #0 @ 0 means not in the JIT code cache 9716 str r3, [r10, #offThread_inJitCodeCache] @ back to the interp land 9717 GET_INST_OPCODE(ip) 9718 GOTO_OPCODE(ip) 9719 /* no return */ 9720#endif 9721 9722/* 9723 * On entry: 9724 * r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot 9725 */ 9726common_selectTrace: 9727 str r2,[rGLUE,#offGlue_jitState] 9728 mov r2,#kInterpEntryInstr @ normal entry reason 9729 str r2,[rGLUE,#offGlue_entryPoint] 9730 mov r1,#1 @ set changeInterp 9731 b common_gotoBail 9732 9733#if defined(WITH_SELF_VERIFICATION) 9734/* 9735 * Save PC and registers to shadow memory for self verification mode 9736 * before jumping to native translation. 9737 * On entry: 9738 * rPC, rFP, rGLUE: the values that they should contain 9739 * r10: the address of the target translation. 9740 */ 9741jitSVShadowRunStart: 9742 mov r0,rPC @ r0<- program counter 9743 mov r1,rFP @ r1<- frame pointer 9744 mov r2,rGLUE @ r2<- InterpState pointer 9745 mov r3,r10 @ r3<- target translation 9746 bl dvmSelfVerificationSaveState @ save registers to shadow space 9747 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 9748 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 9749 bx r10 @ jump to the translation 9750 9751/* 9752 * Restore PC, registers, and interpState to original values 9753 * before jumping back to the interpreter. 9754 */ 9755jitSVShadowRunEnd: 9756 mov r1,rFP @ pass ending fp 9757 bl dvmSelfVerificationRestoreState @ restore pc and fp values 9758 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 9759 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 9760 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 9761 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 9762 cmp r1,#0 @ check for punt condition 9763 beq 1f 9764 mov r2,#kJitSelfVerification @ ask for self verification 9765 str r2,[rGLUE,#offGlue_jitState] 9766 mov r2,#kInterpEntryInstr @ normal entry reason 9767 str r2,[rGLUE,#offGlue_entryPoint] 9768 mov r1,#1 @ set changeInterp 9769 b common_gotoBail 9770 97711: @ exit to interpreter without check 9772 EXPORT_PC() 9773 adrl rIBASE, dvmAsmInstructionStart 9774 FETCH_INST() 9775 GET_INST_OPCODE(ip) 9776 GOTO_OPCODE(ip) 9777#endif 9778 9779#endif 9780 9781/* 9782 * Common code when a backward branch is taken. 9783 * 9784 * TODO: we could avoid a branch by just setting r0 and falling through 9785 * into the common_periodicChecks code, and having a test on r0 at the 9786 * end determine if we should return to the caller or update & branch to 9787 * the next instr. 9788 * 9789 * On entry: 9790 * r9 is PC adjustment *in bytes* 9791 */ 9792common_backwardBranch: 9793 mov r0, #kInterpEntryInstr 9794 bl common_periodicChecks 9795#if defined(WITH_JIT) 9796 GET_JIT_PROF_TABLE(r0) 9797 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9798 cmp r0,#0 9799 bne common_updateProfile 9800 GET_INST_OPCODE(ip) 9801 GOTO_OPCODE(ip) 9802#else 9803 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9804 GET_INST_OPCODE(ip) @ extract opcode from rINST 9805 GOTO_OPCODE(ip) @ jump to next instruction 9806#endif 9807 9808 9809/* 9810 * Need to see if the thread needs to be suspended or debugger/profiler 9811 * activity has begun. If so, we suspend the thread or side-exit to 9812 * the debug interpreter as appropriate. 9813 * 9814 * The common case is no activity on any of these, so we want to figure 9815 * that out quickly. If something is up, we can then sort out what. 9816 * 9817 * We want to be fast if the VM was built without debugger or profiler 9818 * support, but we also need to recognize that the system is usually 9819 * shipped with both of these enabled. 9820 * 9821 * TODO: reduce this so we're just checking a single location. 9822 * 9823 * On entry: 9824 * r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling) 9825 * r9 is trampoline PC adjustment *in bytes* 9826 */ 9827common_periodicChecks: 9828 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9829 9830 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9831 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9832 9833 ldr ip, [r3] @ ip<- suspendCount (int) 9834 9835 cmp r1, #0 @ debugger enabled? 9836 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9837 ldr r2, [r2] @ r2<- activeProfilers (int) 9838 orrne ip, ip, r1 @ ip<- suspendCount | debuggerActive 9839 orrs ip, ip, r2 @ ip<- suspend|debugger|profiler; set Z 9840 9841 bxeq lr @ all zero, return 9842 9843 /* 9844 * One or more interesting events have happened. Figure out what. 9845 * 9846 * If debugging or profiling are compiled in, we need to disambiguate. 9847 * 9848 * r0 still holds the reentry type. 9849 */ 9850 ldr ip, [r3] @ ip<- suspendCount (int) 9851 cmp ip, #0 @ want suspend? 9852 beq 1f @ no, must be debugger/profiler 9853 9854 stmfd sp!, {r0, lr} @ preserve r0 and lr 9855#if defined(WITH_JIT) 9856 /* 9857 * Refresh the Jit's cached copy of profile table pointer. This pointer 9858 * doubles as the Jit's on/off switch. 9859 */ 9860 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable 9861 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9862 ldr r3, [r3] @ r3 <- pJitProfTable 9863 EXPORT_PC() @ need for precise GC 9864 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch 9865#else 9866 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9867 EXPORT_PC() @ need for precise GC 9868#endif 9869 bl dvmCheckSuspendPending @ do full check, suspend if necessary 9870 ldmfd sp!, {r0, lr} @ restore r0 and lr 9871 9872 /* 9873 * Reload the debugger/profiler enable flags. We're checking to see 9874 * if either of these got set while we were suspended. 9875 * 9876 * We can't really avoid the #ifdefs here, because the fields don't 9877 * exist when the feature is disabled. 9878 */ 9879 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9880 cmp r1, #0 @ debugger enabled? 9881 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9882 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9883 ldr r2, [r2] @ r2<- activeProfilers (int) 9884 9885 orrs r1, r1, r2 9886 beq 2f 9887 98881: @ debugger/profiler enabled, bail out; glue->entryPoint was set above 9889 str r0, [rGLUE, #offGlue_entryPoint] @ store r0, need for debug/prof 9890 add rPC, rPC, r9 @ update rPC 9891 mov r1, #1 @ "want switch" = true 9892 b common_gotoBail @ side exit 9893 98942: 9895 bx lr @ nothing to do, return 9896 9897 9898/* 9899 * The equivalent of "goto bail", this calls through the "bail handler". 9900 * 9901 * State registers will be saved to the "glue" area before bailing. 9902 * 9903 * On entry: 9904 * r1 is "bool changeInterp", indicating if we want to switch to the 9905 * other interpreter or just bail all the way out 9906 */ 9907common_gotoBail: 9908 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9909 mov r0, rGLUE @ r0<- glue ptr 9910 b dvmMterpStdBail @ call(glue, changeInterp) 9911 9912 @add r1, r1, #1 @ using (boolean+1) 9913 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9914 @bl _longjmp @ does not return 9915 @bl common_abort 9916 9917 9918/* 9919 * Common code for method invocation with range. 9920 * 9921 * On entry: 9922 * r0 is "Method* methodToCall", the method we're trying to call 9923 */ 9924common_invokeMethodRange: 9925.LinvokeNewRange: 9926 @ prepare to copy args to "outs" area of current frame 9927 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9928 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9929 beq .LinvokeArgsDone @ if no args, skip the rest 9930 FETCH(r1, 2) @ r1<- CCCC 9931 9932 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9933 @ (very few methods have > 10 args; could unroll for common cases) 9934 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9935 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9936 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 99371: ldr r1, [r3], #4 @ val = *fp++ 9938 subs r2, r2, #1 @ count-- 9939 str r1, [r10], #4 @ *outs++ = val 9940 bne 1b @ ...while count != 0 9941 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9942 b .LinvokeArgsDone 9943 9944/* 9945 * Common code for method invocation without range. 9946 * 9947 * On entry: 9948 * r0 is "Method* methodToCall", the method we're trying to call 9949 */ 9950common_invokeMethodNoRange: 9951.LinvokeNewNoRange: 9952 @ prepare to copy args to "outs" area of current frame 9953 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9954 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9955 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9956 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9957 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9958 beq .LinvokeArgsDone 9959 9960 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9961.LinvokeNonRange: 9962 rsb r2, r2, #5 @ r2<- 5-r2 9963 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9964 bl common_abort @ (skipped due to ARM prefetch) 99655: and ip, rINST, #0x0f00 @ isolate A 9966 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 9967 mov r0, r0 @ nop 9968 str r2, [r10, #-4]! @ *--outs = vA 99694: and ip, r1, #0xf000 @ isolate G 9970 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 9971 mov r0, r0 @ nop 9972 str r2, [r10, #-4]! @ *--outs = vG 99733: and ip, r1, #0x0f00 @ isolate F 9974 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 9975 mov r0, r0 @ nop 9976 str r2, [r10, #-4]! @ *--outs = vF 99772: and ip, r1, #0x00f0 @ isolate E 9978 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 9979 mov r0, r0 @ nop 9980 str r2, [r10, #-4]! @ *--outs = vE 99811: and ip, r1, #0x000f @ isolate D 9982 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 9983 mov r0, r0 @ nop 9984 str r2, [r10, #-4]! @ *--outs = vD 99850: @ fall through to .LinvokeArgsDone 9986 9987.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 9988 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 9989 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 9990 @ find space for the new stack frame, check for overflow 9991 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 9992 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 9993 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 9994@ bl common_dumpRegs 9995 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 9996 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 9997 cmp r3, r9 @ bottom < interpStackEnd? 9998 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 9999 blo .LstackOverflow @ yes, this frame will overflow stack 10000 10001 @ set up newSaveArea 10002#ifdef EASY_GDB 10003 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 10004 str ip, [r10, #offStackSaveArea_prevSave] 10005#endif 10006 str rFP, [r10, #offStackSaveArea_prevFrame] 10007 str rPC, [r10, #offStackSaveArea_savedPc] 10008#if defined(WITH_JIT) 10009 mov r9, #0 10010 str r9, [r10, #offStackSaveArea_returnAddr] 10011#endif 10012 str r0, [r10, #offStackSaveArea_method] 10013 tst r3, #ACC_NATIVE 10014 bne .LinvokeNative 10015 10016 /* 10017 stmfd sp!, {r0-r3} 10018 bl common_printNewline 10019 mov r0, rFP 10020 mov r1, #0 10021 bl dvmDumpFp 10022 ldmfd sp!, {r0-r3} 10023 stmfd sp!, {r0-r3} 10024 mov r0, r1 10025 mov r1, r10 10026 bl dvmDumpFp 10027 bl common_printNewline 10028 ldmfd sp!, {r0-r3} 10029 */ 10030 10031 ldrh r9, [r2] @ r9 <- load INST from new PC 10032 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 10033 mov rPC, r2 @ publish new rPC 10034 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 10035 10036 @ Update "glue" values for the new method 10037 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 10038 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 10039 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 10040#if defined(WITH_JIT) 10041 GET_JIT_PROF_TABLE(r0) 10042 mov rFP, r1 @ fp = newFp 10043 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 10044 mov rINST, r9 @ publish new rINST 10045 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 10046 cmp r0,#0 10047 bne common_updateProfile 10048 GOTO_OPCODE(ip) @ jump to next instruction 10049#else 10050 mov rFP, r1 @ fp = newFp 10051 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 10052 mov rINST, r9 @ publish new rINST 10053 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 10054 GOTO_OPCODE(ip) @ jump to next instruction 10055#endif 10056 10057.LinvokeNative: 10058 @ Prep for the native call 10059 @ r0=methodToCall, r1=newFp, r10=newSaveArea 10060 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10061 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 10062 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 10063 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 10064 mov r9, r3 @ r9<- glue->self (preserve) 10065 10066 mov r2, r0 @ r2<- methodToCall 10067 mov r0, r1 @ r0<- newFp (points to args) 10068 add r1, rGLUE, #offGlue_retval @ r1<- &retval 10069 10070#ifdef ASSIST_DEBUGGER 10071 /* insert fake function header to help gdb find the stack frame */ 10072 b .Lskip 10073 .type dalvik_mterp, %function 10074dalvik_mterp: 10075 .fnstart 10076 MTERP_ENTRY1 10077 MTERP_ENTRY2 10078.Lskip: 10079#endif 10080 10081 @mov lr, pc @ set return addr 10082 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 10083 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 10084 10085#if defined(WITH_JIT) 10086 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status 10087#endif 10088 10089 @ native return; r9=self, r10=newSaveArea 10090 @ equivalent to dvmPopJniLocals 10091 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 10092 ldr r1, [r9, #offThread_exception] @ check for exception 10093#if defined(WITH_JIT) 10094 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable 10095#endif 10096 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 10097 cmp r1, #0 @ null? 10098 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 10099#if defined(WITH_JIT) 10100 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch 10101#endif 10102 bne common_exceptionThrown @ no, handle exception 10103 10104 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 10105 GET_INST_OPCODE(ip) @ extract opcode from rINST 10106 GOTO_OPCODE(ip) @ jump to next instruction 10107 10108.LstackOverflow: @ r0=methodToCall 10109 mov r1, r0 @ r1<- methodToCall 10110 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 10111 bl dvmHandleStackOverflow 10112 b common_exceptionThrown 10113#ifdef ASSIST_DEBUGGER 10114 .fnend 10115#endif 10116 10117 10118 /* 10119 * Common code for method invocation, calling through "glue code". 10120 * 10121 * TODO: now that we have range and non-range invoke handlers, this 10122 * needs to be split into two. Maybe just create entry points 10123 * that set r9 and jump here? 10124 * 10125 * On entry: 10126 * r0 is "Method* methodToCall", the method we're trying to call 10127 * r9 is "bool methodCallRange", indicating if this is a /range variant 10128 */ 10129 .if 0 10130.LinvokeOld: 10131 sub sp, sp, #8 @ space for args + pad 10132 FETCH(ip, 2) @ ip<- FEDC or CCCC 10133 mov r2, r0 @ A2<- methodToCall 10134 mov r0, rGLUE @ A0<- glue 10135 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 10136 mov r1, r9 @ A1<- methodCallRange 10137 mov r3, rINST, lsr #8 @ A3<- AA 10138 str ip, [sp, #0] @ A4<- ip 10139 bl dvmMterp_invokeMethod @ call the C invokeMethod 10140 add sp, sp, #8 @ remove arg area 10141 b common_resumeAfterGlueCall @ continue to next instruction 10142 .endif 10143 10144 10145 10146/* 10147 * Common code for handling a return instruction. 10148 * 10149 * This does not return. 10150 */ 10151common_returnFromMethod: 10152.LreturnNew: 10153 mov r0, #kInterpEntryReturn 10154 mov r9, #0 10155 bl common_periodicChecks 10156 10157 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 10158 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 10159 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 10160 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 10161 @ r2<- method we're returning to 10162 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10163 cmp r2, #0 @ is this a break frame? 10164 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 10165 mov r1, #0 @ "want switch" = false 10166 beq common_gotoBail @ break frame, bail out completely 10167 10168 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 10169 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 10170 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 10171 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 10172#if defined(WITH_JIT) 10173 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr 10174 mov rPC, r9 @ publish new rPC 10175 str r1, [rGLUE, #offGlue_methodClassDex] 10176 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land 10177 cmp r10, #0 @ caller is compiled code 10178 blxne r10 10179 GET_INST_OPCODE(ip) @ extract opcode from rINST 10180 GOTO_OPCODE(ip) @ jump to next instruction 10181#else 10182 GET_INST_OPCODE(ip) @ extract opcode from rINST 10183 mov rPC, r9 @ publish new rPC 10184 str r1, [rGLUE, #offGlue_methodClassDex] 10185 GOTO_OPCODE(ip) @ jump to next instruction 10186#endif 10187 10188 /* 10189 * Return handling, calls through "glue code". 10190 */ 10191 .if 0 10192.LreturnOld: 10193 SAVE_PC_FP_TO_GLUE() @ export state 10194 mov r0, rGLUE @ arg to function 10195 bl dvmMterp_returnFromMethod 10196 b common_resumeAfterGlueCall 10197 .endif 10198 10199 10200/* 10201 * Somebody has thrown an exception. Handle it. 10202 * 10203 * If the exception processing code returns to us (instead of falling 10204 * out of the interpreter), continue with whatever the next instruction 10205 * now happens to be. 10206 * 10207 * This does not return. 10208 */ 10209 .global dvmMterpCommonExceptionThrown 10210dvmMterpCommonExceptionThrown: 10211common_exceptionThrown: 10212.LexceptionNew: 10213 mov r0, #kInterpEntryThrow 10214 mov r9, #0 10215 bl common_periodicChecks 10216 10217 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 10218 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 10219 mov r1, r10 @ r1<- self 10220 mov r0, r9 @ r0<- exception 10221 bl dvmAddTrackedAlloc @ don't let the exception be GCed 10222 mov r3, #0 @ r3<- NULL 10223 str r3, [r10, #offThread_exception] @ self->exception = NULL 10224 10225 /* set up args and a local for "&fp" */ 10226 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 10227 str rFP, [sp, #-4]! @ *--sp = fp 10228 mov ip, sp @ ip<- &fp 10229 mov r3, #0 @ r3<- false 10230 str ip, [sp, #-4]! @ *--sp = &fp 10231 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 10232 mov r0, r10 @ r0<- self 10233 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 10234 mov r2, r9 @ r2<- exception 10235 sub r1, rPC, r1 @ r1<- pc - method->insns 10236 mov r1, r1, asr #1 @ r1<- offset in code units 10237 10238 /* call, r0 gets catchRelPc (a code-unit offset) */ 10239 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 10240 10241 /* fix earlier stack overflow if necessary; may trash rFP */ 10242 ldrb r1, [r10, #offThread_stackOverflowed] 10243 cmp r1, #0 @ did we overflow earlier? 10244 beq 1f @ no, skip ahead 10245 mov rFP, r0 @ save relPc result in rFP 10246 mov r0, r10 @ r0<- self 10247 mov r1, r9 @ r1<- exception 10248 bl dvmCleanupStackOverflow @ call(self) 10249 mov r0, rFP @ restore result 102501: 10251 10252 /* update frame pointer and check result from dvmFindCatchBlock */ 10253 ldr rFP, [sp, #4] @ retrieve the updated rFP 10254 cmp r0, #0 @ is catchRelPc < 0? 10255 add sp, sp, #8 @ restore stack 10256 bmi .LnotCaughtLocally 10257 10258 /* adjust locals to match self->curFrame and updated PC */ 10259 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 10260 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 10261 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 10262 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 10263 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 10264 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 10265 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 10266 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 10267 10268 /* release the tracked alloc on the exception */ 10269 mov r0, r9 @ r0<- exception 10270 mov r1, r10 @ r1<- self 10271 bl dvmReleaseTrackedAlloc @ release the exception 10272 10273 /* restore the exception if the handler wants it */ 10274 FETCH_INST() @ load rINST from rPC 10275 GET_INST_OPCODE(ip) @ extract opcode from rINST 10276 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 10277 streq r9, [r10, #offThread_exception] @ yes, restore the exception 10278 GOTO_OPCODE(ip) @ jump to next instruction 10279 10280.LnotCaughtLocally: @ r9=exception, r10=self 10281 /* fix stack overflow if necessary */ 10282 ldrb r1, [r10, #offThread_stackOverflowed] 10283 cmp r1, #0 @ did we overflow earlier? 10284 movne r0, r10 @ if yes: r0<- self 10285 movne r1, r9 @ if yes: r1<- exception 10286 blne dvmCleanupStackOverflow @ if yes: call(self) 10287 10288 @ may want to show "not caught locally" debug messages here 10289#if DVM_SHOW_EXCEPTION >= 2 10290 /* call __android_log_print(prio, tag, format, ...) */ 10291 /* "Exception %s from %s:%d not caught locally" */ 10292 @ dvmLineNumFromPC(method, pc - method->insns) 10293 ldr r0, [rGLUE, #offGlue_method] 10294 ldr r1, [r0, #offMethod_insns] 10295 sub r1, rPC, r1 10296 asr r1, r1, #1 10297 bl dvmLineNumFromPC 10298 str r0, [sp, #-4]! 10299 @ dvmGetMethodSourceFile(method) 10300 ldr r0, [rGLUE, #offGlue_method] 10301 bl dvmGetMethodSourceFile 10302 str r0, [sp, #-4]! 10303 @ exception->clazz->descriptor 10304 ldr r3, [r9, #offObject_clazz] 10305 ldr r3, [r3, #offClassObject_descriptor] 10306 @ 10307 ldr r2, strExceptionNotCaughtLocally 10308 ldr r1, strLogTag 10309 mov r0, #3 @ LOG_DEBUG 10310 bl __android_log_print 10311#endif 10312 str r9, [r10, #offThread_exception] @ restore exception 10313 mov r0, r9 @ r0<- exception 10314 mov r1, r10 @ r1<- self 10315 bl dvmReleaseTrackedAlloc @ release the exception 10316 mov r1, #0 @ "want switch" = false 10317 b common_gotoBail @ bail out 10318 10319 10320 /* 10321 * Exception handling, calls through "glue code". 10322 */ 10323 .if 0 10324.LexceptionOld: 10325 SAVE_PC_FP_TO_GLUE() @ export state 10326 mov r0, rGLUE @ arg to function 10327 bl dvmMterp_exceptionThrown 10328 b common_resumeAfterGlueCall 10329 .endif 10330 10331 10332/* 10333 * After returning from a "glued" function, pull out the updated 10334 * values and start executing at the next instruction. 10335 */ 10336common_resumeAfterGlueCall: 10337 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 10338 FETCH_INST() @ load rINST from rPC 10339 GET_INST_OPCODE(ip) @ extract opcode from rINST 10340 GOTO_OPCODE(ip) @ jump to next instruction 10341 10342/* 10343 * Invalid array index. 10344 */ 10345common_errArrayIndex: 10346 EXPORT_PC() 10347 ldr r0, strArrayIndexException 10348 mov r1, #0 10349 bl dvmThrowException 10350 b common_exceptionThrown 10351 10352/* 10353 * Invalid array value. 10354 */ 10355common_errArrayStore: 10356 EXPORT_PC() 10357 ldr r0, strArrayStoreException 10358 mov r1, #0 10359 bl dvmThrowException 10360 b common_exceptionThrown 10361 10362/* 10363 * Integer divide or mod by zero. 10364 */ 10365common_errDivideByZero: 10366 EXPORT_PC() 10367 ldr r0, strArithmeticException 10368 ldr r1, strDivideByZero 10369 bl dvmThrowException 10370 b common_exceptionThrown 10371 10372/* 10373 * Attempt to allocate an array with a negative size. 10374 */ 10375common_errNegativeArraySize: 10376 EXPORT_PC() 10377 ldr r0, strNegativeArraySizeException 10378 mov r1, #0 10379 bl dvmThrowException 10380 b common_exceptionThrown 10381 10382/* 10383 * Invocation of a non-existent method. 10384 */ 10385common_errNoSuchMethod: 10386 EXPORT_PC() 10387 ldr r0, strNoSuchMethodError 10388 mov r1, #0 10389 bl dvmThrowException 10390 b common_exceptionThrown 10391 10392/* 10393 * We encountered a null object when we weren't expecting one. We 10394 * export the PC, throw a NullPointerException, and goto the exception 10395 * processing code. 10396 */ 10397common_errNullObject: 10398 EXPORT_PC() 10399 ldr r0, strNullPointerException 10400 mov r1, #0 10401 bl dvmThrowException 10402 b common_exceptionThrown 10403 10404/* 10405 * For debugging, cause an immediate fault. The source address will 10406 * be in lr (use a bl instruction to jump here). 10407 */ 10408common_abort: 10409 ldr pc, .LdeadFood 10410.LdeadFood: 10411 .word 0xdeadf00d 10412 10413/* 10414 * Spit out a "we were here", preserving all registers. (The attempt 10415 * to save ip won't work, but we need to save an even number of 10416 * registers for EABI 64-bit stack alignment.) 10417 */ 10418 .macro SQUEAK num 10419common_squeak\num: 10420 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10421 ldr r0, strSqueak 10422 mov r1, #\num 10423 bl printf 10424 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10425 bx lr 10426 .endm 10427 10428 SQUEAK 0 10429 SQUEAK 1 10430 SQUEAK 2 10431 SQUEAK 3 10432 SQUEAK 4 10433 SQUEAK 5 10434 10435/* 10436 * Spit out the number in r0, preserving registers. 10437 */ 10438common_printNum: 10439 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10440 mov r1, r0 10441 ldr r0, strSqueak 10442 bl printf 10443 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10444 bx lr 10445 10446/* 10447 * Print a newline, preserving registers. 10448 */ 10449common_printNewline: 10450 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10451 ldr r0, strNewline 10452 bl printf 10453 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10454 bx lr 10455 10456 /* 10457 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 10458 */ 10459common_printHex: 10460 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10461 mov r1, r0 10462 ldr r0, strPrintHex 10463 bl printf 10464 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10465 bx lr 10466 10467/* 10468 * Print the 64-bit quantity in r0-r1, preserving registers. 10469 */ 10470common_printLong: 10471 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10472 mov r3, r1 10473 mov r2, r0 10474 ldr r0, strPrintLong 10475 bl printf 10476 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10477 bx lr 10478 10479/* 10480 * Print full method info. Pass the Method* in r0. Preserves regs. 10481 */ 10482common_printMethod: 10483 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10484 bl dvmMterpPrintMethod 10485 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10486 bx lr 10487 10488/* 10489 * Call a C helper function that dumps regs and possibly some 10490 * additional info. Requires the C function to be compiled in. 10491 */ 10492 .if 0 10493common_dumpRegs: 10494 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10495 bl dvmMterpDumpArmRegs 10496 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10497 bx lr 10498 .endif 10499 10500#if 0 10501/* 10502 * Experiment on VFP mode. 10503 * 10504 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 10505 * 10506 * Updates the bits specified by "mask", setting them to the values in "val". 10507 */ 10508setFPSCR: 10509 and r0, r0, r1 @ make sure no stray bits are set 10510 fmrx r2, fpscr @ get VFP reg 10511 mvn r1, r1 @ bit-invert mask 10512 and r2, r2, r1 @ clear masked bits 10513 orr r2, r2, r0 @ set specified bits 10514 fmxr fpscr, r2 @ set VFP reg 10515 mov r0, r2 @ return new value 10516 bx lr 10517 10518 .align 2 10519 .global dvmConfigureFP 10520 .type dvmConfigureFP, %function 10521dvmConfigureFP: 10522 stmfd sp!, {ip, lr} 10523 /* 0x03000000 sets DN/FZ */ 10524 /* 0x00009f00 clears the six exception enable flags */ 10525 bl common_squeak0 10526 mov r0, #0x03000000 @ r0<- 0x03000000 10527 add r1, r0, #0x9f00 @ r1<- 0x03009f00 10528 bl setFPSCR 10529 ldmfd sp!, {ip, pc} 10530#endif 10531 10532 10533/* 10534 * String references, must be close to the code that uses them. 10535 */ 10536 .align 2 10537strArithmeticException: 10538 .word .LstrArithmeticException 10539strArrayIndexException: 10540 .word .LstrArrayIndexException 10541strArrayStoreException: 10542 .word .LstrArrayStoreException 10543strDivideByZero: 10544 .word .LstrDivideByZero 10545strNegativeArraySizeException: 10546 .word .LstrNegativeArraySizeException 10547strNoSuchMethodError: 10548 .word .LstrNoSuchMethodError 10549strNullPointerException: 10550 .word .LstrNullPointerException 10551 10552strLogTag: 10553 .word .LstrLogTag 10554strExceptionNotCaughtLocally: 10555 .word .LstrExceptionNotCaughtLocally 10556 10557strNewline: 10558 .word .LstrNewline 10559strSqueak: 10560 .word .LstrSqueak 10561strPrintHex: 10562 .word .LstrPrintHex 10563strPrintLong: 10564 .word .LstrPrintLong 10565 10566/* 10567 * Zero-terminated ASCII string data. 10568 * 10569 * On ARM we have two choices: do like gcc does, and LDR from a .word 10570 * with the address, or use an ADR pseudo-op to get the address 10571 * directly. ADR saves 4 bytes and an indirection, but it's using a 10572 * PC-relative addressing mode and hence has a limited range, which 10573 * makes it not work well with mergeable string sections. 10574 */ 10575 .section .rodata.str1.4,"aMS",%progbits,1 10576 10577.LstrBadEntryPoint: 10578 .asciz "Bad entry point %d\n" 10579.LstrArithmeticException: 10580 .asciz "Ljava/lang/ArithmeticException;" 10581.LstrArrayIndexException: 10582 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 10583.LstrArrayStoreException: 10584 .asciz "Ljava/lang/ArrayStoreException;" 10585.LstrClassCastException: 10586 .asciz "Ljava/lang/ClassCastException;" 10587.LstrDivideByZero: 10588 .asciz "divide by zero" 10589.LstrFilledNewArrayNotImpl: 10590 .asciz "filled-new-array only implemented for objects and 'int'" 10591.LstrInternalError: 10592 .asciz "Ljava/lang/InternalError;" 10593.LstrInstantiationError: 10594 .asciz "Ljava/lang/InstantiationError;" 10595.LstrNegativeArraySizeException: 10596 .asciz "Ljava/lang/NegativeArraySizeException;" 10597.LstrNoSuchMethodError: 10598 .asciz "Ljava/lang/NoSuchMethodError;" 10599.LstrNullPointerException: 10600 .asciz "Ljava/lang/NullPointerException;" 10601 10602.LstrLogTag: 10603 .asciz "mterp" 10604.LstrExceptionNotCaughtLocally: 10605 .asciz "Exception %s from %s:%d not caught locally\n" 10606 10607.LstrNewline: 10608 .asciz "\n" 10609.LstrSqueak: 10610 .asciz "<%d>" 10611.LstrPrintHex: 10612 .asciz "<0x%x>" 10613.LstrPrintLong: 10614 .asciz "<%lld>" 10615 10616