InterpAsm-armv5te-vfp.S revision de75089fb7216d19e9c22cce4dc62a49513477d3
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 * ARMv5 definitions and declarations. 25 */ 26 27/* 28ARM EABI general notes: 29 30r0-r3 hold first 4 args to a method; they are not preserved across method calls 31r4-r8 are available for general use 32r9 is given special treatment in some situations, but not for us 33r10 (sl) seems to be generally available 34r11 (fp) is used by gcc (unless -fomit-frame-pointer is set) 35r12 (ip) is scratch -- not preserved across method calls 36r13 (sp) should be managed carefully in case a signal arrives 37r14 (lr) must be preserved 38r15 (pc) can be tinkered with directly 39 40r0 holds returns of <= 4 bytes 41r0-r1 hold returns of 8 bytes, low word in r0 42 43Callee must save/restore r4+ (except r12) if it modifies them. If VFP 44is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved, 45s0-s15 (d0-d7, q0-a3) do not need to be. 46 47Stack is "full descending". Only the arguments that don't fit in the first 4 48registers are placed on the stack. "sp" points at the first stacked argument 49(i.e. the 5th arg). 50 51VFP: single-precision results in s0, double-precision results in d0. 52 53In the EABI, "sp" must be 64-bit aligned on entry to a function, and any 5464-bit quantities (long long, double) must be 64-bit aligned. 55*/ 56 57/* 58Mterp and ARM notes: 59 60The following registers have fixed assignments: 61 62 reg nick purpose 63 r4 rPC interpreted program counter, used for fetching instructions 64 r5 rFP interpreted frame pointer, used for accessing locals and args 65 r6 rGLUE MterpGlue pointer 66 r7 rINST first 16-bit code unit of current instruction 67 r8 rIBASE interpreted instruction base pointer, used for computed goto 68 69Macros are provided for common operations. Each macro MUST emit only 70one instruction to make instruction-counting easier. They MUST NOT alter 71unspecified registers or condition codes. 72*/ 73 74/* single-purpose registers, given names for clarity */ 75#define rPC r4 76#define rFP r5 77#define rGLUE r6 78#define rINST r7 79#define rIBASE r8 80 81/* save/restore the PC and/or FP from the glue struct */ 82#define LOAD_PC_FROM_GLUE() ldr rPC, [rGLUE, #offGlue_pc] 83#define SAVE_PC_TO_GLUE() str rPC, [rGLUE, #offGlue_pc] 84#define LOAD_FP_FROM_GLUE() ldr rFP, [rGLUE, #offGlue_fp] 85#define SAVE_FP_TO_GLUE() str rFP, [rGLUE, #offGlue_fp] 86#define LOAD_PC_FP_FROM_GLUE() ldmia rGLUE, {rPC, rFP} 87#define SAVE_PC_FP_TO_GLUE() stmia rGLUE, {rPC, rFP} 88 89/* 90 * "export" the PC to the stack frame, f/b/o future exception objects. Must 91 * be done *before* something calls dvmThrowException. 92 * 93 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e. 94 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc) 95 * 96 * It's okay to do this more than once. 97 */ 98#define EXPORT_PC() \ 99 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)] 100 101/* 102 * Given a frame pointer, find the stack save area. 103 * 104 * In C this is "((StackSaveArea*)(_fp) -1)". 105 */ 106#define SAVEAREA_FROM_FP(_reg, _fpreg) \ 107 sub _reg, _fpreg, #sizeofStackSaveArea 108 109/* 110 * Fetch the next instruction from rPC into rINST. Does not advance rPC. 111 */ 112#define FETCH_INST() ldrh rINST, [rPC] 113 114/* 115 * Fetch the next instruction from the specified offset. Advances rPC 116 * to point to the next instruction. "_count" is in 16-bit code units. 117 * 118 * Because of the limited size of immediate constants on ARM, this is only 119 * suitable for small forward movements (i.e. don't try to implement "goto" 120 * with this). 121 * 122 * This must come AFTER anything that can throw an exception, or the 123 * exception catch may miss. (This also implies that it must come after 124 * EXPORT_PC().) 125 */ 126#define FETCH_ADVANCE_INST(_count) ldrh rINST, [rPC, #(_count*2)]! 127 128/* 129 * The operation performed here is similar to FETCH_ADVANCE_INST, except the 130 * src and dest registers are parameterized (not hard-wired to rPC and rINST). 131 */ 132#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \ 133 ldrh _dreg, [_sreg, #(_count*2)]! 134 135/* 136 * Fetch the next instruction from an offset specified by _reg. Updates 137 * rPC to point to the next instruction. "_reg" must specify the distance 138 * in bytes, *not* 16-bit code units, and may be a signed value. 139 * 140 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the 141 * bits that hold the shift distance are used for the half/byte/sign flags. 142 * In some cases we can pre-double _reg for free, so we require a byte offset 143 * here. 144 */ 145#define FETCH_ADVANCE_INST_RB(_reg) ldrh rINST, [rPC, _reg]! 146 147/* 148 * Fetch a half-word code unit from an offset past the current PC. The 149 * "_count" value is in 16-bit code units. Does not advance rPC. 150 * 151 * The "_S" variant works the same but treats the value as signed. 152 */ 153#define FETCH(_reg, _count) ldrh _reg, [rPC, #(_count*2)] 154#define FETCH_S(_reg, _count) ldrsh _reg, [rPC, #(_count*2)] 155 156/* 157 * Fetch one byte from an offset past the current PC. Pass in the same 158 * "_count" as you would for FETCH, and an additional 0/1 indicating which 159 * byte of the halfword you want (lo/hi). 160 */ 161#define FETCH_B(_reg, _count, _byte) ldrb _reg, [rPC, #(_count*2+_byte)] 162 163/* 164 * Put the instruction's opcode field into the specified register. 165 */ 166#define GET_INST_OPCODE(_reg) and _reg, rINST, #255 167 168/* 169 * Put the prefetched instruction's opcode field into the specified register. 170 */ 171#define GET_PREFETCHED_OPCODE(_oreg, _ireg) and _oreg, _ireg, #255 172 173/* 174 * Begin executing the opcode in _reg. Because this only jumps within the 175 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork. 176 */ 177#define GOTO_OPCODE(_reg) add pc, rIBASE, _reg, lsl #6 178#define GOTO_OPCODE_IFEQ(_reg) addeq pc, rIBASE, _reg, lsl #6 179#define GOTO_OPCODE_IFNE(_reg) addne pc, rIBASE, _reg, lsl #6 180 181/* 182 * Get/set the 32-bit value from a Dalvik register. 183 */ 184#define GET_VREG(_reg, _vreg) ldr _reg, [rFP, _vreg, lsl #2] 185#define SET_VREG(_reg, _vreg) str _reg, [rFP, _vreg, lsl #2] 186 187#if defined(WITH_JIT) 188#define GET_JIT_PROF_TABLE(_reg) ldr _reg,[rGLUE,#offGlue_pJitProfTable] 189#define GET_JIT_THRESHOLD(_reg) ldr _reg,[rGLUE,#offGlue_jitThreshold] 190#endif 191 192/* 193 * Convert a virtual register index into an address. 194 */ 195#define VREG_INDEX_TO_ADDR(_reg, _vreg) \ 196 add _reg, rFP, _vreg, lsl #2 197 198/* 199 * This is a #include, not a %include, because we want the C pre-processor 200 * to expand the macros into assembler assignment statements. 201 */ 202#include "../common/asm-constants.h" 203 204#if defined(WITH_JIT) 205#include "../common/jit-config.h" 206#endif 207 208/* File: armv5te/platform.S */ 209/* 210 * =========================================================================== 211 * CPU-version-specific defines 212 * =========================================================================== 213 */ 214 215/* 216 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5. Essentially a 217 * one-way branch. 218 * 219 * May modify IP. Does not modify LR. 220 */ 221.macro LDR_PC source 222 ldr pc, \source 223.endm 224 225/* 226 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5. 227 * Jump to subroutine. 228 * 229 * May modify IP and LR. 230 */ 231.macro LDR_PC_LR source 232 mov lr, pc 233 ldr pc, \source 234.endm 235 236/* 237 * Macro for "LDMFD SP!, {...regs...,PC}". 238 * 239 * May modify IP and LR. 240 */ 241.macro LDMFD_PC regs 242 ldmfd sp!, {\regs,pc} 243.endm 244 245 246/* File: armv5te/entry.S */ 247/* 248 * Copyright (C) 2008 The Android Open Source Project 249 * 250 * Licensed under the Apache License, Version 2.0 (the "License"); 251 * you may not use this file except in compliance with the License. 252 * You may obtain a copy of the License at 253 * 254 * http://www.apache.org/licenses/LICENSE-2.0 255 * 256 * Unless required by applicable law or agreed to in writing, software 257 * distributed under the License is distributed on an "AS IS" BASIS, 258 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 259 * See the License for the specific language governing permissions and 260 * limitations under the License. 261 */ 262/* 263 * Interpreter entry point. 264 */ 265 266/* 267 * We don't have formal stack frames, so gdb scans upward in the code 268 * to find the start of the function (a label with the %function type), 269 * and then looks at the next few instructions to figure out what 270 * got pushed onto the stack. From this it figures out how to restore 271 * the registers, including PC, for the previous stack frame. If gdb 272 * sees a non-function label, it stops scanning, so either we need to 273 * have nothing but assembler-local labels between the entry point and 274 * the break, or we need to fake it out. 275 * 276 * When this is defined, we add some stuff to make gdb less confused. 277 */ 278#define ASSIST_DEBUGGER 1 279 280 .text 281 .align 2 282 .global dvmMterpStdRun 283 .type dvmMterpStdRun, %function 284 285/* 286 * On entry: 287 * r0 MterpGlue* glue 288 * 289 * This function returns a boolean "changeInterp" value. The return comes 290 * via a call to dvmMterpStdBail(). 291 */ 292dvmMterpStdRun: 293#define MTERP_ENTRY1 \ 294 .save {r4-r10,fp,lr}; \ 295 stmfd sp!, {r4-r10,fp,lr} @ save 9 regs 296#define MTERP_ENTRY2 \ 297 .pad #4; \ 298 sub sp, sp, #4 @ align 64 299 300 .fnstart 301 MTERP_ENTRY1 302 MTERP_ENTRY2 303 304 /* save stack pointer, add magic word for debuggerd */ 305 str sp, [r0, #offGlue_bailPtr] @ save SP for eventual return 306 307 /* set up "named" registers, figure out entry point */ 308 mov rGLUE, r0 @ set rGLUE 309 ldr r1, [r0, #offGlue_entryPoint] @ enum is 4 bytes in aapcs-EABI 310 LOAD_PC_FP_FROM_GLUE() @ load rPC and rFP from "glue" 311 adr rIBASE, dvmAsmInstructionStart @ set rIBASE 312 cmp r1, #kInterpEntryInstr @ usual case? 313 bne .Lnot_instr @ no, handle it 314 315#if defined(WITH_JIT) 316.LentryInstr: 317 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 318 /* Entry is always a possible trace start */ 319 GET_JIT_PROF_TABLE(r0) 320 FETCH_INST() 321 mov r1, #0 @ prepare the value for the new state 322 str r1, [r10, #offThread_inJitCodeCache] @ back to the interp land 323 cmp r0,#0 324 bne common_updateProfile 325 GET_INST_OPCODE(ip) 326 GOTO_OPCODE(ip) 327#else 328 /* start executing the instruction at rPC */ 329 FETCH_INST() @ load rINST from rPC 330 GET_INST_OPCODE(ip) @ extract opcode from rINST 331 GOTO_OPCODE(ip) @ jump to next instruction 332#endif 333 334.Lnot_instr: 335 cmp r1, #kInterpEntryReturn @ were we returning from a method? 336 beq common_returnFromMethod 337 338.Lnot_return: 339 cmp r1, #kInterpEntryThrow @ were we throwing an exception? 340 beq common_exceptionThrown 341 342#if defined(WITH_JIT) 343.Lnot_throw: 344 ldr r10,[rGLUE, #offGlue_jitResumeNPC] 345 ldr r2,[rGLUE, #offGlue_jitResumeDPC] 346 cmp r1, #kInterpEntryResume @ resuming after Jit single-step? 347 bne .Lbad_arg 348 cmp rPC,r2 349 bne .LentryInstr @ must have branched, don't resume 350#if defined(WITH_SELF_VERIFICATION) 351 @ glue->entryPoint will be set in dvmSelfVerificationSaveState 352 b jitSVShadowRunStart @ re-enter the translation after the 353 @ single-stepped instruction 354 @noreturn 355#endif 356 mov r1, #kInterpEntryInstr 357 str r1, [rGLUE, #offGlue_entryPoint] 358 bx r10 @ re-enter the translation 359#endif 360 361.Lbad_arg: 362 ldr r0, strBadEntryPoint 363 @ r1 holds value of entryPoint 364 bl printf 365 bl dvmAbort 366 .fnend 367 368 369 .global dvmMterpStdBail 370 .type dvmMterpStdBail, %function 371 372/* 373 * Restore the stack pointer and PC from the save point established on entry. 374 * This is essentially the same as a longjmp, but should be cheaper. The 375 * last instruction causes us to return to whoever called dvmMterpStdRun. 376 * 377 * We pushed some registers on the stack in dvmMterpStdRun, then saved 378 * SP and LR. Here we restore SP, restore the registers, and then restore 379 * LR to PC. 380 * 381 * On entry: 382 * r0 MterpGlue* glue 383 * r1 bool changeInterp 384 */ 385dvmMterpStdBail: 386 ldr sp, [r0, #offGlue_bailPtr] @ sp<- saved SP 387 mov r0, r1 @ return the changeInterp value 388 add sp, sp, #4 @ un-align 64 389 LDMFD_PC "r4-r10,fp" @ restore 9 regs and return 390 391 392/* 393 * String references. 394 */ 395strBadEntryPoint: 396 .word .LstrBadEntryPoint 397 398 399 400 .global dvmAsmInstructionStart 401 .type dvmAsmInstructionStart, %function 402dvmAsmInstructionStart = .L_OP_NOP 403 .text 404 405/* ------------------------------ */ 406 .balign 64 407.L_OP_NOP: /* 0x00 */ 408/* File: armv5te/OP_NOP.S */ 409 FETCH_ADVANCE_INST(1) @ advance to next instr, load rINST 410 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 411 GOTO_OPCODE(ip) @ execute it 412 413#ifdef ASSIST_DEBUGGER 414 /* insert fake function header to help gdb find the stack frame */ 415 .type dalvik_inst, %function 416dalvik_inst: 417 .fnstart 418 MTERP_ENTRY1 419 MTERP_ENTRY2 420 .fnend 421#endif 422 423 424/* ------------------------------ */ 425 .balign 64 426.L_OP_MOVE: /* 0x01 */ 427/* File: armv5te/OP_MOVE.S */ 428 /* for move, move-object, long-to-int */ 429 /* op vA, vB */ 430 mov r1, rINST, lsr #12 @ r1<- B from 15:12 431 mov r0, rINST, lsr #8 @ r0<- A from 11:8 432 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 433 GET_VREG(r2, r1) @ r2<- fp[B] 434 and r0, r0, #15 435 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 436 SET_VREG(r2, r0) @ fp[A]<- r2 437 GOTO_OPCODE(ip) @ execute next instruction 438 439 440/* ------------------------------ */ 441 .balign 64 442.L_OP_MOVE_FROM16: /* 0x02 */ 443/* File: armv5te/OP_MOVE_FROM16.S */ 444 /* for: move/from16, move-object/from16 */ 445 /* op vAA, vBBBB */ 446 FETCH(r1, 1) @ r1<- BBBB 447 mov r0, rINST, lsr #8 @ r0<- AA 448 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 449 GET_VREG(r2, r1) @ r2<- fp[BBBB] 450 GET_INST_OPCODE(ip) @ extract opcode from rINST 451 SET_VREG(r2, r0) @ fp[AA]<- r2 452 GOTO_OPCODE(ip) @ jump to next instruction 453 454 455/* ------------------------------ */ 456 .balign 64 457.L_OP_MOVE_16: /* 0x03 */ 458/* File: armv5te/OP_MOVE_16.S */ 459 /* for: move/16, move-object/16 */ 460 /* op vAAAA, vBBBB */ 461 FETCH(r1, 2) @ r1<- BBBB 462 FETCH(r0, 1) @ r0<- AAAA 463 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 464 GET_VREG(r2, r1) @ r2<- fp[BBBB] 465 GET_INST_OPCODE(ip) @ extract opcode from rINST 466 SET_VREG(r2, r0) @ fp[AAAA]<- r2 467 GOTO_OPCODE(ip) @ jump to next instruction 468 469 470/* ------------------------------ */ 471 .balign 64 472.L_OP_MOVE_WIDE: /* 0x04 */ 473/* File: armv5te/OP_MOVE_WIDE.S */ 474 /* move-wide vA, vB */ 475 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 476 mov r2, rINST, lsr #8 @ r2<- A(+) 477 mov r3, rINST, lsr #12 @ r3<- B 478 and r2, r2, #15 479 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 480 add r2, rFP, r2, lsl #2 @ r2<- &fp[A] 481 ldmia r3, {r0-r1} @ r0/r1<- fp[B] 482 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 483 GET_INST_OPCODE(ip) @ extract opcode from rINST 484 stmia r2, {r0-r1} @ fp[A]<- r0/r1 485 GOTO_OPCODE(ip) @ jump to next instruction 486 487 488/* ------------------------------ */ 489 .balign 64 490.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 491/* File: armv5te/OP_MOVE_WIDE_FROM16.S */ 492 /* move-wide/from16 vAA, vBBBB */ 493 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 494 FETCH(r3, 1) @ r3<- BBBB 495 mov r2, rINST, lsr #8 @ r2<- AA 496 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 497 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 498 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 499 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 500 GET_INST_OPCODE(ip) @ extract opcode from rINST 501 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 502 GOTO_OPCODE(ip) @ jump to next instruction 503 504 505/* ------------------------------ */ 506 .balign 64 507.L_OP_MOVE_WIDE_16: /* 0x06 */ 508/* File: armv5te/OP_MOVE_WIDE_16.S */ 509 /* move-wide/16 vAAAA, vBBBB */ 510 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 511 FETCH(r3, 2) @ r3<- BBBB 512 FETCH(r2, 1) @ r2<- AAAA 513 add r3, rFP, r3, lsl #2 @ r3<- &fp[BBBB] 514 add r2, rFP, r2, lsl #2 @ r2<- &fp[AAAA] 515 ldmia r3, {r0-r1} @ r0/r1<- fp[BBBB] 516 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 517 GET_INST_OPCODE(ip) @ extract opcode from rINST 518 stmia r2, {r0-r1} @ fp[AAAA]<- r0/r1 519 GOTO_OPCODE(ip) @ jump to next instruction 520 521 522/* ------------------------------ */ 523 .balign 64 524.L_OP_MOVE_OBJECT: /* 0x07 */ 525/* File: armv5te/OP_MOVE_OBJECT.S */ 526/* File: armv5te/OP_MOVE.S */ 527 /* for move, move-object, long-to-int */ 528 /* op vA, vB */ 529 mov r1, rINST, lsr #12 @ r1<- B from 15:12 530 mov r0, rINST, lsr #8 @ r0<- A from 11:8 531 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 532 GET_VREG(r2, r1) @ r2<- fp[B] 533 and r0, r0, #15 534 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 535 SET_VREG(r2, r0) @ fp[A]<- r2 536 GOTO_OPCODE(ip) @ execute next instruction 537 538 539 540/* ------------------------------ */ 541 .balign 64 542.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 543/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */ 544/* File: armv5te/OP_MOVE_FROM16.S */ 545 /* for: move/from16, move-object/from16 */ 546 /* op vAA, vBBBB */ 547 FETCH(r1, 1) @ r1<- BBBB 548 mov r0, rINST, lsr #8 @ r0<- AA 549 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 550 GET_VREG(r2, r1) @ r2<- fp[BBBB] 551 GET_INST_OPCODE(ip) @ extract opcode from rINST 552 SET_VREG(r2, r0) @ fp[AA]<- r2 553 GOTO_OPCODE(ip) @ jump to next instruction 554 555 556 557/* ------------------------------ */ 558 .balign 64 559.L_OP_MOVE_OBJECT_16: /* 0x09 */ 560/* File: armv5te/OP_MOVE_OBJECT_16.S */ 561/* File: armv5te/OP_MOVE_16.S */ 562 /* for: move/16, move-object/16 */ 563 /* op vAAAA, vBBBB */ 564 FETCH(r1, 2) @ r1<- BBBB 565 FETCH(r0, 1) @ r0<- AAAA 566 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 567 GET_VREG(r2, r1) @ r2<- fp[BBBB] 568 GET_INST_OPCODE(ip) @ extract opcode from rINST 569 SET_VREG(r2, r0) @ fp[AAAA]<- r2 570 GOTO_OPCODE(ip) @ jump to next instruction 571 572 573 574/* ------------------------------ */ 575 .balign 64 576.L_OP_MOVE_RESULT: /* 0x0a */ 577/* File: armv5te/OP_MOVE_RESULT.S */ 578 /* for: move-result, move-result-object */ 579 /* op vAA */ 580 mov r2, rINST, lsr #8 @ r2<- AA 581 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 582 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 583 GET_INST_OPCODE(ip) @ extract opcode from rINST 584 SET_VREG(r0, r2) @ fp[AA]<- r0 585 GOTO_OPCODE(ip) @ jump to next instruction 586 587 588/* ------------------------------ */ 589 .balign 64 590.L_OP_MOVE_RESULT_WIDE: /* 0x0b */ 591/* File: armv5te/OP_MOVE_RESULT_WIDE.S */ 592 /* move-result-wide vAA */ 593 mov r2, rINST, lsr #8 @ r2<- AA 594 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 595 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 596 ldmia r3, {r0-r1} @ r0/r1<- retval.j 597 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 598 GET_INST_OPCODE(ip) @ extract opcode from rINST 599 stmia r2, {r0-r1} @ fp[AA]<- r0/r1 600 GOTO_OPCODE(ip) @ jump to next instruction 601 602 603/* ------------------------------ */ 604 .balign 64 605.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 606/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */ 607/* File: armv5te/OP_MOVE_RESULT.S */ 608 /* for: move-result, move-result-object */ 609 /* op vAA */ 610 mov r2, rINST, lsr #8 @ r2<- AA 611 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 612 ldr r0, [rGLUE, #offGlue_retval] @ r0<- glue->retval.i 613 GET_INST_OPCODE(ip) @ extract opcode from rINST 614 SET_VREG(r0, r2) @ fp[AA]<- r0 615 GOTO_OPCODE(ip) @ jump to next instruction 616 617 618 619/* ------------------------------ */ 620 .balign 64 621.L_OP_MOVE_EXCEPTION: /* 0x0d */ 622/* File: armv5te/OP_MOVE_EXCEPTION.S */ 623 /* move-exception vAA */ 624 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 625 mov r2, rINST, lsr #8 @ r2<- AA 626 ldr r3, [r0, #offThread_exception] @ r3<- dvmGetException bypass 627 mov r1, #0 @ r1<- 0 628 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 629 SET_VREG(r3, r2) @ fp[AA]<- exception obj 630 GET_INST_OPCODE(ip) @ extract opcode from rINST 631 str r1, [r0, #offThread_exception] @ dvmClearException bypass 632 GOTO_OPCODE(ip) @ jump to next instruction 633 634 635/* ------------------------------ */ 636 .balign 64 637.L_OP_RETURN_VOID: /* 0x0e */ 638/* File: armv5te/OP_RETURN_VOID.S */ 639 b common_returnFromMethod 640 641 642/* ------------------------------ */ 643 .balign 64 644.L_OP_RETURN: /* 0x0f */ 645/* File: armv5te/OP_RETURN.S */ 646 /* 647 * Return a 32-bit value. Copies the return value into the "glue" 648 * structure, then jumps to the return handler. 649 * 650 * for: return, return-object 651 */ 652 /* op vAA */ 653 mov r2, rINST, lsr #8 @ r2<- AA 654 GET_VREG(r0, r2) @ r0<- vAA 655 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 656 b common_returnFromMethod 657 658 659/* ------------------------------ */ 660 .balign 64 661.L_OP_RETURN_WIDE: /* 0x10 */ 662/* File: armv5te/OP_RETURN_WIDE.S */ 663 /* 664 * Return a 64-bit value. Copies the return value into the "glue" 665 * structure, then jumps to the return handler. 666 */ 667 /* return-wide vAA */ 668 mov r2, rINST, lsr #8 @ r2<- AA 669 add r2, rFP, r2, lsl #2 @ r2<- &fp[AA] 670 add r3, rGLUE, #offGlue_retval @ r3<- &glue->retval 671 ldmia r2, {r0-r1} @ r0/r1 <- vAA/vAA+1 672 stmia r3, {r0-r1} @ retval<- r0/r1 673 b common_returnFromMethod 674 675 676/* ------------------------------ */ 677 .balign 64 678.L_OP_RETURN_OBJECT: /* 0x11 */ 679/* File: armv5te/OP_RETURN_OBJECT.S */ 680/* File: armv5te/OP_RETURN.S */ 681 /* 682 * Return a 32-bit value. Copies the return value into the "glue" 683 * structure, then jumps to the return handler. 684 * 685 * for: return, return-object 686 */ 687 /* op vAA */ 688 mov r2, rINST, lsr #8 @ r2<- AA 689 GET_VREG(r0, r2) @ r0<- vAA 690 str r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA 691 b common_returnFromMethod 692 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/* ------------------------------ */ 711 .balign 64 712.L_OP_CONST_16: /* 0x13 */ 713/* File: armv5te/OP_CONST_16.S */ 714 /* const/16 vAA, #+BBBB */ 715 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 716 mov r3, rINST, lsr #8 @ r3<- AA 717 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 718 SET_VREG(r0, r3) @ vAA<- r0 719 GET_INST_OPCODE(ip) @ extract opcode from rINST 720 GOTO_OPCODE(ip) @ jump to next instruction 721 722 723/* ------------------------------ */ 724 .balign 64 725.L_OP_CONST: /* 0x14 */ 726/* File: armv5te/OP_CONST.S */ 727 /* const vAA, #+BBBBbbbb */ 728 mov r3, rINST, lsr #8 @ r3<- AA 729 FETCH(r0, 1) @ r0<- bbbb (low) 730 FETCH(r1, 2) @ r1<- BBBB (high) 731 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 732 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 733 GET_INST_OPCODE(ip) @ extract opcode from rINST 734 SET_VREG(r0, r3) @ vAA<- r0 735 GOTO_OPCODE(ip) @ jump to next instruction 736 737 738/* ------------------------------ */ 739 .balign 64 740.L_OP_CONST_HIGH16: /* 0x15 */ 741/* File: armv5te/OP_CONST_HIGH16.S */ 742 /* const/high16 vAA, #+BBBB0000 */ 743 FETCH(r0, 1) @ r0<- 0000BBBB (zero-extended) 744 mov r3, rINST, lsr #8 @ r3<- AA 745 mov r0, r0, lsl #16 @ r0<- BBBB0000 746 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 747 SET_VREG(r0, r3) @ vAA<- r0 748 GET_INST_OPCODE(ip) @ extract opcode from rINST 749 GOTO_OPCODE(ip) @ jump to next instruction 750 751 752/* ------------------------------ */ 753 .balign 64 754.L_OP_CONST_WIDE_16: /* 0x16 */ 755/* File: armv5te/OP_CONST_WIDE_16.S */ 756 /* const-wide/16 vAA, #+BBBB */ 757 FETCH_S(r0, 1) @ r0<- ssssBBBB (sign-extended) 758 mov r3, rINST, lsr #8 @ r3<- AA 759 mov r1, r0, asr #31 @ r1<- ssssssss 760 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 761 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 762 GET_INST_OPCODE(ip) @ extract opcode from rINST 763 stmia r3, {r0-r1} @ vAA<- r0/r1 764 GOTO_OPCODE(ip) @ jump to next instruction 765 766 767/* ------------------------------ */ 768 .balign 64 769.L_OP_CONST_WIDE_32: /* 0x17 */ 770/* File: armv5te/OP_CONST_WIDE_32.S */ 771 /* const-wide/32 vAA, #+BBBBbbbb */ 772 FETCH(r0, 1) @ r0<- 0000bbbb (low) 773 mov r3, rINST, lsr #8 @ r3<- AA 774 FETCH_S(r2, 2) @ r2<- ssssBBBB (high) 775 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 776 orr r0, r0, r2, lsl #16 @ r0<- BBBBbbbb 777 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 778 mov r1, r0, asr #31 @ r1<- ssssssss 779 GET_INST_OPCODE(ip) @ extract opcode from rINST 780 stmia r3, {r0-r1} @ vAA<- r0/r1 781 GOTO_OPCODE(ip) @ jump to next instruction 782 783 784/* ------------------------------ */ 785 .balign 64 786.L_OP_CONST_WIDE: /* 0x18 */ 787/* File: armv5te/OP_CONST_WIDE.S */ 788 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 789 FETCH(r0, 1) @ r0<- bbbb (low) 790 FETCH(r1, 2) @ r1<- BBBB (low middle) 791 FETCH(r2, 3) @ r2<- hhhh (high middle) 792 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb (low word) 793 FETCH(r3, 4) @ r3<- HHHH (high) 794 mov r9, rINST, lsr #8 @ r9<- AA 795 orr r1, r2, r3, lsl #16 @ r1<- HHHHhhhh (high word) 796 FETCH_ADVANCE_INST(5) @ advance rPC, load rINST 797 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 798 GET_INST_OPCODE(ip) @ extract opcode from rINST 799 stmia r9, {r0-r1} @ vAA<- r0/r1 800 GOTO_OPCODE(ip) @ jump to next instruction 801 802 803/* ------------------------------ */ 804 .balign 64 805.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 806/* File: armv5te/OP_CONST_WIDE_HIGH16.S */ 807 /* const-wide/high16 vAA, #+BBBB000000000000 */ 808 FETCH(r1, 1) @ r1<- 0000BBBB (zero-extended) 809 mov r3, rINST, lsr #8 @ r3<- AA 810 mov r0, #0 @ r0<- 00000000 811 mov r1, r1, lsl #16 @ r1<- BBBB0000 812 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 813 add r3, rFP, r3, lsl #2 @ r3<- &fp[AA] 814 GET_INST_OPCODE(ip) @ extract opcode from rINST 815 stmia r3, {r0-r1} @ vAA<- r0/r1 816 GOTO_OPCODE(ip) @ jump to next instruction 817 818 819/* ------------------------------ */ 820 .balign 64 821.L_OP_CONST_STRING: /* 0x1a */ 822/* File: armv5te/OP_CONST_STRING.S */ 823 /* const/string vAA, String@BBBB */ 824 FETCH(r1, 1) @ r1<- BBBB 825 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 826 mov r9, rINST, lsr #8 @ r9<- AA 827 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 828 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 829 cmp r0, #0 @ not yet resolved? 830 beq .LOP_CONST_STRING_resolve 831 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 832 GET_INST_OPCODE(ip) @ extract opcode from rINST 833 SET_VREG(r0, r9) @ vAA<- r0 834 GOTO_OPCODE(ip) @ jump to next instruction 835 836/* ------------------------------ */ 837 .balign 64 838.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 839/* File: armv5te/OP_CONST_STRING_JUMBO.S */ 840 /* const/string vAA, String@BBBBBBBB */ 841 FETCH(r0, 1) @ r0<- bbbb (low) 842 FETCH(r1, 2) @ r1<- BBBB (high) 843 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 844 mov r9, rINST, lsr #8 @ r9<- AA 845 ldr r2, [r2, #offDvmDex_pResStrings] @ r2<- dvmDex->pResStrings 846 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 847 ldr r0, [r2, r1, lsl #2] @ r0<- pResStrings[BBBB] 848 cmp r0, #0 849 beq .LOP_CONST_STRING_JUMBO_resolve 850 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 851 GET_INST_OPCODE(ip) @ extract opcode from rINST 852 SET_VREG(r0, r9) @ vAA<- r0 853 GOTO_OPCODE(ip) @ jump to next instruction 854 855/* ------------------------------ */ 856 .balign 64 857.L_OP_CONST_CLASS: /* 0x1c */ 858/* File: armv5te/OP_CONST_CLASS.S */ 859 /* const/class vAA, Class@BBBB */ 860 FETCH(r1, 1) @ r1<- BBBB 861 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- glue->methodClassDex 862 mov r9, rINST, lsr #8 @ r9<- AA 863 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- dvmDex->pResClasses 864 ldr r0, [r2, r1, lsl #2] @ r0<- pResClasses[BBBB] 865 cmp r0, #0 @ not yet resolved? 866 beq .LOP_CONST_CLASS_resolve 867 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 868 GET_INST_OPCODE(ip) @ extract opcode from rINST 869 SET_VREG(r0, r9) @ vAA<- r0 870 GOTO_OPCODE(ip) @ jump to next instruction 871 872/* ------------------------------ */ 873 .balign 64 874.L_OP_MONITOR_ENTER: /* 0x1d */ 875/* File: armv5te/OP_MONITOR_ENTER.S */ 876 /* 877 * Synchronize on an object. 878 */ 879 /* monitor-enter vAA */ 880 mov r2, rINST, lsr #8 @ r2<- AA 881 GET_VREG(r1, r2) @ r1<- vAA (object) 882 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 883 cmp r1, #0 @ null object? 884 EXPORT_PC() @ need for precise GC, MONITOR_TRACKING 885 beq common_errNullObject @ null object, throw an exception 886 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 887 bl dvmLockObject @ call(self, obj) 888#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ 889 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 890 ldr r1, [r0, #offThread_exception] @ check for exception 891 cmp r1, #0 892 bne common_exceptionThrown @ exception raised, bail out 893#endif 894 GET_INST_OPCODE(ip) @ extract opcode from rINST 895 GOTO_OPCODE(ip) @ jump to next instruction 896 897 898/* ------------------------------ */ 899 .balign 64 900.L_OP_MONITOR_EXIT: /* 0x1e */ 901/* File: armv5te/OP_MONITOR_EXIT.S */ 902 /* 903 * Unlock an object. 904 * 905 * Exceptions that occur when unlocking a monitor need to appear as 906 * if they happened at the following instruction. See the Dalvik 907 * instruction spec. 908 */ 909 /* monitor-exit vAA */ 910 mov r2, rINST, lsr #8 @ r2<- AA 911 EXPORT_PC() @ before fetch: export the PC 912 GET_VREG(r1, r2) @ r1<- vAA (object) 913 cmp r1, #0 @ null object? 914 beq 1f @ yes 915 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 916 bl dvmUnlockObject @ r0<- success for unlock(self, obj) 917 cmp r0, #0 @ failed? 918 FETCH_ADVANCE_INST(1) @ before throw: advance rPC, load rINST 919 beq common_exceptionThrown @ yes, exception is pending 920 GET_INST_OPCODE(ip) @ extract opcode from rINST 921 GOTO_OPCODE(ip) @ jump to next instruction 9221: 923 FETCH_ADVANCE_INST(1) @ advance before throw 924 b common_errNullObject 925 926 927/* ------------------------------ */ 928 .balign 64 929.L_OP_CHECK_CAST: /* 0x1f */ 930/* File: armv5te/OP_CHECK_CAST.S */ 931 /* 932 * Check to see if a cast from one class to another is allowed. 933 */ 934 /* check-cast vAA, class@BBBB */ 935 mov r3, rINST, lsr #8 @ r3<- AA 936 FETCH(r2, 1) @ r2<- BBBB 937 GET_VREG(r9, r3) @ r9<- object 938 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- pDvmDex 939 cmp r9, #0 @ is object null? 940 ldr r0, [r0, #offDvmDex_pResClasses] @ r0<- pDvmDex->pResClasses 941 beq .LOP_CHECK_CAST_okay @ null obj, cast always succeeds 942 ldr r1, [r0, r2, lsl #2] @ r1<- resolved class 943 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 944 cmp r1, #0 @ have we resolved this before? 945 beq .LOP_CHECK_CAST_resolve @ not resolved, do it now 946.LOP_CHECK_CAST_resolved: 947 cmp r0, r1 @ same class (trivial success)? 948 bne .LOP_CHECK_CAST_fullcheck @ no, do full check 949.LOP_CHECK_CAST_okay: 950 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 951 GET_INST_OPCODE(ip) @ extract opcode from rINST 952 GOTO_OPCODE(ip) @ jump to next instruction 953 954/* ------------------------------ */ 955 .balign 64 956.L_OP_INSTANCE_OF: /* 0x20 */ 957/* File: armv5te/OP_INSTANCE_OF.S */ 958 /* 959 * Check to see if an object reference is an instance of a class. 960 * 961 * Most common situation is a non-null object, being compared against 962 * an already-resolved class. 963 */ 964 /* instance-of vA, vB, class@CCCC */ 965 mov r3, rINST, lsr #12 @ r3<- B 966 mov r9, rINST, lsr #8 @ r9<- A+ 967 GET_VREG(r0, r3) @ r0<- vB (object) 968 and r9, r9, #15 @ r9<- A 969 cmp r0, #0 @ is object null? 970 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- pDvmDex 971 beq .LOP_INSTANCE_OF_store @ null obj, not an instance, store r0 972 FETCH(r3, 1) @ r3<- CCCC 973 ldr r2, [r2, #offDvmDex_pResClasses] @ r2<- pDvmDex->pResClasses 974 ldr r1, [r2, r3, lsl #2] @ r1<- resolved class 975 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 976 cmp r1, #0 @ have we resolved this before? 977 beq .LOP_INSTANCE_OF_resolve @ not resolved, do it now 978.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class 979 cmp r0, r1 @ same class (trivial success)? 980 beq .LOP_INSTANCE_OF_trivial @ yes, trivial finish 981 b .LOP_INSTANCE_OF_fullcheck @ no, do full check 982 983/* ------------------------------ */ 984 .balign 64 985.L_OP_ARRAY_LENGTH: /* 0x21 */ 986/* File: armv5te/OP_ARRAY_LENGTH.S */ 987 /* 988 * Return the length of an array. 989 */ 990 mov r1, rINST, lsr #12 @ r1<- B 991 mov r2, rINST, lsr #8 @ r2<- A+ 992 GET_VREG(r0, r1) @ r0<- vB (object ref) 993 and r2, r2, #15 @ r2<- A 994 cmp r0, #0 @ is object null? 995 beq common_errNullObject @ yup, fail 996 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 997 ldr r3, [r0, #offArrayObject_length] @ r3<- array length 998 GET_INST_OPCODE(ip) @ extract opcode from rINST 999 SET_VREG(r3, r2) @ vB<- length 1000 GOTO_OPCODE(ip) @ jump to next instruction 1001 1002 1003/* ------------------------------ */ 1004 .balign 64 1005.L_OP_NEW_INSTANCE: /* 0x22 */ 1006/* File: armv5te/OP_NEW_INSTANCE.S */ 1007 /* 1008 * Create a new instance of a class. 1009 */ 1010 /* new-instance vAA, class@BBBB */ 1011 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1012 FETCH(r1, 1) @ r1<- BBBB 1013 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1014 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1015 EXPORT_PC() @ req'd for init, resolve, alloc 1016 cmp r0, #0 @ already resolved? 1017 beq .LOP_NEW_INSTANCE_resolve @ no, resolve it now 1018.LOP_NEW_INSTANCE_resolved: @ r0=class 1019 ldrb r1, [r0, #offClassObject_status] @ r1<- ClassStatus enum 1020 cmp r1, #CLASS_INITIALIZED @ has class been initialized? 1021 bne .LOP_NEW_INSTANCE_needinit @ no, init class now 1022.LOP_NEW_INSTANCE_initialized: @ r0=class 1023 mov r1, #ALLOC_DONT_TRACK @ flags for alloc call 1024 bl dvmAllocObject @ r0<- new object 1025 b .LOP_NEW_INSTANCE_finish @ continue 1026 1027/* ------------------------------ */ 1028 .balign 64 1029.L_OP_NEW_ARRAY: /* 0x23 */ 1030/* File: armv5te/OP_NEW_ARRAY.S */ 1031 /* 1032 * Allocate an array of objects, specified with the array class 1033 * and a count. 1034 * 1035 * The verifier guarantees that this is an array class, so we don't 1036 * check for it here. 1037 */ 1038 /* new-array vA, vB, class@CCCC */ 1039 mov r0, rINST, lsr #12 @ r0<- B 1040 FETCH(r2, 1) @ r2<- CCCC 1041 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1042 GET_VREG(r1, r0) @ r1<- vB (array length) 1043 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1044 cmp r1, #0 @ check length 1045 ldr r0, [r3, r2, lsl #2] @ r0<- resolved class 1046 bmi common_errNegativeArraySize @ negative length, bail 1047 cmp r0, #0 @ already resolved? 1048 EXPORT_PC() @ req'd for resolve, alloc 1049 bne .LOP_NEW_ARRAY_finish @ resolved, continue 1050 b .LOP_NEW_ARRAY_resolve @ do resolve now 1051 1052/* ------------------------------ */ 1053 .balign 64 1054.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1055/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1056 /* 1057 * Create a new array with elements filled from registers. 1058 * 1059 * for: filled-new-array, filled-new-array/range 1060 */ 1061 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1062 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1063 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1064 FETCH(r1, 1) @ r1<- BBBB 1065 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1066 EXPORT_PC() @ need for resolve and alloc 1067 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1068 mov r10, rINST, lsr #8 @ r10<- AA or BA 1069 cmp r0, #0 @ already resolved? 1070 bne .LOP_FILLED_NEW_ARRAY_continue @ yes, continue on 10718: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1072 mov r2, #0 @ r2<- false 1073 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1074 bl dvmResolveClass @ r0<- call(clazz, ref) 1075 cmp r0, #0 @ got null? 1076 beq common_exceptionThrown @ yes, handle exception 1077 b .LOP_FILLED_NEW_ARRAY_continue 1078 1079/* ------------------------------ */ 1080 .balign 64 1081.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1082/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */ 1083/* File: armv5te/OP_FILLED_NEW_ARRAY.S */ 1084 /* 1085 * Create a new array with elements filled from registers. 1086 * 1087 * for: filled-new-array, filled-new-array/range 1088 */ 1089 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1090 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1091 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 1092 FETCH(r1, 1) @ r1<- BBBB 1093 ldr r3, [r3, #offDvmDex_pResClasses] @ r3<- pDvmDex->pResClasses 1094 EXPORT_PC() @ need for resolve and alloc 1095 ldr r0, [r3, r1, lsl #2] @ r0<- resolved class 1096 mov r10, rINST, lsr #8 @ r10<- AA or BA 1097 cmp r0, #0 @ already resolved? 1098 bne .LOP_FILLED_NEW_ARRAY_RANGE_continue @ yes, continue on 10998: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 1100 mov r2, #0 @ r2<- false 1101 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 1102 bl dvmResolveClass @ r0<- call(clazz, ref) 1103 cmp r0, #0 @ got null? 1104 beq common_exceptionThrown @ yes, handle exception 1105 b .LOP_FILLED_NEW_ARRAY_RANGE_continue 1106 1107 1108/* ------------------------------ */ 1109 .balign 64 1110.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1111/* File: armv5te/OP_FILL_ARRAY_DATA.S */ 1112 /* fill-array-data vAA, +BBBBBBBB */ 1113 FETCH(r0, 1) @ r0<- bbbb (lo) 1114 FETCH(r1, 2) @ r1<- BBBB (hi) 1115 mov r3, rINST, lsr #8 @ r3<- AA 1116 orr r1, r0, r1, lsl #16 @ r1<- BBBBbbbb 1117 GET_VREG(r0, r3) @ r0<- vAA (array object) 1118 add r1, rPC, r1, lsl #1 @ r1<- PC + BBBBbbbb*2 (array data off.) 1119 EXPORT_PC(); 1120 bl dvmInterpHandleFillArrayData@ fill the array with predefined data 1121 cmp r0, #0 @ 0 means an exception is thrown 1122 beq common_exceptionThrown @ has exception 1123 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 1124 GET_INST_OPCODE(ip) @ extract opcode from rINST 1125 GOTO_OPCODE(ip) @ jump to next instruction 1126 1127/* ------------------------------ */ 1128 .balign 64 1129.L_OP_THROW: /* 0x27 */ 1130/* File: armv5te/OP_THROW.S */ 1131 /* 1132 * Throw an exception object in the current thread. 1133 */ 1134 /* throw vAA */ 1135 mov r2, rINST, lsr #8 @ r2<- AA 1136 GET_VREG(r1, r2) @ r1<- vAA (exception object) 1137 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 1138 EXPORT_PC() @ exception handler can throw 1139 cmp r1, #0 @ null object? 1140 beq common_errNullObject @ yes, throw an NPE instead 1141 @ bypass dvmSetException, just store it 1142 str r1, [r0, #offThread_exception] @ thread->exception<- obj 1143 b common_exceptionThrown 1144 1145 1146/* ------------------------------ */ 1147 .balign 64 1148.L_OP_GOTO: /* 0x28 */ 1149/* File: armv5te/OP_GOTO.S */ 1150 /* 1151 * Unconditional branch, 8-bit offset. 1152 * 1153 * The branch distance is a signed code-unit offset, which we need to 1154 * double to get a byte offset. 1155 */ 1156 /* goto +AA */ 1157 mov r0, rINST, lsl #16 @ r0<- AAxx0000 1158 movs r9, r0, asr #24 @ r9<- ssssssAA (sign-extended) 1159 mov r9, r9, lsl #1 @ r9<- byte offset 1160 bmi common_backwardBranch @ backward branch, do periodic checks 1161#if defined(WITH_JIT) 1162 GET_JIT_PROF_TABLE(r0) 1163 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1164 cmp r0,#0 1165 bne common_updateProfile 1166 GET_INST_OPCODE(ip) @ extract opcode from rINST 1167 GOTO_OPCODE(ip) @ jump to next instruction 1168#else 1169 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1170 GET_INST_OPCODE(ip) @ extract opcode from rINST 1171 GOTO_OPCODE(ip) @ jump to next instruction 1172#endif 1173 1174/* ------------------------------ */ 1175 .balign 64 1176.L_OP_GOTO_16: /* 0x29 */ 1177/* File: armv5te/OP_GOTO_16.S */ 1178 /* 1179 * Unconditional branch, 16-bit offset. 1180 * 1181 * The branch distance is a signed code-unit offset, which we need to 1182 * double to get a byte offset. 1183 */ 1184 /* goto/16 +AAAA */ 1185 FETCH_S(r0, 1) @ r0<- ssssAAAA (sign-extended) 1186 movs r9, r0, asl #1 @ r9<- byte offset, check sign 1187 bmi common_backwardBranch @ backward branch, do periodic checks 1188#if defined(WITH_JIT) 1189 GET_JIT_PROF_TABLE(r0) 1190 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1191 cmp r0,#0 1192 bne common_updateProfile 1193 GET_INST_OPCODE(ip) @ extract opcode from rINST 1194 GOTO_OPCODE(ip) @ jump to next instruction 1195#else 1196 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1197 GET_INST_OPCODE(ip) @ extract opcode from rINST 1198 GOTO_OPCODE(ip) @ jump to next instruction 1199#endif 1200 1201 1202/* ------------------------------ */ 1203 .balign 64 1204.L_OP_GOTO_32: /* 0x2a */ 1205/* File: armv5te/OP_GOTO_32.S */ 1206 /* 1207 * Unconditional branch, 32-bit offset. 1208 * 1209 * The branch distance is a signed code-unit offset, which we need to 1210 * double to get a byte offset. 1211 * 1212 * Unlike most opcodes, this one is allowed to branch to itself, so 1213 * our "backward branch" test must be "<=0" instead of "<0". The ORRS 1214 * instruction doesn't affect the V flag, so we need to clear it 1215 * explicitly. 1216 */ 1217 /* goto/32 +AAAAAAAA */ 1218 FETCH(r0, 1) @ r0<- aaaa (lo) 1219 FETCH(r1, 2) @ r1<- AAAA (hi) 1220 cmp ip, ip @ (clear V flag during stall) 1221 orrs r0, r0, r1, lsl #16 @ r0<- AAAAaaaa, check sign 1222 mov r9, r0, asl #1 @ r9<- byte offset 1223 ble common_backwardBranch @ backward branch, do periodic checks 1224#if defined(WITH_JIT) 1225 GET_JIT_PROF_TABLE(r0) 1226 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1227 cmp r0,#0 1228 bne common_updateProfile 1229 GET_INST_OPCODE(ip) @ extract opcode from rINST 1230 GOTO_OPCODE(ip) @ jump to next instruction 1231#else 1232 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1233 GET_INST_OPCODE(ip) @ extract opcode from rINST 1234 GOTO_OPCODE(ip) @ jump to next instruction 1235#endif 1236 1237/* ------------------------------ */ 1238 .balign 64 1239.L_OP_PACKED_SWITCH: /* 0x2b */ 1240/* File: armv5te/OP_PACKED_SWITCH.S */ 1241 /* 1242 * Handle a packed-switch or sparse-switch instruction. In both cases 1243 * we decode it and hand it off to a helper function. 1244 * 1245 * We don't really expect backward branches in a switch statement, but 1246 * they're perfectly legal, so we check for them here. 1247 * 1248 * for: packed-switch, sparse-switch 1249 */ 1250 /* op vAA, +BBBB */ 1251 FETCH(r0, 1) @ r0<- bbbb (lo) 1252 FETCH(r1, 2) @ r1<- BBBB (hi) 1253 mov r3, rINST, lsr #8 @ r3<- AA 1254 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1255 GET_VREG(r1, r3) @ r1<- vAA 1256 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1257 bl dvmInterpHandlePackedSwitch @ r0<- code-unit branch offset 1258 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1259 bmi common_backwardBranch @ backward branch, do periodic checks 1260 beq common_backwardBranch @ (want to use BLE but V is unknown) 1261#if defined(WITH_JIT) 1262 GET_JIT_PROF_TABLE(r0) 1263 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1264 cmp r0,#0 1265 bne common_updateProfile 1266 GET_INST_OPCODE(ip) @ extract opcode from rINST 1267 GOTO_OPCODE(ip) @ jump to next instruction 1268#else 1269 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1270 GET_INST_OPCODE(ip) @ extract opcode from rINST 1271 GOTO_OPCODE(ip) @ jump to next instruction 1272#endif 1273 1274 1275/* ------------------------------ */ 1276 .balign 64 1277.L_OP_SPARSE_SWITCH: /* 0x2c */ 1278/* File: armv5te/OP_SPARSE_SWITCH.S */ 1279/* File: armv5te/OP_PACKED_SWITCH.S */ 1280 /* 1281 * Handle a packed-switch or sparse-switch instruction. In both cases 1282 * we decode it and hand it off to a helper function. 1283 * 1284 * We don't really expect backward branches in a switch statement, but 1285 * they're perfectly legal, so we check for them here. 1286 * 1287 * for: packed-switch, sparse-switch 1288 */ 1289 /* op vAA, +BBBB */ 1290 FETCH(r0, 1) @ r0<- bbbb (lo) 1291 FETCH(r1, 2) @ r1<- BBBB (hi) 1292 mov r3, rINST, lsr #8 @ r3<- AA 1293 orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 1294 GET_VREG(r1, r3) @ r1<- vAA 1295 add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 1296 bl dvmInterpHandleSparseSwitch @ r0<- code-unit branch offset 1297 movs r9, r0, asl #1 @ r9<- branch byte offset, check sign 1298 bmi common_backwardBranch @ backward branch, do periodic checks 1299 beq common_backwardBranch @ (want to use BLE but V is unknown) 1300#if defined(WITH_JIT) 1301 GET_JIT_PROF_TABLE(r0) 1302 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1303 cmp r0,#0 1304 bne common_updateProfile 1305 GET_INST_OPCODE(ip) @ extract opcode from rINST 1306 GOTO_OPCODE(ip) @ jump to next instruction 1307#else 1308 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1309 GET_INST_OPCODE(ip) @ extract opcode from rINST 1310 GOTO_OPCODE(ip) @ jump to next instruction 1311#endif 1312 1313 1314 1315/* ------------------------------ */ 1316 .balign 64 1317.L_OP_CMPL_FLOAT: /* 0x2d */ 1318/* File: arm-vfp/OP_CMPL_FLOAT.S */ 1319 /* 1320 * Compare two floating-point values. Puts 0, 1, or -1 into the 1321 * destination register based on the results of the comparison. 1322 * 1323 * int compare(x, y) { 1324 * if (x == y) { 1325 * return 0; 1326 * } else if (x > y) { 1327 * return 1; 1328 * } else if (x < y) { 1329 * return -1; 1330 * } else { 1331 * return -1; 1332 * } 1333 * } 1334 */ 1335 /* op vAA, vBB, vCC */ 1336 FETCH(r0, 1) @ r0<- CCBB 1337 mov r9, rINST, lsr #8 @ r9<- AA 1338 and r2, r0, #255 @ r2<- BB 1339 mov r3, r0, lsr #8 @ r3<- CC 1340 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1341 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1342 flds s0, [r2] @ s0<- vBB 1343 flds s1, [r3] @ s1<- vCC 1344 fcmpes s0, s1 @ compare (vBB, vCC) 1345 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1346 mvn r0, #0 @ r0<- -1 (default) 1347 GET_INST_OPCODE(ip) @ extract opcode from rINST 1348 fmstat @ export status flags 1349 movgt r0, #1 @ (greater than) r1<- 1 1350 moveq r0, #0 @ (equal) r1<- 0 1351 b .LOP_CMPL_FLOAT_finish @ argh 1352 1353 1354/* ------------------------------ */ 1355 .balign 64 1356.L_OP_CMPG_FLOAT: /* 0x2e */ 1357/* File: arm-vfp/OP_CMPG_FLOAT.S */ 1358 /* 1359 * Compare two floating-point values. Puts 0, 1, or -1 into the 1360 * destination register based on the results of the comparison. 1361 * 1362 * int compare(x, y) { 1363 * if (x == y) { 1364 * return 0; 1365 * } else if (x < y) { 1366 * return -1; 1367 * } else if (x > y) { 1368 * return 1; 1369 * } else { 1370 * return 1; 1371 * } 1372 * } 1373 */ 1374 /* op vAA, vBB, vCC */ 1375 FETCH(r0, 1) @ r0<- CCBB 1376 mov r9, rINST, lsr #8 @ r9<- AA 1377 and r2, r0, #255 @ r2<- BB 1378 mov r3, r0, lsr #8 @ r3<- CC 1379 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1380 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1381 flds s0, [r2] @ s0<- vBB 1382 flds s1, [r3] @ s1<- vCC 1383 fcmpes s0, s1 @ compare (vBB, vCC) 1384 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1385 mov r0, #1 @ r0<- 1 (default) 1386 GET_INST_OPCODE(ip) @ extract opcode from rINST 1387 fmstat @ export status flags 1388 mvnmi r0, #0 @ (less than) r1<- -1 1389 moveq r0, #0 @ (equal) r1<- 0 1390 b .LOP_CMPG_FLOAT_finish @ argh 1391 1392 1393/* ------------------------------ */ 1394 .balign 64 1395.L_OP_CMPL_DOUBLE: /* 0x2f */ 1396/* File: arm-vfp/OP_CMPL_DOUBLE.S */ 1397 /* 1398 * Compare two floating-point values. Puts 0, 1, or -1 into the 1399 * destination register based on the results of the comparison. 1400 * 1401 * int compare(x, y) { 1402 * if (x == y) { 1403 * return 0; 1404 * } else if (x > y) { 1405 * return 1; 1406 * } else if (x < y) { 1407 * return -1; 1408 * } else { 1409 * return -1; 1410 * } 1411 * } 1412 */ 1413 /* op vAA, vBB, vCC */ 1414 FETCH(r0, 1) @ r0<- CCBB 1415 mov r9, rINST, lsr #8 @ r9<- AA 1416 and r2, r0, #255 @ r2<- BB 1417 mov r3, r0, lsr #8 @ r3<- CC 1418 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1419 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1420 fldd d0, [r2] @ d0<- vBB 1421 fldd d1, [r3] @ d1<- vCC 1422 fcmped d0, d1 @ compare (vBB, vCC) 1423 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1424 mvn r0, #0 @ r0<- -1 (default) 1425 GET_INST_OPCODE(ip) @ extract opcode from rINST 1426 fmstat @ export status flags 1427 movgt r0, #1 @ (greater than) r1<- 1 1428 moveq r0, #0 @ (equal) r1<- 0 1429 b .LOP_CMPL_DOUBLE_finish @ argh 1430 1431 1432/* ------------------------------ */ 1433 .balign 64 1434.L_OP_CMPG_DOUBLE: /* 0x30 */ 1435/* File: arm-vfp/OP_CMPG_DOUBLE.S */ 1436 /* 1437 * Compare two floating-point values. Puts 0, 1, or -1 into the 1438 * destination register based on the results of the comparison. 1439 * 1440 * int compare(x, y) { 1441 * if (x == y) { 1442 * return 0; 1443 * } else if (x < y) { 1444 * return -1; 1445 * } else if (x > y) { 1446 * return 1; 1447 * } else { 1448 * return 1; 1449 * } 1450 * } 1451 */ 1452 /* op vAA, vBB, vCC */ 1453 FETCH(r0, 1) @ r0<- CCBB 1454 mov r9, rINST, lsr #8 @ r9<- AA 1455 and r2, r0, #255 @ r2<- BB 1456 mov r3, r0, lsr #8 @ r3<- CC 1457 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 1458 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 1459 fldd d0, [r2] @ d0<- vBB 1460 fldd d1, [r3] @ d1<- vCC 1461 fcmped d0, d1 @ compare (vBB, vCC) 1462 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 1463 mov r0, #1 @ r0<- 1 (default) 1464 GET_INST_OPCODE(ip) @ extract opcode from rINST 1465 fmstat @ export status flags 1466 mvnmi r0, #0 @ (less than) r1<- -1 1467 moveq r0, #0 @ (equal) r1<- 0 1468 b .LOP_CMPG_DOUBLE_finish @ argh 1469 1470 1471/* ------------------------------ */ 1472 .balign 64 1473.L_OP_CMP_LONG: /* 0x31 */ 1474/* File: armv5te/OP_CMP_LONG.S */ 1475 /* 1476 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1477 * register based on the results of the comparison. 1478 * 1479 * We load the full values with LDM, but in practice many values could 1480 * be resolved by only looking at the high word. This could be made 1481 * faster or slower by splitting the LDM into a pair of LDRs. 1482 * 1483 * If we just wanted to set condition flags, we could do this: 1484 * subs ip, r0, r2 1485 * sbcs ip, r1, r3 1486 * subeqs ip, r0, r2 1487 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific 1488 * integer value, which we can do with 2 conditional mov/mvn instructions 1489 * (set 1, set -1; if they're equal we already have 0 in ip), giving 1490 * us a constant 5-cycle path plus a branch at the end to the 1491 * instruction epilogue code. The multi-compare approach below needs 1492 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch 1493 * in the worst case (the 64-bit values are equal). 1494 */ 1495 /* cmp-long vAA, vBB, vCC */ 1496 FETCH(r0, 1) @ r0<- CCBB 1497 mov r9, rINST, lsr #8 @ r9<- AA 1498 and r2, r0, #255 @ r2<- BB 1499 mov r3, r0, lsr #8 @ r3<- CC 1500 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 1501 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 1502 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 1503 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 1504 cmp r1, r3 @ compare (vBB+1, vCC+1) 1505 blt .LOP_CMP_LONG_less @ signed compare on high part 1506 bgt .LOP_CMP_LONG_greater 1507 subs r1, r0, r2 @ r1<- r0 - r2 1508 bhi .LOP_CMP_LONG_greater @ unsigned compare on low part 1509 bne .LOP_CMP_LONG_less 1510 b .LOP_CMP_LONG_finish @ equal; r1 already holds 0 1511 1512/* ------------------------------ */ 1513 .balign 64 1514.L_OP_IF_EQ: /* 0x32 */ 1515/* File: armv5te/OP_IF_EQ.S */ 1516/* File: armv5te/bincmp.S */ 1517 /* 1518 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1519 * fragment that specifies the *reverse* comparison to perform, e.g. 1520 * for "if-le" you would use "gt". 1521 * 1522 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1523 */ 1524 /* if-cmp vA, vB, +CCCC */ 1525 mov r0, rINST, lsr #8 @ r0<- A+ 1526 mov r1, rINST, lsr #12 @ r1<- B 1527 and r0, r0, #15 1528 GET_VREG(r3, r1) @ r3<- vB 1529 GET_VREG(r2, r0) @ r2<- vA 1530 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1531 cmp r2, r3 @ compare (vA, vB) 1532 bne 1f @ branch to 1 if comparison failed 1533 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1534 movs r9, r9, asl #1 @ convert to bytes, check sign 1535 bmi common_backwardBranch @ yes, do periodic checks 15361: 1537#if defined(WITH_JIT) 1538 GET_JIT_PROF_TABLE(r0) 1539 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1540 b common_testUpdateProfile 1541#else 1542 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1543 GET_INST_OPCODE(ip) @ extract opcode from rINST 1544 GOTO_OPCODE(ip) @ jump to next instruction 1545#endif 1546 1547 1548 1549/* ------------------------------ */ 1550 .balign 64 1551.L_OP_IF_NE: /* 0x33 */ 1552/* File: armv5te/OP_IF_NE.S */ 1553/* File: armv5te/bincmp.S */ 1554 /* 1555 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1556 * fragment that specifies the *reverse* comparison to perform, e.g. 1557 * for "if-le" you would use "gt". 1558 * 1559 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1560 */ 1561 /* if-cmp vA, vB, +CCCC */ 1562 mov r0, rINST, lsr #8 @ r0<- A+ 1563 mov r1, rINST, lsr #12 @ r1<- B 1564 and r0, r0, #15 1565 GET_VREG(r3, r1) @ r3<- vB 1566 GET_VREG(r2, r0) @ r2<- vA 1567 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1568 cmp r2, r3 @ compare (vA, vB) 1569 beq 1f @ branch to 1 if comparison failed 1570 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1571 movs r9, r9, asl #1 @ convert to bytes, check sign 1572 bmi common_backwardBranch @ yes, do periodic checks 15731: 1574#if defined(WITH_JIT) 1575 GET_JIT_PROF_TABLE(r0) 1576 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1577 b common_testUpdateProfile 1578#else 1579 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1580 GET_INST_OPCODE(ip) @ extract opcode from rINST 1581 GOTO_OPCODE(ip) @ jump to next instruction 1582#endif 1583 1584 1585 1586/* ------------------------------ */ 1587 .balign 64 1588.L_OP_IF_LT: /* 0x34 */ 1589/* File: armv5te/OP_IF_LT.S */ 1590/* File: armv5te/bincmp.S */ 1591 /* 1592 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1593 * fragment that specifies the *reverse* comparison to perform, e.g. 1594 * for "if-le" you would use "gt". 1595 * 1596 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1597 */ 1598 /* if-cmp vA, vB, +CCCC */ 1599 mov r0, rINST, lsr #8 @ r0<- A+ 1600 mov r1, rINST, lsr #12 @ r1<- B 1601 and r0, r0, #15 1602 GET_VREG(r3, r1) @ r3<- vB 1603 GET_VREG(r2, r0) @ r2<- vA 1604 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1605 cmp r2, r3 @ compare (vA, vB) 1606 bge 1f @ branch to 1 if comparison failed 1607 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1608 movs r9, r9, asl #1 @ convert to bytes, check sign 1609 bmi common_backwardBranch @ yes, do periodic checks 16101: 1611#if defined(WITH_JIT) 1612 GET_JIT_PROF_TABLE(r0) 1613 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1614 b common_testUpdateProfile 1615#else 1616 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1617 GET_INST_OPCODE(ip) @ extract opcode from rINST 1618 GOTO_OPCODE(ip) @ jump to next instruction 1619#endif 1620 1621 1622 1623/* ------------------------------ */ 1624 .balign 64 1625.L_OP_IF_GE: /* 0x35 */ 1626/* File: armv5te/OP_IF_GE.S */ 1627/* File: armv5te/bincmp.S */ 1628 /* 1629 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1630 * fragment that specifies the *reverse* comparison to perform, e.g. 1631 * for "if-le" you would use "gt". 1632 * 1633 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1634 */ 1635 /* if-cmp vA, vB, +CCCC */ 1636 mov r0, rINST, lsr #8 @ r0<- A+ 1637 mov r1, rINST, lsr #12 @ r1<- B 1638 and r0, r0, #15 1639 GET_VREG(r3, r1) @ r3<- vB 1640 GET_VREG(r2, r0) @ r2<- vA 1641 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1642 cmp r2, r3 @ compare (vA, vB) 1643 blt 1f @ branch to 1 if comparison failed 1644 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1645 movs r9, r9, asl #1 @ convert to bytes, check sign 1646 bmi common_backwardBranch @ yes, do periodic checks 16471: 1648#if defined(WITH_JIT) 1649 GET_JIT_PROF_TABLE(r0) 1650 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1651 b common_testUpdateProfile 1652#else 1653 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1654 GET_INST_OPCODE(ip) @ extract opcode from rINST 1655 GOTO_OPCODE(ip) @ jump to next instruction 1656#endif 1657 1658 1659 1660/* ------------------------------ */ 1661 .balign 64 1662.L_OP_IF_GT: /* 0x36 */ 1663/* File: armv5te/OP_IF_GT.S */ 1664/* File: armv5te/bincmp.S */ 1665 /* 1666 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1667 * fragment that specifies the *reverse* comparison to perform, e.g. 1668 * for "if-le" you would use "gt". 1669 * 1670 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1671 */ 1672 /* if-cmp vA, vB, +CCCC */ 1673 mov r0, rINST, lsr #8 @ r0<- A+ 1674 mov r1, rINST, lsr #12 @ r1<- B 1675 and r0, r0, #15 1676 GET_VREG(r3, r1) @ r3<- vB 1677 GET_VREG(r2, r0) @ r2<- vA 1678 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1679 cmp r2, r3 @ compare (vA, vB) 1680 ble 1f @ branch to 1 if comparison failed 1681 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1682 movs r9, r9, asl #1 @ convert to bytes, check sign 1683 bmi common_backwardBranch @ yes, do periodic checks 16841: 1685#if defined(WITH_JIT) 1686 GET_JIT_PROF_TABLE(r0) 1687 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1688 b common_testUpdateProfile 1689#else 1690 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1691 GET_INST_OPCODE(ip) @ extract opcode from rINST 1692 GOTO_OPCODE(ip) @ jump to next instruction 1693#endif 1694 1695 1696 1697/* ------------------------------ */ 1698 .balign 64 1699.L_OP_IF_LE: /* 0x37 */ 1700/* File: armv5te/OP_IF_LE.S */ 1701/* File: armv5te/bincmp.S */ 1702 /* 1703 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1704 * fragment that specifies the *reverse* comparison to perform, e.g. 1705 * for "if-le" you would use "gt". 1706 * 1707 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1708 */ 1709 /* if-cmp vA, vB, +CCCC */ 1710 mov r0, rINST, lsr #8 @ r0<- A+ 1711 mov r1, rINST, lsr #12 @ r1<- B 1712 and r0, r0, #15 1713 GET_VREG(r3, r1) @ r3<- vB 1714 GET_VREG(r2, r0) @ r2<- vA 1715 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1716 cmp r2, r3 @ compare (vA, vB) 1717 bgt 1f @ branch to 1 if comparison failed 1718 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1719 movs r9, r9, asl #1 @ convert to bytes, check sign 1720 bmi common_backwardBranch @ yes, do periodic checks 17211: 1722#if defined(WITH_JIT) 1723 GET_JIT_PROF_TABLE(r0) 1724 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1725 b common_testUpdateProfile 1726#else 1727 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1728 GET_INST_OPCODE(ip) @ extract opcode from rINST 1729 GOTO_OPCODE(ip) @ jump to next instruction 1730#endif 1731 1732 1733 1734/* ------------------------------ */ 1735 .balign 64 1736.L_OP_IF_EQZ: /* 0x38 */ 1737/* File: armv5te/OP_IF_EQZ.S */ 1738/* File: armv5te/zcmp.S */ 1739 /* 1740 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1741 * fragment that specifies the *reverse* comparison to perform, e.g. 1742 * for "if-le" you would use "gt". 1743 * 1744 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1745 */ 1746 /* if-cmp vAA, +BBBB */ 1747 mov r0, rINST, lsr #8 @ r0<- AA 1748 GET_VREG(r2, r0) @ r2<- vAA 1749 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1750 cmp r2, #0 @ compare (vA, 0) 1751 bne 1f @ branch to 1 if comparison failed 1752 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1753 movs r9, r9, asl #1 @ convert to bytes, check sign 1754 bmi common_backwardBranch @ backward branch, do periodic checks 17551: 1756#if defined(WITH_JIT) 1757 GET_JIT_PROF_TABLE(r0) 1758 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1759 cmp r0,#0 1760 bne common_updateProfile 1761 GET_INST_OPCODE(ip) @ extract opcode from rINST 1762 GOTO_OPCODE(ip) @ jump to next instruction 1763#else 1764 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1765 GET_INST_OPCODE(ip) @ extract opcode from rINST 1766 GOTO_OPCODE(ip) @ jump to next instruction 1767#endif 1768 1769 1770 1771/* ------------------------------ */ 1772 .balign 64 1773.L_OP_IF_NEZ: /* 0x39 */ 1774/* File: armv5te/OP_IF_NEZ.S */ 1775/* File: armv5te/zcmp.S */ 1776 /* 1777 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1778 * fragment that specifies the *reverse* comparison to perform, e.g. 1779 * for "if-le" you would use "gt". 1780 * 1781 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1782 */ 1783 /* if-cmp vAA, +BBBB */ 1784 mov r0, rINST, lsr #8 @ r0<- AA 1785 GET_VREG(r2, r0) @ r2<- vAA 1786 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1787 cmp r2, #0 @ compare (vA, 0) 1788 beq 1f @ branch to 1 if comparison failed 1789 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1790 movs r9, r9, asl #1 @ convert to bytes, check sign 1791 bmi common_backwardBranch @ backward branch, do periodic checks 17921: 1793#if defined(WITH_JIT) 1794 GET_JIT_PROF_TABLE(r0) 1795 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1796 cmp r0,#0 1797 bne common_updateProfile 1798 GET_INST_OPCODE(ip) @ extract opcode from rINST 1799 GOTO_OPCODE(ip) @ jump to next instruction 1800#else 1801 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1802 GET_INST_OPCODE(ip) @ extract opcode from rINST 1803 GOTO_OPCODE(ip) @ jump to next instruction 1804#endif 1805 1806 1807 1808/* ------------------------------ */ 1809 .balign 64 1810.L_OP_IF_LTZ: /* 0x3a */ 1811/* File: armv5te/OP_IF_LTZ.S */ 1812/* File: armv5te/zcmp.S */ 1813 /* 1814 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1815 * fragment that specifies the *reverse* comparison to perform, e.g. 1816 * for "if-le" you would use "gt". 1817 * 1818 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1819 */ 1820 /* if-cmp vAA, +BBBB */ 1821 mov r0, rINST, lsr #8 @ r0<- AA 1822 GET_VREG(r2, r0) @ r2<- vAA 1823 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1824 cmp r2, #0 @ compare (vA, 0) 1825 bge 1f @ branch to 1 if comparison failed 1826 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1827 movs r9, r9, asl #1 @ convert to bytes, check sign 1828 bmi common_backwardBranch @ backward branch, do periodic checks 18291: 1830#if defined(WITH_JIT) 1831 GET_JIT_PROF_TABLE(r0) 1832 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1833 cmp r0,#0 1834 bne common_updateProfile 1835 GET_INST_OPCODE(ip) @ extract opcode from rINST 1836 GOTO_OPCODE(ip) @ jump to next instruction 1837#else 1838 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1839 GET_INST_OPCODE(ip) @ extract opcode from rINST 1840 GOTO_OPCODE(ip) @ jump to next instruction 1841#endif 1842 1843 1844 1845/* ------------------------------ */ 1846 .balign 64 1847.L_OP_IF_GEZ: /* 0x3b */ 1848/* File: armv5te/OP_IF_GEZ.S */ 1849/* File: armv5te/zcmp.S */ 1850 /* 1851 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1852 * fragment that specifies the *reverse* comparison to perform, e.g. 1853 * for "if-le" you would use "gt". 1854 * 1855 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1856 */ 1857 /* if-cmp vAA, +BBBB */ 1858 mov r0, rINST, lsr #8 @ r0<- AA 1859 GET_VREG(r2, r0) @ r2<- vAA 1860 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1861 cmp r2, #0 @ compare (vA, 0) 1862 blt 1f @ branch to 1 if comparison failed 1863 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1864 movs r9, r9, asl #1 @ convert to bytes, check sign 1865 bmi common_backwardBranch @ backward branch, do periodic checks 18661: 1867#if defined(WITH_JIT) 1868 GET_JIT_PROF_TABLE(r0) 1869 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1870 cmp r0,#0 1871 bne common_updateProfile 1872 GET_INST_OPCODE(ip) @ extract opcode from rINST 1873 GOTO_OPCODE(ip) @ jump to next instruction 1874#else 1875 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1876 GET_INST_OPCODE(ip) @ extract opcode from rINST 1877 GOTO_OPCODE(ip) @ jump to next instruction 1878#endif 1879 1880 1881 1882/* ------------------------------ */ 1883 .balign 64 1884.L_OP_IF_GTZ: /* 0x3c */ 1885/* File: armv5te/OP_IF_GTZ.S */ 1886/* File: armv5te/zcmp.S */ 1887 /* 1888 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1889 * fragment that specifies the *reverse* comparison to perform, e.g. 1890 * for "if-le" you would use "gt". 1891 * 1892 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1893 */ 1894 /* if-cmp vAA, +BBBB */ 1895 mov r0, rINST, lsr #8 @ r0<- AA 1896 GET_VREG(r2, r0) @ r2<- vAA 1897 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1898 cmp r2, #0 @ compare (vA, 0) 1899 ble 1f @ branch to 1 if comparison failed 1900 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1901 movs r9, r9, asl #1 @ convert to bytes, check sign 1902 bmi common_backwardBranch @ backward branch, do periodic checks 19031: 1904#if defined(WITH_JIT) 1905 GET_JIT_PROF_TABLE(r0) 1906 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1907 cmp r0,#0 1908 bne common_updateProfile 1909 GET_INST_OPCODE(ip) @ extract opcode from rINST 1910 GOTO_OPCODE(ip) @ jump to next instruction 1911#else 1912 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1913 GET_INST_OPCODE(ip) @ extract opcode from rINST 1914 GOTO_OPCODE(ip) @ jump to next instruction 1915#endif 1916 1917 1918 1919/* ------------------------------ */ 1920 .balign 64 1921.L_OP_IF_LEZ: /* 0x3d */ 1922/* File: armv5te/OP_IF_LEZ.S */ 1923/* File: armv5te/zcmp.S */ 1924 /* 1925 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1926 * fragment that specifies the *reverse* comparison to perform, e.g. 1927 * for "if-le" you would use "gt". 1928 * 1929 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1930 */ 1931 /* if-cmp vAA, +BBBB */ 1932 mov r0, rINST, lsr #8 @ r0<- AA 1933 GET_VREG(r2, r0) @ r2<- vAA 1934 mov r9, #4 @ r0<- BYTE branch dist for not-taken 1935 cmp r2, #0 @ compare (vA, 0) 1936 bgt 1f @ branch to 1 if comparison failed 1937 FETCH_S(r9, 1) @ r9<- branch offset, in code units 1938 movs r9, r9, asl #1 @ convert to bytes, check sign 1939 bmi common_backwardBranch @ backward branch, do periodic checks 19401: 1941#if defined(WITH_JIT) 1942 GET_JIT_PROF_TABLE(r0) 1943 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1944 cmp r0,#0 1945 bne common_updateProfile 1946 GET_INST_OPCODE(ip) @ extract opcode from rINST 1947 GOTO_OPCODE(ip) @ jump to next instruction 1948#else 1949 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 1950 GET_INST_OPCODE(ip) @ extract opcode from rINST 1951 GOTO_OPCODE(ip) @ jump to next instruction 1952#endif 1953 1954 1955 1956/* ------------------------------ */ 1957 .balign 64 1958.L_OP_UNUSED_3E: /* 0x3e */ 1959/* File: armv5te/OP_UNUSED_3E.S */ 1960/* File: armv5te/unused.S */ 1961 bl common_abort 1962 1963 1964 1965/* ------------------------------ */ 1966 .balign 64 1967.L_OP_UNUSED_3F: /* 0x3f */ 1968/* File: armv5te/OP_UNUSED_3F.S */ 1969/* File: armv5te/unused.S */ 1970 bl common_abort 1971 1972 1973 1974/* ------------------------------ */ 1975 .balign 64 1976.L_OP_UNUSED_40: /* 0x40 */ 1977/* File: armv5te/OP_UNUSED_40.S */ 1978/* File: armv5te/unused.S */ 1979 bl common_abort 1980 1981 1982 1983/* ------------------------------ */ 1984 .balign 64 1985.L_OP_UNUSED_41: /* 0x41 */ 1986/* File: armv5te/OP_UNUSED_41.S */ 1987/* File: armv5te/unused.S */ 1988 bl common_abort 1989 1990 1991 1992/* ------------------------------ */ 1993 .balign 64 1994.L_OP_UNUSED_42: /* 0x42 */ 1995/* File: armv5te/OP_UNUSED_42.S */ 1996/* File: armv5te/unused.S */ 1997 bl common_abort 1998 1999 2000 2001/* ------------------------------ */ 2002 .balign 64 2003.L_OP_UNUSED_43: /* 0x43 */ 2004/* File: armv5te/OP_UNUSED_43.S */ 2005/* File: armv5te/unused.S */ 2006 bl common_abort 2007 2008 2009 2010/* ------------------------------ */ 2011 .balign 64 2012.L_OP_AGET: /* 0x44 */ 2013/* File: armv5te/OP_AGET.S */ 2014 /* 2015 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2016 * 2017 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2018 * instructions. We use a pair of FETCH_Bs instead. 2019 * 2020 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2021 */ 2022 /* op vAA, vBB, vCC */ 2023 FETCH_B(r2, 1, 0) @ r2<- BB 2024 mov r9, rINST, lsr #8 @ r9<- AA 2025 FETCH_B(r3, 1, 1) @ r3<- CC 2026 GET_VREG(r0, r2) @ r0<- vBB (array object) 2027 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2028 cmp r0, #0 @ null array object? 2029 beq common_errNullObject @ yes, bail 2030 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2031 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2032 cmp r1, r3 @ compare unsigned index, length 2033 bcs common_errArrayIndex @ index >= length, bail 2034 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2035 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2036 GET_INST_OPCODE(ip) @ extract opcode from rINST 2037 SET_VREG(r2, r9) @ vAA<- r2 2038 GOTO_OPCODE(ip) @ jump to next instruction 2039 2040 2041/* ------------------------------ */ 2042 .balign 64 2043.L_OP_AGET_WIDE: /* 0x45 */ 2044/* File: armv5te/OP_AGET_WIDE.S */ 2045 /* 2046 * Array get, 64 bits. vAA <- vBB[vCC]. 2047 * 2048 * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD. 2049 */ 2050 /* aget-wide vAA, vBB, vCC */ 2051 FETCH(r0, 1) @ r0<- CCBB 2052 mov r9, rINST, lsr #8 @ r9<- AA 2053 and r2, r0, #255 @ r2<- BB 2054 mov r3, r0, lsr #8 @ r3<- CC 2055 GET_VREG(r0, r2) @ r0<- vBB (array object) 2056 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2057 cmp r0, #0 @ null array object? 2058 beq common_errNullObject @ yes, bail 2059 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2060 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2061 cmp r1, r3 @ compare unsigned index, length 2062 bcc .LOP_AGET_WIDE_finish @ okay, continue below 2063 b common_errArrayIndex @ index >= length, bail 2064 @ May want to swap the order of these two branches depending on how the 2065 @ branch prediction (if any) handles conditional forward branches vs. 2066 @ unconditional forward branches. 2067 2068/* ------------------------------ */ 2069 .balign 64 2070.L_OP_AGET_OBJECT: /* 0x46 */ 2071/* File: armv5te/OP_AGET_OBJECT.S */ 2072/* File: armv5te/OP_AGET.S */ 2073 /* 2074 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2075 * 2076 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2077 * instructions. We use a pair of FETCH_Bs instead. 2078 * 2079 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2080 */ 2081 /* op vAA, vBB, vCC */ 2082 FETCH_B(r2, 1, 0) @ r2<- BB 2083 mov r9, rINST, lsr #8 @ r9<- AA 2084 FETCH_B(r3, 1, 1) @ r3<- CC 2085 GET_VREG(r0, r2) @ r0<- vBB (array object) 2086 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2087 cmp r0, #0 @ null array object? 2088 beq common_errNullObject @ yes, bail 2089 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2090 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2091 cmp r1, r3 @ compare unsigned index, length 2092 bcs common_errArrayIndex @ index >= length, bail 2093 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2094 ldr r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2095 GET_INST_OPCODE(ip) @ extract opcode from rINST 2096 SET_VREG(r2, r9) @ vAA<- r2 2097 GOTO_OPCODE(ip) @ jump to next instruction 2098 2099 2100 2101/* ------------------------------ */ 2102 .balign 64 2103.L_OP_AGET_BOOLEAN: /* 0x47 */ 2104/* File: armv5te/OP_AGET_BOOLEAN.S */ 2105/* File: armv5te/OP_AGET.S */ 2106 /* 2107 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2108 * 2109 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2110 * instructions. We use a pair of FETCH_Bs instead. 2111 * 2112 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2113 */ 2114 /* op vAA, vBB, vCC */ 2115 FETCH_B(r2, 1, 0) @ r2<- BB 2116 mov r9, rINST, lsr #8 @ r9<- AA 2117 FETCH_B(r3, 1, 1) @ r3<- CC 2118 GET_VREG(r0, r2) @ r0<- vBB (array object) 2119 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2120 cmp r0, #0 @ null array object? 2121 beq common_errNullObject @ yes, bail 2122 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2123 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2124 cmp r1, r3 @ compare unsigned index, length 2125 bcs common_errArrayIndex @ index >= length, bail 2126 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2127 ldrb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2128 GET_INST_OPCODE(ip) @ extract opcode from rINST 2129 SET_VREG(r2, r9) @ vAA<- r2 2130 GOTO_OPCODE(ip) @ jump to next instruction 2131 2132 2133 2134/* ------------------------------ */ 2135 .balign 64 2136.L_OP_AGET_BYTE: /* 0x48 */ 2137/* File: armv5te/OP_AGET_BYTE.S */ 2138/* File: armv5te/OP_AGET.S */ 2139 /* 2140 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2141 * 2142 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2143 * instructions. We use a pair of FETCH_Bs instead. 2144 * 2145 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2146 */ 2147 /* op vAA, vBB, vCC */ 2148 FETCH_B(r2, 1, 0) @ r2<- BB 2149 mov r9, rINST, lsr #8 @ r9<- AA 2150 FETCH_B(r3, 1, 1) @ r3<- CC 2151 GET_VREG(r0, r2) @ r0<- vBB (array object) 2152 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2153 cmp r0, #0 @ null array object? 2154 beq common_errNullObject @ yes, bail 2155 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2156 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2157 cmp r1, r3 @ compare unsigned index, length 2158 bcs common_errArrayIndex @ index >= length, bail 2159 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2160 ldrsb r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2161 GET_INST_OPCODE(ip) @ extract opcode from rINST 2162 SET_VREG(r2, r9) @ vAA<- r2 2163 GOTO_OPCODE(ip) @ jump to next instruction 2164 2165 2166 2167/* ------------------------------ */ 2168 .balign 64 2169.L_OP_AGET_CHAR: /* 0x49 */ 2170/* File: armv5te/OP_AGET_CHAR.S */ 2171/* File: armv5te/OP_AGET.S */ 2172 /* 2173 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2174 * 2175 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2176 * instructions. We use a pair of FETCH_Bs instead. 2177 * 2178 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2179 */ 2180 /* op vAA, vBB, vCC */ 2181 FETCH_B(r2, 1, 0) @ r2<- BB 2182 mov r9, rINST, lsr #8 @ r9<- AA 2183 FETCH_B(r3, 1, 1) @ r3<- CC 2184 GET_VREG(r0, r2) @ r0<- vBB (array object) 2185 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2186 cmp r0, #0 @ null array object? 2187 beq common_errNullObject @ yes, bail 2188 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2189 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2190 cmp r1, r3 @ compare unsigned index, length 2191 bcs common_errArrayIndex @ index >= length, bail 2192 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2193 ldrh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2194 GET_INST_OPCODE(ip) @ extract opcode from rINST 2195 SET_VREG(r2, r9) @ vAA<- r2 2196 GOTO_OPCODE(ip) @ jump to next instruction 2197 2198 2199 2200/* ------------------------------ */ 2201 .balign 64 2202.L_OP_AGET_SHORT: /* 0x4a */ 2203/* File: armv5te/OP_AGET_SHORT.S */ 2204/* File: armv5te/OP_AGET.S */ 2205 /* 2206 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2207 * 2208 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2209 * instructions. We use a pair of FETCH_Bs instead. 2210 * 2211 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2212 */ 2213 /* op vAA, vBB, vCC */ 2214 FETCH_B(r2, 1, 0) @ r2<- BB 2215 mov r9, rINST, lsr #8 @ r9<- AA 2216 FETCH_B(r3, 1, 1) @ r3<- CC 2217 GET_VREG(r0, r2) @ r0<- vBB (array object) 2218 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2219 cmp r0, #0 @ null array object? 2220 beq common_errNullObject @ yes, bail 2221 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2222 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2223 cmp r1, r3 @ compare unsigned index, length 2224 bcs common_errArrayIndex @ index >= length, bail 2225 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2226 ldrsh r2, [r0, #offArrayObject_contents] @ r2<- vBB[vCC] 2227 GET_INST_OPCODE(ip) @ extract opcode from rINST 2228 SET_VREG(r2, r9) @ vAA<- r2 2229 GOTO_OPCODE(ip) @ jump to next instruction 2230 2231 2232 2233/* ------------------------------ */ 2234 .balign 64 2235.L_OP_APUT: /* 0x4b */ 2236/* File: armv5te/OP_APUT.S */ 2237 /* 2238 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2239 * 2240 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2241 * instructions. We use a pair of FETCH_Bs instead. 2242 * 2243 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2244 */ 2245 /* op vAA, vBB, vCC */ 2246 FETCH_B(r2, 1, 0) @ r2<- BB 2247 mov r9, rINST, lsr #8 @ r9<- AA 2248 FETCH_B(r3, 1, 1) @ r3<- CC 2249 GET_VREG(r0, r2) @ r0<- vBB (array object) 2250 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2251 cmp r0, #0 @ null array object? 2252 beq common_errNullObject @ yes, bail 2253 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2254 add r0, r0, r1, lsl #2 @ r0<- arrayObj + index*width 2255 cmp r1, r3 @ compare unsigned index, length 2256 bcs common_errArrayIndex @ index >= length, bail 2257 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2258 GET_VREG(r2, r9) @ r2<- vAA 2259 GET_INST_OPCODE(ip) @ extract opcode from rINST 2260 str r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2261 GOTO_OPCODE(ip) @ jump to next instruction 2262 2263 2264/* ------------------------------ */ 2265 .balign 64 2266.L_OP_APUT_WIDE: /* 0x4c */ 2267/* File: armv5te/OP_APUT_WIDE.S */ 2268 /* 2269 * Array put, 64 bits. vBB[vCC] <- vAA. 2270 * 2271 * Arrays of long/double are 64-bit aligned, so it's okay to use STRD. 2272 */ 2273 /* aput-wide vAA, vBB, vCC */ 2274 FETCH(r0, 1) @ r0<- CCBB 2275 mov r9, rINST, lsr #8 @ r9<- AA 2276 and r2, r0, #255 @ r2<- BB 2277 mov r3, r0, lsr #8 @ r3<- CC 2278 GET_VREG(r0, r2) @ r0<- vBB (array object) 2279 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2280 cmp r0, #0 @ null array object? 2281 beq common_errNullObject @ yes, bail 2282 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2283 add r0, r0, r1, lsl #3 @ r0<- arrayObj + index*width 2284 cmp r1, r3 @ compare unsigned index, length 2285 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2286 bcc .LOP_APUT_WIDE_finish @ okay, continue below 2287 b common_errArrayIndex @ index >= length, bail 2288 @ May want to swap the order of these two branches depending on how the 2289 @ branch prediction (if any) handles conditional forward branches vs. 2290 @ unconditional forward branches. 2291 2292/* ------------------------------ */ 2293 .balign 64 2294.L_OP_APUT_OBJECT: /* 0x4d */ 2295/* File: armv5te/OP_APUT_OBJECT.S */ 2296 /* 2297 * Store an object into an array. vBB[vCC] <- vAA. 2298 * 2299 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2300 * instructions. We use a pair of FETCH_Bs instead. 2301 */ 2302 /* op vAA, vBB, vCC */ 2303 FETCH(r0, 1) @ r0<- CCBB 2304 mov r9, rINST, lsr #8 @ r9<- AA 2305 and r2, r0, #255 @ r2<- BB 2306 mov r3, r0, lsr #8 @ r3<- CC 2307 GET_VREG(r1, r2) @ r1<- vBB (array object) 2308 GET_VREG(r0, r3) @ r0<- vCC (requested index) 2309 cmp r1, #0 @ null array object? 2310 GET_VREG(r9, r9) @ r9<- vAA 2311 beq common_errNullObject @ yes, bail 2312 ldr r3, [r1, #offArrayObject_length] @ r3<- arrayObj->length 2313 add r10, r1, r0, lsl #2 @ r10<- arrayObj + index*width 2314 cmp r0, r3 @ compare unsigned index, length 2315 bcc .LOP_APUT_OBJECT_finish @ we're okay, continue on 2316 b common_errArrayIndex @ index >= length, bail 2317 2318 2319/* ------------------------------ */ 2320 .balign 64 2321.L_OP_APUT_BOOLEAN: /* 0x4e */ 2322/* File: armv5te/OP_APUT_BOOLEAN.S */ 2323/* File: armv5te/OP_APUT.S */ 2324 /* 2325 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2326 * 2327 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2328 * instructions. We use a pair of FETCH_Bs instead. 2329 * 2330 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2331 */ 2332 /* op vAA, vBB, vCC */ 2333 FETCH_B(r2, 1, 0) @ r2<- BB 2334 mov r9, rINST, lsr #8 @ r9<- AA 2335 FETCH_B(r3, 1, 1) @ r3<- CC 2336 GET_VREG(r0, r2) @ r0<- vBB (array object) 2337 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2338 cmp r0, #0 @ null array object? 2339 beq common_errNullObject @ yes, bail 2340 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2341 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2342 cmp r1, r3 @ compare unsigned index, length 2343 bcs common_errArrayIndex @ index >= length, bail 2344 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2345 GET_VREG(r2, r9) @ r2<- vAA 2346 GET_INST_OPCODE(ip) @ extract opcode from rINST 2347 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2348 GOTO_OPCODE(ip) @ jump to next instruction 2349 2350 2351 2352/* ------------------------------ */ 2353 .balign 64 2354.L_OP_APUT_BYTE: /* 0x4f */ 2355/* File: armv5te/OP_APUT_BYTE.S */ 2356/* File: armv5te/OP_APUT.S */ 2357 /* 2358 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2359 * 2360 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2361 * instructions. We use a pair of FETCH_Bs instead. 2362 * 2363 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2364 */ 2365 /* op vAA, vBB, vCC */ 2366 FETCH_B(r2, 1, 0) @ r2<- BB 2367 mov r9, rINST, lsr #8 @ r9<- AA 2368 FETCH_B(r3, 1, 1) @ r3<- CC 2369 GET_VREG(r0, r2) @ r0<- vBB (array object) 2370 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2371 cmp r0, #0 @ null array object? 2372 beq common_errNullObject @ yes, bail 2373 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2374 add r0, r0, r1, lsl #0 @ r0<- arrayObj + index*width 2375 cmp r1, r3 @ compare unsigned index, length 2376 bcs common_errArrayIndex @ index >= length, bail 2377 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2378 GET_VREG(r2, r9) @ r2<- vAA 2379 GET_INST_OPCODE(ip) @ extract opcode from rINST 2380 strb r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2381 GOTO_OPCODE(ip) @ jump to next instruction 2382 2383 2384 2385/* ------------------------------ */ 2386 .balign 64 2387.L_OP_APUT_CHAR: /* 0x50 */ 2388/* File: armv5te/OP_APUT_CHAR.S */ 2389/* File: armv5te/OP_APUT.S */ 2390 /* 2391 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2392 * 2393 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2394 * instructions. We use a pair of FETCH_Bs instead. 2395 * 2396 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2397 */ 2398 /* op vAA, vBB, vCC */ 2399 FETCH_B(r2, 1, 0) @ r2<- BB 2400 mov r9, rINST, lsr #8 @ r9<- AA 2401 FETCH_B(r3, 1, 1) @ r3<- CC 2402 GET_VREG(r0, r2) @ r0<- vBB (array object) 2403 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2404 cmp r0, #0 @ null array object? 2405 beq common_errNullObject @ yes, bail 2406 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2407 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2408 cmp r1, r3 @ compare unsigned index, length 2409 bcs common_errArrayIndex @ index >= length, bail 2410 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2411 GET_VREG(r2, r9) @ r2<- vAA 2412 GET_INST_OPCODE(ip) @ extract opcode from rINST 2413 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2414 GOTO_OPCODE(ip) @ jump to next instruction 2415 2416 2417 2418/* ------------------------------ */ 2419 .balign 64 2420.L_OP_APUT_SHORT: /* 0x51 */ 2421/* File: armv5te/OP_APUT_SHORT.S */ 2422/* File: armv5te/OP_APUT.S */ 2423 /* 2424 * Array put, 32 bits or less. vBB[vCC] <- vAA. 2425 * 2426 * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17 2427 * instructions. We use a pair of FETCH_Bs instead. 2428 * 2429 * for: aput, aput-boolean, aput-byte, aput-char, aput-short 2430 */ 2431 /* op vAA, vBB, vCC */ 2432 FETCH_B(r2, 1, 0) @ r2<- BB 2433 mov r9, rINST, lsr #8 @ r9<- AA 2434 FETCH_B(r3, 1, 1) @ r3<- CC 2435 GET_VREG(r0, r2) @ r0<- vBB (array object) 2436 GET_VREG(r1, r3) @ r1<- vCC (requested index) 2437 cmp r0, #0 @ null array object? 2438 beq common_errNullObject @ yes, bail 2439 ldr r3, [r0, #offArrayObject_length] @ r3<- arrayObj->length 2440 add r0, r0, r1, lsl #1 @ r0<- arrayObj + index*width 2441 cmp r1, r3 @ compare unsigned index, length 2442 bcs common_errArrayIndex @ index >= length, bail 2443 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2444 GET_VREG(r2, r9) @ r2<- vAA 2445 GET_INST_OPCODE(ip) @ extract opcode from rINST 2446 strh r2, [r0, #offArrayObject_contents] @ vBB[vCC]<- r2 2447 GOTO_OPCODE(ip) @ jump to next instruction 2448 2449 2450 2451/* ------------------------------ */ 2452 .balign 64 2453.L_OP_IGET: /* 0x52 */ 2454/* File: armv5te/OP_IGET.S */ 2455 /* 2456 * General 32-bit instance field get. 2457 * 2458 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2459 */ 2460 /* op vA, vB, field@CCCC */ 2461 mov r0, rINST, lsr #12 @ r0<- B 2462 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2463 FETCH(r1, 1) @ r1<- field ref CCCC 2464 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2465 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2466 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2467 cmp r0, #0 @ is resolved entry null? 2468 bne .LOP_IGET_finish @ no, already resolved 24698: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2470 EXPORT_PC() @ resolve() could throw 2471 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2472 bl dvmResolveInstField @ r0<- resolved InstField ptr 2473 cmp r0, #0 2474 bne .LOP_IGET_finish 2475 b common_exceptionThrown 2476 2477/* ------------------------------ */ 2478 .balign 64 2479.L_OP_IGET_WIDE: /* 0x53 */ 2480/* File: armv5te/OP_IGET_WIDE.S */ 2481 /* 2482 * Wide 32-bit instance field get. 2483 */ 2484 /* iget-wide vA, vB, field@CCCC */ 2485 mov r0, rINST, lsr #12 @ r0<- B 2486 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2487 FETCH(r1, 1) @ r1<- field ref CCCC 2488 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2489 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2490 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2491 cmp r0, #0 @ is resolved entry null? 2492 bne .LOP_IGET_WIDE_finish @ no, already resolved 24938: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2494 EXPORT_PC() @ resolve() could throw 2495 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2496 bl dvmResolveInstField @ r0<- resolved InstField ptr 2497 cmp r0, #0 2498 bne .LOP_IGET_WIDE_finish 2499 b common_exceptionThrown 2500 2501/* ------------------------------ */ 2502 .balign 64 2503.L_OP_IGET_OBJECT: /* 0x54 */ 2504/* File: armv5te/OP_IGET_OBJECT.S */ 2505/* File: armv5te/OP_IGET.S */ 2506 /* 2507 * General 32-bit instance field get. 2508 * 2509 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2510 */ 2511 /* op vA, vB, field@CCCC */ 2512 mov r0, rINST, lsr #12 @ r0<- B 2513 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2514 FETCH(r1, 1) @ r1<- field ref CCCC 2515 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2516 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2517 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2518 cmp r0, #0 @ is resolved entry null? 2519 bne .LOP_IGET_OBJECT_finish @ no, already resolved 25208: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2521 EXPORT_PC() @ resolve() could throw 2522 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2523 bl dvmResolveInstField @ r0<- resolved InstField ptr 2524 cmp r0, #0 2525 bne .LOP_IGET_OBJECT_finish 2526 b common_exceptionThrown 2527 2528 2529/* ------------------------------ */ 2530 .balign 64 2531.L_OP_IGET_BOOLEAN: /* 0x55 */ 2532/* File: armv5te/OP_IGET_BOOLEAN.S */ 2533@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" } 2534/* File: armv5te/OP_IGET.S */ 2535 /* 2536 * General 32-bit instance field get. 2537 * 2538 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2539 */ 2540 /* op vA, vB, field@CCCC */ 2541 mov r0, rINST, lsr #12 @ r0<- B 2542 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2543 FETCH(r1, 1) @ r1<- field ref CCCC 2544 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2545 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2546 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2547 cmp r0, #0 @ is resolved entry null? 2548 bne .LOP_IGET_BOOLEAN_finish @ no, already resolved 25498: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2550 EXPORT_PC() @ resolve() could throw 2551 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2552 bl dvmResolveInstField @ r0<- resolved InstField ptr 2553 cmp r0, #0 2554 bne .LOP_IGET_BOOLEAN_finish 2555 b common_exceptionThrown 2556 2557 2558/* ------------------------------ */ 2559 .balign 64 2560.L_OP_IGET_BYTE: /* 0x56 */ 2561/* File: armv5te/OP_IGET_BYTE.S */ 2562@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" } 2563/* File: armv5te/OP_IGET.S */ 2564 /* 2565 * General 32-bit instance field get. 2566 * 2567 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2568 */ 2569 /* op vA, vB, field@CCCC */ 2570 mov r0, rINST, lsr #12 @ r0<- B 2571 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2572 FETCH(r1, 1) @ r1<- field ref CCCC 2573 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2574 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2575 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2576 cmp r0, #0 @ is resolved entry null? 2577 bne .LOP_IGET_BYTE_finish @ no, already resolved 25788: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2579 EXPORT_PC() @ resolve() could throw 2580 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2581 bl dvmResolveInstField @ r0<- resolved InstField ptr 2582 cmp r0, #0 2583 bne .LOP_IGET_BYTE_finish 2584 b common_exceptionThrown 2585 2586 2587/* ------------------------------ */ 2588 .balign 64 2589.L_OP_IGET_CHAR: /* 0x57 */ 2590/* File: armv5te/OP_IGET_CHAR.S */ 2591@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" } 2592/* File: armv5te/OP_IGET.S */ 2593 /* 2594 * General 32-bit instance field get. 2595 * 2596 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2597 */ 2598 /* op vA, vB, field@CCCC */ 2599 mov r0, rINST, lsr #12 @ r0<- B 2600 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2601 FETCH(r1, 1) @ r1<- field ref CCCC 2602 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2603 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2604 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2605 cmp r0, #0 @ is resolved entry null? 2606 bne .LOP_IGET_CHAR_finish @ no, already resolved 26078: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2608 EXPORT_PC() @ resolve() could throw 2609 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2610 bl dvmResolveInstField @ r0<- resolved InstField ptr 2611 cmp r0, #0 2612 bne .LOP_IGET_CHAR_finish 2613 b common_exceptionThrown 2614 2615 2616/* ------------------------------ */ 2617 .balign 64 2618.L_OP_IGET_SHORT: /* 0x58 */ 2619/* File: armv5te/OP_IGET_SHORT.S */ 2620@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" } 2621/* File: armv5te/OP_IGET.S */ 2622 /* 2623 * General 32-bit instance field get. 2624 * 2625 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2626 */ 2627 /* op vA, vB, field@CCCC */ 2628 mov r0, rINST, lsr #12 @ r0<- B 2629 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2630 FETCH(r1, 1) @ r1<- field ref CCCC 2631 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2632 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2633 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2634 cmp r0, #0 @ is resolved entry null? 2635 bne .LOP_IGET_SHORT_finish @ no, already resolved 26368: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2637 EXPORT_PC() @ resolve() could throw 2638 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2639 bl dvmResolveInstField @ r0<- resolved InstField ptr 2640 cmp r0, #0 2641 bne .LOP_IGET_SHORT_finish 2642 b common_exceptionThrown 2643 2644 2645/* ------------------------------ */ 2646 .balign 64 2647.L_OP_IPUT: /* 0x59 */ 2648/* File: armv5te/OP_IPUT.S */ 2649 /* 2650 * General 32-bit instance field put. 2651 * 2652 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2653 */ 2654 /* op vA, vB, field@CCCC */ 2655 mov r0, rINST, lsr #12 @ r0<- B 2656 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2657 FETCH(r1, 1) @ r1<- field ref CCCC 2658 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2659 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2660 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2661 cmp r0, #0 @ is resolved entry null? 2662 bne .LOP_IPUT_finish @ no, already resolved 26638: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2664 EXPORT_PC() @ resolve() could throw 2665 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2666 bl dvmResolveInstField @ r0<- resolved InstField ptr 2667 cmp r0, #0 @ success? 2668 bne .LOP_IPUT_finish @ yes, finish up 2669 b common_exceptionThrown 2670 2671/* ------------------------------ */ 2672 .balign 64 2673.L_OP_IPUT_WIDE: /* 0x5a */ 2674/* File: armv5te/OP_IPUT_WIDE.S */ 2675 /* iput-wide vA, vB, field@CCCC */ 2676 mov r0, rINST, lsr #12 @ r0<- B 2677 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2678 FETCH(r1, 1) @ r1<- field ref CCCC 2679 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 2680 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2681 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2682 cmp r0, #0 @ is resolved entry null? 2683 bne .LOP_IPUT_WIDE_finish @ no, already resolved 26848: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2685 EXPORT_PC() @ resolve() could throw 2686 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2687 bl dvmResolveInstField @ r0<- resolved InstField ptr 2688 cmp r0, #0 @ success? 2689 bne .LOP_IPUT_WIDE_finish @ yes, finish up 2690 b common_exceptionThrown 2691 2692/* ------------------------------ */ 2693 .balign 64 2694.L_OP_IPUT_OBJECT: /* 0x5b */ 2695/* File: armv5te/OP_IPUT_OBJECT.S */ 2696/* File: armv5te/OP_IPUT.S */ 2697 /* 2698 * General 32-bit instance field put. 2699 * 2700 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2701 */ 2702 /* op vA, vB, field@CCCC */ 2703 mov r0, rINST, lsr #12 @ r0<- B 2704 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2705 FETCH(r1, 1) @ r1<- field ref CCCC 2706 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2707 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2708 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2709 cmp r0, #0 @ is resolved entry null? 2710 bne .LOP_IPUT_OBJECT_finish @ no, already resolved 27118: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2712 EXPORT_PC() @ resolve() could throw 2713 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2714 bl dvmResolveInstField @ r0<- resolved InstField ptr 2715 cmp r0, #0 @ success? 2716 bne .LOP_IPUT_OBJECT_finish @ yes, finish up 2717 b common_exceptionThrown 2718 2719 2720/* ------------------------------ */ 2721 .balign 64 2722.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2723/* File: armv5te/OP_IPUT_BOOLEAN.S */ 2724@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" } 2725/* File: armv5te/OP_IPUT.S */ 2726 /* 2727 * General 32-bit instance field put. 2728 * 2729 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2730 */ 2731 /* op vA, vB, field@CCCC */ 2732 mov r0, rINST, lsr #12 @ r0<- B 2733 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2734 FETCH(r1, 1) @ r1<- field ref CCCC 2735 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2736 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2737 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2738 cmp r0, #0 @ is resolved entry null? 2739 bne .LOP_IPUT_BOOLEAN_finish @ no, already resolved 27408: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2741 EXPORT_PC() @ resolve() could throw 2742 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2743 bl dvmResolveInstField @ r0<- resolved InstField ptr 2744 cmp r0, #0 @ success? 2745 bne .LOP_IPUT_BOOLEAN_finish @ yes, finish up 2746 b common_exceptionThrown 2747 2748 2749/* ------------------------------ */ 2750 .balign 64 2751.L_OP_IPUT_BYTE: /* 0x5d */ 2752/* File: armv5te/OP_IPUT_BYTE.S */ 2753@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" } 2754/* File: armv5te/OP_IPUT.S */ 2755 /* 2756 * General 32-bit instance field put. 2757 * 2758 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2759 */ 2760 /* op vA, vB, field@CCCC */ 2761 mov r0, rINST, lsr #12 @ r0<- B 2762 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2763 FETCH(r1, 1) @ r1<- field ref CCCC 2764 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2765 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2766 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2767 cmp r0, #0 @ is resolved entry null? 2768 bne .LOP_IPUT_BYTE_finish @ no, already resolved 27698: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2770 EXPORT_PC() @ resolve() could throw 2771 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2772 bl dvmResolveInstField @ r0<- resolved InstField ptr 2773 cmp r0, #0 @ success? 2774 bne .LOP_IPUT_BYTE_finish @ yes, finish up 2775 b common_exceptionThrown 2776 2777 2778/* ------------------------------ */ 2779 .balign 64 2780.L_OP_IPUT_CHAR: /* 0x5e */ 2781/* File: armv5te/OP_IPUT_CHAR.S */ 2782@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" } 2783/* File: armv5te/OP_IPUT.S */ 2784 /* 2785 * General 32-bit instance field put. 2786 * 2787 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2788 */ 2789 /* op vA, vB, field@CCCC */ 2790 mov r0, rINST, lsr #12 @ r0<- B 2791 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2792 FETCH(r1, 1) @ r1<- field ref CCCC 2793 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2794 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2795 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2796 cmp r0, #0 @ is resolved entry null? 2797 bne .LOP_IPUT_CHAR_finish @ no, already resolved 27988: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2799 EXPORT_PC() @ resolve() could throw 2800 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2801 bl dvmResolveInstField @ r0<- resolved InstField ptr 2802 cmp r0, #0 @ success? 2803 bne .LOP_IPUT_CHAR_finish @ yes, finish up 2804 b common_exceptionThrown 2805 2806 2807/* ------------------------------ */ 2808 .balign 64 2809.L_OP_IPUT_SHORT: /* 0x5f */ 2810/* File: armv5te/OP_IPUT_SHORT.S */ 2811@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" } 2812/* File: armv5te/OP_IPUT.S */ 2813 /* 2814 * General 32-bit instance field put. 2815 * 2816 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2817 */ 2818 /* op vA, vB, field@CCCC */ 2819 mov r0, rINST, lsr #12 @ r0<- B 2820 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 2821 FETCH(r1, 1) @ r1<- field ref CCCC 2822 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields 2823 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 2824 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 2825 cmp r0, #0 @ is resolved entry null? 2826 bne .LOP_IPUT_SHORT_finish @ no, already resolved 28278: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 2828 EXPORT_PC() @ resolve() could throw 2829 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 2830 bl dvmResolveInstField @ r0<- resolved InstField ptr 2831 cmp r0, #0 @ success? 2832 bne .LOP_IPUT_SHORT_finish @ yes, finish up 2833 b common_exceptionThrown 2834 2835 2836/* ------------------------------ */ 2837 .balign 64 2838.L_OP_SGET: /* 0x60 */ 2839/* File: armv5te/OP_SGET.S */ 2840 /* 2841 * General 32-bit SGET handler. 2842 * 2843 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2844 */ 2845 /* op vAA, field@BBBB */ 2846 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2847 FETCH(r1, 1) @ r1<- field ref BBBB 2848 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2849 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2850 cmp r0, #0 @ is resolved entry null? 2851 beq .LOP_SGET_resolve @ yes, do resolve 2852.LOP_SGET_finish: @ field ptr in r0 2853 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2854 mov r2, rINST, lsr #8 @ r2<- AA 2855 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2856 SET_VREG(r1, r2) @ fp[AA]<- r1 2857 GET_INST_OPCODE(ip) @ extract opcode from rINST 2858 GOTO_OPCODE(ip) @ jump to next instruction 2859 2860/* ------------------------------ */ 2861 .balign 64 2862.L_OP_SGET_WIDE: /* 0x61 */ 2863/* File: armv5te/OP_SGET_WIDE.S */ 2864 /* 2865 * 64-bit SGET handler. 2866 */ 2867 /* sget-wide vAA, field@BBBB */ 2868 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2869 FETCH(r1, 1) @ r1<- field ref BBBB 2870 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2871 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2872 cmp r0, #0 @ is resolved entry null? 2873 beq .LOP_SGET_WIDE_resolve @ yes, do resolve 2874.LOP_SGET_WIDE_finish: 2875 mov r9, rINST, lsr #8 @ r9<- AA 2876 .if 0 2877 add r0, r0, #offStaticField_value @ r0<- pointer to data 2878 bl android_quasiatomic_read_64 @ r0/r1<- contents of field 2879 .else 2880 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 2881 .endif 2882 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 2883 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2884 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 2885 GET_INST_OPCODE(ip) @ extract opcode from rINST 2886 GOTO_OPCODE(ip) @ jump to next instruction 2887 2888/* ------------------------------ */ 2889 .balign 64 2890.L_OP_SGET_OBJECT: /* 0x62 */ 2891/* File: armv5te/OP_SGET_OBJECT.S */ 2892/* File: armv5te/OP_SGET.S */ 2893 /* 2894 * General 32-bit SGET handler. 2895 * 2896 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2897 */ 2898 /* op vAA, field@BBBB */ 2899 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2900 FETCH(r1, 1) @ r1<- field ref BBBB 2901 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2902 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2903 cmp r0, #0 @ is resolved entry null? 2904 beq .LOP_SGET_OBJECT_resolve @ yes, do resolve 2905.LOP_SGET_OBJECT_finish: @ field ptr in r0 2906 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2907 mov r2, rINST, lsr #8 @ r2<- AA 2908 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2909 SET_VREG(r1, r2) @ fp[AA]<- r1 2910 GET_INST_OPCODE(ip) @ extract opcode from rINST 2911 GOTO_OPCODE(ip) @ jump to next instruction 2912 2913 2914/* ------------------------------ */ 2915 .balign 64 2916.L_OP_SGET_BOOLEAN: /* 0x63 */ 2917/* File: armv5te/OP_SGET_BOOLEAN.S */ 2918/* File: armv5te/OP_SGET.S */ 2919 /* 2920 * General 32-bit SGET handler. 2921 * 2922 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2923 */ 2924 /* op vAA, field@BBBB */ 2925 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2926 FETCH(r1, 1) @ r1<- field ref BBBB 2927 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2928 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2929 cmp r0, #0 @ is resolved entry null? 2930 beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve 2931.LOP_SGET_BOOLEAN_finish: @ field ptr in r0 2932 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2933 mov r2, rINST, lsr #8 @ r2<- AA 2934 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2935 SET_VREG(r1, r2) @ fp[AA]<- r1 2936 GET_INST_OPCODE(ip) @ extract opcode from rINST 2937 GOTO_OPCODE(ip) @ jump to next instruction 2938 2939 2940/* ------------------------------ */ 2941 .balign 64 2942.L_OP_SGET_BYTE: /* 0x64 */ 2943/* File: armv5te/OP_SGET_BYTE.S */ 2944/* File: armv5te/OP_SGET.S */ 2945 /* 2946 * General 32-bit SGET handler. 2947 * 2948 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2949 */ 2950 /* op vAA, field@BBBB */ 2951 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2952 FETCH(r1, 1) @ r1<- field ref BBBB 2953 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2954 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2955 cmp r0, #0 @ is resolved entry null? 2956 beq .LOP_SGET_BYTE_resolve @ yes, do resolve 2957.LOP_SGET_BYTE_finish: @ field ptr in r0 2958 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2959 mov r2, rINST, lsr #8 @ r2<- AA 2960 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2961 SET_VREG(r1, r2) @ fp[AA]<- r1 2962 GET_INST_OPCODE(ip) @ extract opcode from rINST 2963 GOTO_OPCODE(ip) @ jump to next instruction 2964 2965 2966/* ------------------------------ */ 2967 .balign 64 2968.L_OP_SGET_CHAR: /* 0x65 */ 2969/* File: armv5te/OP_SGET_CHAR.S */ 2970/* File: armv5te/OP_SGET.S */ 2971 /* 2972 * General 32-bit SGET handler. 2973 * 2974 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2975 */ 2976 /* op vAA, field@BBBB */ 2977 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 2978 FETCH(r1, 1) @ r1<- field ref BBBB 2979 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 2980 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 2981 cmp r0, #0 @ is resolved entry null? 2982 beq .LOP_SGET_CHAR_resolve @ yes, do resolve 2983.LOP_SGET_CHAR_finish: @ field ptr in r0 2984 ldr r1, [r0, #offStaticField_value] @ r1<- field value 2985 mov r2, rINST, lsr #8 @ r2<- AA 2986 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 2987 SET_VREG(r1, r2) @ fp[AA]<- r1 2988 GET_INST_OPCODE(ip) @ extract opcode from rINST 2989 GOTO_OPCODE(ip) @ jump to next instruction 2990 2991 2992/* ------------------------------ */ 2993 .balign 64 2994.L_OP_SGET_SHORT: /* 0x66 */ 2995/* File: armv5te/OP_SGET_SHORT.S */ 2996/* File: armv5te/OP_SGET.S */ 2997 /* 2998 * General 32-bit SGET handler. 2999 * 3000 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 3001 */ 3002 /* op vAA, field@BBBB */ 3003 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3004 FETCH(r1, 1) @ r1<- field ref BBBB 3005 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3006 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3007 cmp r0, #0 @ is resolved entry null? 3008 beq .LOP_SGET_SHORT_resolve @ yes, do resolve 3009.LOP_SGET_SHORT_finish: @ field ptr in r0 3010 ldr r1, [r0, #offStaticField_value] @ r1<- field value 3011 mov r2, rINST, lsr #8 @ r2<- AA 3012 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3013 SET_VREG(r1, r2) @ fp[AA]<- r1 3014 GET_INST_OPCODE(ip) @ extract opcode from rINST 3015 GOTO_OPCODE(ip) @ jump to next instruction 3016 3017 3018/* ------------------------------ */ 3019 .balign 64 3020.L_OP_SPUT: /* 0x67 */ 3021/* File: armv5te/OP_SPUT.S */ 3022 /* 3023 * General 32-bit SPUT handler. 3024 * 3025 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3026 */ 3027 /* op vAA, field@BBBB */ 3028 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3029 FETCH(r1, 1) @ r1<- field ref BBBB 3030 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3031 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3032 cmp r0, #0 @ is resolved entry null? 3033 beq .LOP_SPUT_resolve @ yes, do resolve 3034.LOP_SPUT_finish: @ field ptr in r0 3035 mov r2, rINST, lsr #8 @ r2<- AA 3036 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3037 GET_VREG(r1, r2) @ r1<- fp[AA] 3038 GET_INST_OPCODE(ip) @ extract opcode from rINST 3039 str r1, [r0, #offStaticField_value] @ field<- vAA 3040 GOTO_OPCODE(ip) @ jump to next instruction 3041 3042/* ------------------------------ */ 3043 .balign 64 3044.L_OP_SPUT_WIDE: /* 0x68 */ 3045/* File: armv5te/OP_SPUT_WIDE.S */ 3046 /* 3047 * 64-bit SPUT handler. 3048 */ 3049 /* sput-wide vAA, field@BBBB */ 3050 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 3051 FETCH(r1, 1) @ r1<- field ref BBBB 3052 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 3053 mov r9, rINST, lsr #8 @ r9<- AA 3054 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 3055 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 3056 cmp r2, #0 @ is resolved entry null? 3057 beq .LOP_SPUT_WIDE_resolve @ yes, do resolve 3058.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9 3059 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3060 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 3061 GET_INST_OPCODE(r10) @ extract opcode from rINST 3062 .if 0 3063 add r2, r2, #offStaticField_value @ r2<- pointer to data 3064 bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2 3065 .else 3066 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 3067 .endif 3068 GOTO_OPCODE(r10) @ jump to next instruction 3069 3070/* ------------------------------ */ 3071 .balign 64 3072.L_OP_SPUT_OBJECT: /* 0x69 */ 3073/* File: armv5te/OP_SPUT_OBJECT.S */ 3074/* File: armv5te/OP_SPUT.S */ 3075 /* 3076 * General 32-bit SPUT handler. 3077 * 3078 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3079 */ 3080 /* op vAA, field@BBBB */ 3081 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3082 FETCH(r1, 1) @ r1<- field ref BBBB 3083 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3084 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3085 cmp r0, #0 @ is resolved entry null? 3086 beq .LOP_SPUT_OBJECT_resolve @ yes, do resolve 3087.LOP_SPUT_OBJECT_finish: @ field ptr in r0 3088 mov r2, rINST, lsr #8 @ r2<- AA 3089 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3090 GET_VREG(r1, r2) @ r1<- fp[AA] 3091 GET_INST_OPCODE(ip) @ extract opcode from rINST 3092 str r1, [r0, #offStaticField_value] @ field<- vAA 3093 GOTO_OPCODE(ip) @ jump to next instruction 3094 3095 3096/* ------------------------------ */ 3097 .balign 64 3098.L_OP_SPUT_BOOLEAN: /* 0x6a */ 3099/* File: armv5te/OP_SPUT_BOOLEAN.S */ 3100/* File: armv5te/OP_SPUT.S */ 3101 /* 3102 * General 32-bit SPUT handler. 3103 * 3104 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3105 */ 3106 /* op vAA, field@BBBB */ 3107 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3108 FETCH(r1, 1) @ r1<- field ref BBBB 3109 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3110 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3111 cmp r0, #0 @ is resolved entry null? 3112 beq .LOP_SPUT_BOOLEAN_resolve @ yes, do resolve 3113.LOP_SPUT_BOOLEAN_finish: @ field ptr in r0 3114 mov r2, rINST, lsr #8 @ r2<- AA 3115 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3116 GET_VREG(r1, r2) @ r1<- fp[AA] 3117 GET_INST_OPCODE(ip) @ extract opcode from rINST 3118 str r1, [r0, #offStaticField_value] @ field<- vAA 3119 GOTO_OPCODE(ip) @ jump to next instruction 3120 3121 3122/* ------------------------------ */ 3123 .balign 64 3124.L_OP_SPUT_BYTE: /* 0x6b */ 3125/* File: armv5te/OP_SPUT_BYTE.S */ 3126/* File: armv5te/OP_SPUT.S */ 3127 /* 3128 * General 32-bit SPUT handler. 3129 * 3130 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3131 */ 3132 /* op vAA, field@BBBB */ 3133 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3134 FETCH(r1, 1) @ r1<- field ref BBBB 3135 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3136 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3137 cmp r0, #0 @ is resolved entry null? 3138 beq .LOP_SPUT_BYTE_resolve @ yes, do resolve 3139.LOP_SPUT_BYTE_finish: @ field ptr in r0 3140 mov r2, rINST, lsr #8 @ r2<- AA 3141 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3142 GET_VREG(r1, r2) @ r1<- fp[AA] 3143 GET_INST_OPCODE(ip) @ extract opcode from rINST 3144 str r1, [r0, #offStaticField_value] @ field<- vAA 3145 GOTO_OPCODE(ip) @ jump to next instruction 3146 3147 3148/* ------------------------------ */ 3149 .balign 64 3150.L_OP_SPUT_CHAR: /* 0x6c */ 3151/* File: armv5te/OP_SPUT_CHAR.S */ 3152/* File: armv5te/OP_SPUT.S */ 3153 /* 3154 * General 32-bit SPUT handler. 3155 * 3156 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3157 */ 3158 /* op vAA, field@BBBB */ 3159 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3160 FETCH(r1, 1) @ r1<- field ref BBBB 3161 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3162 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3163 cmp r0, #0 @ is resolved entry null? 3164 beq .LOP_SPUT_CHAR_resolve @ yes, do resolve 3165.LOP_SPUT_CHAR_finish: @ field ptr in r0 3166 mov r2, rINST, lsr #8 @ r2<- AA 3167 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3168 GET_VREG(r1, r2) @ r1<- fp[AA] 3169 GET_INST_OPCODE(ip) @ extract opcode from rINST 3170 str r1, [r0, #offStaticField_value] @ field<- vAA 3171 GOTO_OPCODE(ip) @ jump to next instruction 3172 3173 3174/* ------------------------------ */ 3175 .balign 64 3176.L_OP_SPUT_SHORT: /* 0x6d */ 3177/* File: armv5te/OP_SPUT_SHORT.S */ 3178/* File: armv5te/OP_SPUT.S */ 3179 /* 3180 * General 32-bit SPUT handler. 3181 * 3182 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 3183 */ 3184 /* op vAA, field@BBBB */ 3185 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 3186 FETCH(r1, 1) @ r1<- field ref BBBB 3187 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 3188 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 3189 cmp r0, #0 @ is resolved entry null? 3190 beq .LOP_SPUT_SHORT_resolve @ yes, do resolve 3191.LOP_SPUT_SHORT_finish: @ field ptr in r0 3192 mov r2, rINST, lsr #8 @ r2<- AA 3193 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 3194 GET_VREG(r1, r2) @ r1<- fp[AA] 3195 GET_INST_OPCODE(ip) @ extract opcode from rINST 3196 str r1, [r0, #offStaticField_value] @ field<- vAA 3197 GOTO_OPCODE(ip) @ jump to next instruction 3198 3199 3200/* ------------------------------ */ 3201 .balign 64 3202.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3203/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3204 /* 3205 * Handle a virtual method call. 3206 * 3207 * for: invoke-virtual, invoke-virtual/range 3208 */ 3209 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3210 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3211 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3212 FETCH(r1, 1) @ r1<- BBBB 3213 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3214 FETCH(r10, 2) @ r10<- GFED or CCCC 3215 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3216 .if (!0) 3217 and r10, r10, #15 @ r10<- D (or stays CCCC) 3218 .endif 3219 cmp r0, #0 @ already resolved? 3220 EXPORT_PC() @ must export for invoke 3221 bne .LOP_INVOKE_VIRTUAL_continue @ yes, continue on 3222 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3223 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3224 mov r2, #METHOD_VIRTUAL @ resolver method type 3225 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3226 cmp r0, #0 @ got null? 3227 bne .LOP_INVOKE_VIRTUAL_continue @ no, continue 3228 b common_exceptionThrown @ yes, handle exception 3229 3230/* ------------------------------ */ 3231 .balign 64 3232.L_OP_INVOKE_SUPER: /* 0x6f */ 3233/* File: armv5te/OP_INVOKE_SUPER.S */ 3234 /* 3235 * Handle a "super" method call. 3236 * 3237 * for: invoke-super, invoke-super/range 3238 */ 3239 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3240 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3241 FETCH(r10, 2) @ r10<- GFED or CCCC 3242 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3243 .if (!0) 3244 and r10, r10, #15 @ r10<- D (or stays CCCC) 3245 .endif 3246 FETCH(r1, 1) @ r1<- BBBB 3247 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3248 GET_VREG(r2, r10) @ r2<- "this" ptr 3249 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3250 cmp r2, #0 @ null "this"? 3251 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3252 beq common_errNullObject @ null "this", throw exception 3253 cmp r0, #0 @ already resolved? 3254 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3255 EXPORT_PC() @ must export for invoke 3256 bne .LOP_INVOKE_SUPER_continue @ resolved, continue on 3257 b .LOP_INVOKE_SUPER_resolve @ do resolve now 3258 3259/* ------------------------------ */ 3260 .balign 64 3261.L_OP_INVOKE_DIRECT: /* 0x70 */ 3262/* File: armv5te/OP_INVOKE_DIRECT.S */ 3263 /* 3264 * Handle a direct method call. 3265 * 3266 * (We could defer the "is 'this' pointer null" test to the common 3267 * method invocation code, and use a flag to indicate that static 3268 * calls don't count. If we do this as part of copying the arguments 3269 * out we could avoiding loading the first arg twice.) 3270 * 3271 * for: invoke-direct, invoke-direct/range 3272 */ 3273 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3274 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3275 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3276 FETCH(r1, 1) @ r1<- BBBB 3277 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3278 FETCH(r10, 2) @ r10<- GFED or CCCC 3279 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3280 .if (!0) 3281 and r10, r10, #15 @ r10<- D (or stays CCCC) 3282 .endif 3283 cmp r0, #0 @ already resolved? 3284 EXPORT_PC() @ must export for invoke 3285 GET_VREG(r2, r10) @ r2<- "this" ptr 3286 beq .LOP_INVOKE_DIRECT_resolve @ not resolved, do it now 3287.LOP_INVOKE_DIRECT_finish: 3288 cmp r2, #0 @ null "this" ref? 3289 bne common_invokeMethodNoRange @ no, continue on 3290 b common_errNullObject @ yes, throw exception 3291 3292/* ------------------------------ */ 3293 .balign 64 3294.L_OP_INVOKE_STATIC: /* 0x71 */ 3295/* File: armv5te/OP_INVOKE_STATIC.S */ 3296 /* 3297 * Handle a static method call. 3298 * 3299 * for: invoke-static, invoke-static/range 3300 */ 3301 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3302 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3303 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3304 FETCH(r1, 1) @ r1<- BBBB 3305 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3306 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3307 cmp r0, #0 @ already resolved? 3308 EXPORT_PC() @ must export for invoke 3309 bne common_invokeMethodNoRange @ yes, continue on 33100: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3311 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3312 mov r2, #METHOD_STATIC @ resolver method type 3313 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3314 cmp r0, #0 @ got null? 3315 bne common_invokeMethodNoRange @ no, continue 3316 b common_exceptionThrown @ yes, handle exception 3317 3318 3319/* ------------------------------ */ 3320 .balign 64 3321.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3322/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3323 /* 3324 * Handle an interface method call. 3325 * 3326 * for: invoke-interface, invoke-interface/range 3327 */ 3328 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3329 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3330 FETCH(r2, 2) @ r2<- FEDC or CCCC 3331 FETCH(r1, 1) @ r1<- BBBB 3332 .if (!0) 3333 and r2, r2, #15 @ r2<- C (or stays CCCC) 3334 .endif 3335 EXPORT_PC() @ must export for invoke 3336 GET_VREG(r0, r2) @ r0<- first arg ("this") 3337 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3338 cmp r0, #0 @ null obj? 3339 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3340 beq common_errNullObject @ yes, fail 3341 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3342 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3343 cmp r0, #0 @ failed? 3344 beq common_exceptionThrown @ yes, handle exception 3345 b common_invokeMethodNoRange @ jump to common handler 3346 3347 3348/* ------------------------------ */ 3349 .balign 64 3350.L_OP_UNUSED_73: /* 0x73 */ 3351/* File: armv5te/OP_UNUSED_73.S */ 3352/* File: armv5te/unused.S */ 3353 bl common_abort 3354 3355 3356 3357/* ------------------------------ */ 3358 .balign 64 3359.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3360/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */ 3361/* File: armv5te/OP_INVOKE_VIRTUAL.S */ 3362 /* 3363 * Handle a virtual method call. 3364 * 3365 * for: invoke-virtual, invoke-virtual/range 3366 */ 3367 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3368 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3369 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3370 FETCH(r1, 1) @ r1<- BBBB 3371 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3372 FETCH(r10, 2) @ r10<- GFED or CCCC 3373 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3374 .if (!1) 3375 and r10, r10, #15 @ r10<- D (or stays CCCC) 3376 .endif 3377 cmp r0, #0 @ already resolved? 3378 EXPORT_PC() @ must export for invoke 3379 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ yes, continue on 3380 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3381 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3382 mov r2, #METHOD_VIRTUAL @ resolver method type 3383 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3384 cmp r0, #0 @ got null? 3385 bne .LOP_INVOKE_VIRTUAL_RANGE_continue @ no, continue 3386 b common_exceptionThrown @ yes, handle exception 3387 3388 3389/* ------------------------------ */ 3390 .balign 64 3391.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3392/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */ 3393/* File: armv5te/OP_INVOKE_SUPER.S */ 3394 /* 3395 * Handle a "super" method call. 3396 * 3397 * for: invoke-super, invoke-super/range 3398 */ 3399 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3400 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3401 FETCH(r10, 2) @ r10<- GFED or CCCC 3402 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3403 .if (!1) 3404 and r10, r10, #15 @ r10<- D (or stays CCCC) 3405 .endif 3406 FETCH(r1, 1) @ r1<- BBBB 3407 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3408 GET_VREG(r2, r10) @ r2<- "this" ptr 3409 ldr r0, [r3, r1, lsl #2] @ r0<- resolved baseMethod 3410 cmp r2, #0 @ null "this"? 3411 ldr r9, [rGLUE, #offGlue_method] @ r9<- current method 3412 beq common_errNullObject @ null "this", throw exception 3413 cmp r0, #0 @ already resolved? 3414 ldr r9, [r9, #offMethod_clazz] @ r9<- method->clazz 3415 EXPORT_PC() @ must export for invoke 3416 bne .LOP_INVOKE_SUPER_RANGE_continue @ resolved, continue on 3417 b .LOP_INVOKE_SUPER_RANGE_resolve @ do resolve now 3418 3419 3420/* ------------------------------ */ 3421 .balign 64 3422.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3423/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */ 3424/* File: armv5te/OP_INVOKE_DIRECT.S */ 3425 /* 3426 * Handle a direct method call. 3427 * 3428 * (We could defer the "is 'this' pointer null" test to the common 3429 * method invocation code, and use a flag to indicate that static 3430 * calls don't count. If we do this as part of copying the arguments 3431 * out we could avoiding loading the first arg twice.) 3432 * 3433 * for: invoke-direct, invoke-direct/range 3434 */ 3435 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3436 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3437 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3438 FETCH(r1, 1) @ r1<- BBBB 3439 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3440 FETCH(r10, 2) @ r10<- GFED or CCCC 3441 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3442 .if (!1) 3443 and r10, r10, #15 @ r10<- D (or stays CCCC) 3444 .endif 3445 cmp r0, #0 @ already resolved? 3446 EXPORT_PC() @ must export for invoke 3447 GET_VREG(r2, r10) @ r2<- "this" ptr 3448 beq .LOP_INVOKE_DIRECT_RANGE_resolve @ not resolved, do it now 3449.LOP_INVOKE_DIRECT_RANGE_finish: 3450 cmp r2, #0 @ null "this" ref? 3451 bne common_invokeMethodRange @ no, continue on 3452 b common_errNullObject @ yes, throw exception 3453 3454 3455/* ------------------------------ */ 3456 .balign 64 3457.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3458/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */ 3459/* File: armv5te/OP_INVOKE_STATIC.S */ 3460 /* 3461 * Handle a static method call. 3462 * 3463 * for: invoke-static, invoke-static/range 3464 */ 3465 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3466 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3467 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- pDvmDex 3468 FETCH(r1, 1) @ r1<- BBBB 3469 ldr r3, [r3, #offDvmDex_pResMethods] @ r3<- pDvmDex->pResMethods 3470 ldr r0, [r3, r1, lsl #2] @ r0<- resolved methodToCall 3471 cmp r0, #0 @ already resolved? 3472 EXPORT_PC() @ must export for invoke 3473 bne common_invokeMethodRange @ yes, continue on 34740: ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 3475 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 3476 mov r2, #METHOD_STATIC @ resolver method type 3477 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 3478 cmp r0, #0 @ got null? 3479 bne common_invokeMethodRange @ no, continue 3480 b common_exceptionThrown @ yes, handle exception 3481 3482 3483 3484/* ------------------------------ */ 3485 .balign 64 3486.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3487/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */ 3488/* File: armv5te/OP_INVOKE_INTERFACE.S */ 3489 /* 3490 * Handle an interface method call. 3491 * 3492 * for: invoke-interface, invoke-interface/range 3493 */ 3494 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3495 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3496 FETCH(r2, 2) @ r2<- FEDC or CCCC 3497 FETCH(r1, 1) @ r1<- BBBB 3498 .if (!1) 3499 and r2, r2, #15 @ r2<- C (or stays CCCC) 3500 .endif 3501 EXPORT_PC() @ must export for invoke 3502 GET_VREG(r0, r2) @ r0<- first arg ("this") 3503 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- methodClassDex 3504 cmp r0, #0 @ null obj? 3505 ldr r2, [rGLUE, #offGlue_method] @ r2<- method 3506 beq common_errNullObject @ yes, fail 3507 ldr r0, [r0, #offObject_clazz] @ r0<- thisPtr->clazz 3508 bl dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex) 3509 cmp r0, #0 @ failed? 3510 beq common_exceptionThrown @ yes, handle exception 3511 b common_invokeMethodRange @ jump to common handler 3512 3513 3514 3515/* ------------------------------ */ 3516 .balign 64 3517.L_OP_UNUSED_79: /* 0x79 */ 3518/* File: armv5te/OP_UNUSED_79.S */ 3519/* File: armv5te/unused.S */ 3520 bl common_abort 3521 3522 3523 3524/* ------------------------------ */ 3525 .balign 64 3526.L_OP_UNUSED_7A: /* 0x7a */ 3527/* File: armv5te/OP_UNUSED_7A.S */ 3528/* File: armv5te/unused.S */ 3529 bl common_abort 3530 3531 3532 3533/* ------------------------------ */ 3534 .balign 64 3535.L_OP_NEG_INT: /* 0x7b */ 3536/* File: armv5te/OP_NEG_INT.S */ 3537/* File: armv5te/unop.S */ 3538 /* 3539 * Generic 32-bit unary operation. Provide an "instr" line that 3540 * specifies an instruction that performs "result = op r0". 3541 * This could be an ARM instruction or a function call. 3542 * 3543 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3544 * int-to-byte, int-to-char, int-to-short 3545 */ 3546 /* unop vA, vB */ 3547 mov r3, rINST, lsr #12 @ r3<- B 3548 mov r9, rINST, lsr #8 @ r9<- A+ 3549 GET_VREG(r0, r3) @ r0<- vB 3550 and r9, r9, #15 3551 @ optional op; may set condition codes 3552 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3553 rsb r0, r0, #0 @ r0<- op, r0-r3 changed 3554 GET_INST_OPCODE(ip) @ extract opcode from rINST 3555 SET_VREG(r0, r9) @ vAA<- r0 3556 GOTO_OPCODE(ip) @ jump to next instruction 3557 /* 9-10 instructions */ 3558 3559 3560/* ------------------------------ */ 3561 .balign 64 3562.L_OP_NOT_INT: /* 0x7c */ 3563/* File: armv5te/OP_NOT_INT.S */ 3564/* File: armv5te/unop.S */ 3565 /* 3566 * Generic 32-bit unary operation. Provide an "instr" line that 3567 * specifies an instruction that performs "result = op r0". 3568 * This could be an ARM instruction or a function call. 3569 * 3570 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3571 * int-to-byte, int-to-char, int-to-short 3572 */ 3573 /* unop vA, vB */ 3574 mov r3, rINST, lsr #12 @ r3<- B 3575 mov r9, rINST, lsr #8 @ r9<- A+ 3576 GET_VREG(r0, r3) @ r0<- vB 3577 and r9, r9, #15 3578 @ optional op; may set condition codes 3579 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3580 mvn r0, r0 @ r0<- op, r0-r3 changed 3581 GET_INST_OPCODE(ip) @ extract opcode from rINST 3582 SET_VREG(r0, r9) @ vAA<- r0 3583 GOTO_OPCODE(ip) @ jump to next instruction 3584 /* 9-10 instructions */ 3585 3586 3587/* ------------------------------ */ 3588 .balign 64 3589.L_OP_NEG_LONG: /* 0x7d */ 3590/* File: armv5te/OP_NEG_LONG.S */ 3591/* File: armv5te/unopWide.S */ 3592 /* 3593 * Generic 64-bit unary operation. Provide an "instr" line that 3594 * specifies an instruction that performs "result = op r0/r1". 3595 * This could be an ARM instruction or a function call. 3596 * 3597 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3598 */ 3599 /* unop vA, vB */ 3600 mov r9, rINST, lsr #8 @ r9<- A+ 3601 mov r3, rINST, lsr #12 @ r3<- B 3602 and r9, r9, #15 3603 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3604 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3605 ldmia r3, {r0-r1} @ r0/r1<- vAA 3606 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3607 rsbs r0, r0, #0 @ optional op; may set condition codes 3608 rsc r1, r1, #0 @ r0/r1<- op, r2-r3 changed 3609 GET_INST_OPCODE(ip) @ extract opcode from rINST 3610 stmia r9, {r0-r1} @ vAA<- r0/r1 3611 GOTO_OPCODE(ip) @ jump to next instruction 3612 /* 12-13 instructions */ 3613 3614 3615 3616/* ------------------------------ */ 3617 .balign 64 3618.L_OP_NOT_LONG: /* 0x7e */ 3619/* File: armv5te/OP_NOT_LONG.S */ 3620/* File: armv5te/unopWide.S */ 3621 /* 3622 * Generic 64-bit unary operation. Provide an "instr" line that 3623 * specifies an instruction that performs "result = op r0/r1". 3624 * This could be an ARM instruction or a function call. 3625 * 3626 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3627 */ 3628 /* unop vA, vB */ 3629 mov r9, rINST, lsr #8 @ r9<- A+ 3630 mov r3, rINST, lsr #12 @ r3<- B 3631 and r9, r9, #15 3632 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3633 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3634 ldmia r3, {r0-r1} @ r0/r1<- vAA 3635 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3636 mvn r0, r0 @ optional op; may set condition codes 3637 mvn r1, r1 @ r0/r1<- op, r2-r3 changed 3638 GET_INST_OPCODE(ip) @ extract opcode from rINST 3639 stmia r9, {r0-r1} @ vAA<- r0/r1 3640 GOTO_OPCODE(ip) @ jump to next instruction 3641 /* 12-13 instructions */ 3642 3643 3644 3645/* ------------------------------ */ 3646 .balign 64 3647.L_OP_NEG_FLOAT: /* 0x7f */ 3648/* File: armv5te/OP_NEG_FLOAT.S */ 3649/* File: armv5te/unop.S */ 3650 /* 3651 * Generic 32-bit unary operation. Provide an "instr" line that 3652 * specifies an instruction that performs "result = op r0". 3653 * This could be an ARM instruction or a function call. 3654 * 3655 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 3656 * int-to-byte, int-to-char, int-to-short 3657 */ 3658 /* unop vA, vB */ 3659 mov r3, rINST, lsr #12 @ r3<- B 3660 mov r9, rINST, lsr #8 @ r9<- A+ 3661 GET_VREG(r0, r3) @ r0<- vB 3662 and r9, r9, #15 3663 @ optional op; may set condition codes 3664 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3665 add r0, r0, #0x80000000 @ r0<- op, r0-r3 changed 3666 GET_INST_OPCODE(ip) @ extract opcode from rINST 3667 SET_VREG(r0, r9) @ vAA<- r0 3668 GOTO_OPCODE(ip) @ jump to next instruction 3669 /* 9-10 instructions */ 3670 3671 3672/* ------------------------------ */ 3673 .balign 64 3674.L_OP_NEG_DOUBLE: /* 0x80 */ 3675/* File: armv5te/OP_NEG_DOUBLE.S */ 3676/* File: armv5te/unopWide.S */ 3677 /* 3678 * Generic 64-bit unary operation. Provide an "instr" line that 3679 * specifies an instruction that performs "result = op r0/r1". 3680 * This could be an ARM instruction or a function call. 3681 * 3682 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3683 */ 3684 /* unop vA, vB */ 3685 mov r9, rINST, lsr #8 @ r9<- A+ 3686 mov r3, rINST, lsr #12 @ r3<- B 3687 and r9, r9, #15 3688 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3689 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3690 ldmia r3, {r0-r1} @ r0/r1<- vAA 3691 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3692 @ optional op; may set condition codes 3693 add r1, r1, #0x80000000 @ r0/r1<- op, r2-r3 changed 3694 GET_INST_OPCODE(ip) @ extract opcode from rINST 3695 stmia r9, {r0-r1} @ vAA<- r0/r1 3696 GOTO_OPCODE(ip) @ jump to next instruction 3697 /* 12-13 instructions */ 3698 3699 3700 3701/* ------------------------------ */ 3702 .balign 64 3703.L_OP_INT_TO_LONG: /* 0x81 */ 3704/* File: armv5te/OP_INT_TO_LONG.S */ 3705/* File: armv5te/unopWider.S */ 3706 /* 3707 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3708 * that specifies an instruction that performs "result = op r0", where 3709 * "result" is a 64-bit quantity in r0/r1. 3710 * 3711 * For: int-to-long, int-to-double, float-to-long, float-to-double 3712 */ 3713 /* unop vA, vB */ 3714 mov r9, rINST, lsr #8 @ r9<- A+ 3715 mov r3, rINST, lsr #12 @ r3<- B 3716 and r9, r9, #15 3717 GET_VREG(r0, r3) @ r0<- vB 3718 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3719 @ optional op; may set condition codes 3720 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3721 mov r1, r0, asr #31 @ r0<- op, r0-r3 changed 3722 GET_INST_OPCODE(ip) @ extract opcode from rINST 3723 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3724 GOTO_OPCODE(ip) @ jump to next instruction 3725 /* 10-11 instructions */ 3726 3727 3728/* ------------------------------ */ 3729 .balign 64 3730.L_OP_INT_TO_FLOAT: /* 0x82 */ 3731/* File: arm-vfp/OP_INT_TO_FLOAT.S */ 3732/* File: arm-vfp/funop.S */ 3733 /* 3734 * Generic 32-bit unary floating-point operation. Provide an "instr" 3735 * line that specifies an instruction that performs "s1 = op s0". 3736 * 3737 * for: int-to-float, float-to-int 3738 */ 3739 /* unop vA, vB */ 3740 mov r3, rINST, lsr #12 @ r3<- B 3741 mov r9, rINST, lsr #8 @ r9<- A+ 3742 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3743 flds s0, [r3] @ s0<- vB 3744 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3745 and r9, r9, #15 @ r9<- A 3746 fsitos s1, s0 @ s1<- op 3747 GET_INST_OPCODE(ip) @ extract opcode from rINST 3748 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3749 fsts s1, [r9] @ vA<- s1 3750 GOTO_OPCODE(ip) @ jump to next instruction 3751 3752 3753/* ------------------------------ */ 3754 .balign 64 3755.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3756/* File: arm-vfp/OP_INT_TO_DOUBLE.S */ 3757/* File: arm-vfp/funopWider.S */ 3758 /* 3759 * Generic 32bit-to-64bit floating point unary operation. Provide an 3760 * "instr" line that specifies an instruction that performs "d0 = op s0". 3761 * 3762 * For: int-to-double, float-to-double 3763 */ 3764 /* unop vA, vB */ 3765 mov r3, rINST, lsr #12 @ r3<- B 3766 mov r9, rINST, lsr #8 @ r9<- A+ 3767 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3768 flds s0, [r3] @ s0<- vB 3769 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3770 and r9, r9, #15 @ r9<- A 3771 fsitod d0, s0 @ d0<- op 3772 GET_INST_OPCODE(ip) @ extract opcode from rINST 3773 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3774 fstd d0, [r9] @ vA<- d0 3775 GOTO_OPCODE(ip) @ jump to next instruction 3776 3777 3778/* ------------------------------ */ 3779 .balign 64 3780.L_OP_LONG_TO_INT: /* 0x84 */ 3781/* File: armv5te/OP_LONG_TO_INT.S */ 3782/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3783/* File: armv5te/OP_MOVE.S */ 3784 /* for move, move-object, long-to-int */ 3785 /* op vA, vB */ 3786 mov r1, rINST, lsr #12 @ r1<- B from 15:12 3787 mov r0, rINST, lsr #8 @ r0<- A from 11:8 3788 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3789 GET_VREG(r2, r1) @ r2<- fp[B] 3790 and r0, r0, #15 3791 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 3792 SET_VREG(r2, r0) @ fp[A]<- r2 3793 GOTO_OPCODE(ip) @ execute next instruction 3794 3795 3796 3797/* ------------------------------ */ 3798 .balign 64 3799.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3800/* File: armv5te/OP_LONG_TO_FLOAT.S */ 3801/* File: armv5te/unopNarrower.S */ 3802 /* 3803 * Generic 64bit-to-32bit unary operation. Provide an "instr" line 3804 * that specifies an instruction that performs "result = op r0/r1", where 3805 * "result" is a 32-bit quantity in r0. 3806 * 3807 * For: long-to-float, double-to-int, double-to-float 3808 * 3809 * (This would work for long-to-int, but that instruction is actually 3810 * an exact match for OP_MOVE.) 3811 */ 3812 /* unop vA, vB */ 3813 mov r3, rINST, lsr #12 @ r3<- B 3814 mov r9, rINST, lsr #8 @ r9<- A+ 3815 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3816 and r9, r9, #15 3817 ldmia r3, {r0-r1} @ r0/r1<- vB/vB+1 3818 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3819 @ optional op; may set condition codes 3820 bl __aeabi_l2f @ r0<- op, r0-r3 changed 3821 GET_INST_OPCODE(ip) @ extract opcode from rINST 3822 SET_VREG(r0, r9) @ vA<- r0 3823 GOTO_OPCODE(ip) @ jump to next instruction 3824 /* 10-11 instructions */ 3825 3826 3827/* ------------------------------ */ 3828 .balign 64 3829.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3830/* File: armv5te/OP_LONG_TO_DOUBLE.S */ 3831/* File: armv5te/unopWide.S */ 3832 /* 3833 * Generic 64-bit unary operation. Provide an "instr" line that 3834 * specifies an instruction that performs "result = op r0/r1". 3835 * This could be an ARM instruction or a function call. 3836 * 3837 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3838 */ 3839 /* unop vA, vB */ 3840 mov r9, rINST, lsr #8 @ r9<- A+ 3841 mov r3, rINST, lsr #12 @ r3<- B 3842 and r9, r9, #15 3843 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3844 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3845 ldmia r3, {r0-r1} @ r0/r1<- vAA 3846 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3847 @ optional op; may set condition codes 3848 bl __aeabi_l2d @ r0/r1<- op, r2-r3 changed 3849 GET_INST_OPCODE(ip) @ extract opcode from rINST 3850 stmia r9, {r0-r1} @ vAA<- r0/r1 3851 GOTO_OPCODE(ip) @ jump to next instruction 3852 /* 12-13 instructions */ 3853 3854 3855 3856/* ------------------------------ */ 3857 .balign 64 3858.L_OP_FLOAT_TO_INT: /* 0x87 */ 3859/* File: arm-vfp/OP_FLOAT_TO_INT.S */ 3860/* File: arm-vfp/funop.S */ 3861 /* 3862 * Generic 32-bit unary floating-point operation. Provide an "instr" 3863 * line that specifies an instruction that performs "s1 = op s0". 3864 * 3865 * for: int-to-float, float-to-int 3866 */ 3867 /* unop vA, vB */ 3868 mov r3, rINST, lsr #12 @ r3<- B 3869 mov r9, rINST, lsr #8 @ r9<- A+ 3870 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3871 flds s0, [r3] @ s0<- vB 3872 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3873 and r9, r9, #15 @ r9<- A 3874 ftosizs s1, s0 @ s1<- op 3875 GET_INST_OPCODE(ip) @ extract opcode from rINST 3876 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3877 fsts s1, [r9] @ vA<- s1 3878 GOTO_OPCODE(ip) @ jump to next instruction 3879 3880 3881/* ------------------------------ */ 3882 .balign 64 3883.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3884/* File: armv5te/OP_FLOAT_TO_LONG.S */ 3885@include "armv5te/unopWider.S" {"instr":"bl __aeabi_f2lz"} 3886/* File: armv5te/unopWider.S */ 3887 /* 3888 * Generic 32bit-to-64bit unary operation. Provide an "instr" line 3889 * that specifies an instruction that performs "result = op r0", where 3890 * "result" is a 64-bit quantity in r0/r1. 3891 * 3892 * For: int-to-long, int-to-double, float-to-long, float-to-double 3893 */ 3894 /* unop vA, vB */ 3895 mov r9, rINST, lsr #8 @ r9<- A+ 3896 mov r3, rINST, lsr #12 @ r3<- B 3897 and r9, r9, #15 3898 GET_VREG(r0, r3) @ r0<- vB 3899 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3900 @ optional op; may set condition codes 3901 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3902 bl f2l_doconv @ r0<- op, r0-r3 changed 3903 GET_INST_OPCODE(ip) @ extract opcode from rINST 3904 stmia r9, {r0-r1} @ vA/vA+1<- r0/r1 3905 GOTO_OPCODE(ip) @ jump to next instruction 3906 /* 10-11 instructions */ 3907 3908 3909 3910/* ------------------------------ */ 3911 .balign 64 3912.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3913/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */ 3914/* File: arm-vfp/funopWider.S */ 3915 /* 3916 * Generic 32bit-to-64bit floating point unary operation. Provide an 3917 * "instr" line that specifies an instruction that performs "d0 = op s0". 3918 * 3919 * For: int-to-double, float-to-double 3920 */ 3921 /* unop vA, vB */ 3922 mov r3, rINST, lsr #12 @ r3<- B 3923 mov r9, rINST, lsr #8 @ r9<- A+ 3924 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3925 flds s0, [r3] @ s0<- vB 3926 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3927 and r9, r9, #15 @ r9<- A 3928 fcvtds d0, s0 @ d0<- op 3929 GET_INST_OPCODE(ip) @ extract opcode from rINST 3930 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3931 fstd d0, [r9] @ vA<- d0 3932 GOTO_OPCODE(ip) @ jump to next instruction 3933 3934 3935/* ------------------------------ */ 3936 .balign 64 3937.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3938/* File: arm-vfp/OP_DOUBLE_TO_INT.S */ 3939/* File: arm-vfp/funopNarrower.S */ 3940 /* 3941 * Generic 64bit-to-32bit unary floating point operation. Provide an 3942 * "instr" line that specifies an instruction that performs "s0 = op d0". 3943 * 3944 * For: double-to-int, double-to-float 3945 */ 3946 /* unop vA, vB */ 3947 mov r3, rINST, lsr #12 @ r3<- B 3948 mov r9, rINST, lsr #8 @ r9<- A+ 3949 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 3950 fldd d0, [r3] @ d0<- vB 3951 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3952 and r9, r9, #15 @ r9<- A 3953 ftosizd s0, d0 @ s0<- op 3954 GET_INST_OPCODE(ip) @ extract opcode from rINST 3955 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 3956 fsts s0, [r9] @ vA<- s0 3957 GOTO_OPCODE(ip) @ jump to next instruction 3958 3959 3960/* ------------------------------ */ 3961 .balign 64 3962.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3963/* File: armv5te/OP_DOUBLE_TO_LONG.S */ 3964@include "armv5te/unopWide.S" {"instr":"bl __aeabi_d2lz"} 3965/* File: armv5te/unopWide.S */ 3966 /* 3967 * Generic 64-bit unary operation. Provide an "instr" line that 3968 * specifies an instruction that performs "result = op r0/r1". 3969 * This could be an ARM instruction or a function call. 3970 * 3971 * For: neg-long, not-long, neg-double, long-to-double, double-to-long 3972 */ 3973 /* unop vA, vB */ 3974 mov r9, rINST, lsr #8 @ r9<- A+ 3975 mov r3, rINST, lsr #12 @ r3<- B 3976 and r9, r9, #15 3977 add r3, rFP, r3, lsl #2 @ r3<- &fp[B] 3978 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 3979 ldmia r3, {r0-r1} @ r0/r1<- vAA 3980 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 3981 @ optional op; may set condition codes 3982 bl d2l_doconv @ r0/r1<- op, r2-r3 changed 3983 GET_INST_OPCODE(ip) @ extract opcode from rINST 3984 stmia r9, {r0-r1} @ vAA<- r0/r1 3985 GOTO_OPCODE(ip) @ jump to next instruction 3986 /* 12-13 instructions */ 3987 3988 3989 3990 3991/* ------------------------------ */ 3992 .balign 64 3993.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3994/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */ 3995/* File: arm-vfp/funopNarrower.S */ 3996 /* 3997 * Generic 64bit-to-32bit unary floating point operation. Provide an 3998 * "instr" line that specifies an instruction that performs "s0 = op d0". 3999 * 4000 * For: double-to-int, double-to-float 4001 */ 4002 /* unop vA, vB */ 4003 mov r3, rINST, lsr #12 @ r3<- B 4004 mov r9, rINST, lsr #8 @ r9<- A+ 4005 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 4006 fldd d0, [r3] @ d0<- vB 4007 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4008 and r9, r9, #15 @ r9<- A 4009 fcvtsd s0, d0 @ s0<- op 4010 GET_INST_OPCODE(ip) @ extract opcode from rINST 4011 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 4012 fsts s0, [r9] @ vA<- s0 4013 GOTO_OPCODE(ip) @ jump to next instruction 4014 4015 4016/* ------------------------------ */ 4017 .balign 64 4018.L_OP_INT_TO_BYTE: /* 0x8d */ 4019/* File: armv5te/OP_INT_TO_BYTE.S */ 4020/* File: armv5te/unop.S */ 4021 /* 4022 * Generic 32-bit unary operation. Provide an "instr" line that 4023 * specifies an instruction that performs "result = op r0". 4024 * This could be an ARM instruction or a function call. 4025 * 4026 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4027 * int-to-byte, int-to-char, int-to-short 4028 */ 4029 /* unop vA, vB */ 4030 mov r3, rINST, lsr #12 @ r3<- B 4031 mov r9, rINST, lsr #8 @ r9<- A+ 4032 GET_VREG(r0, r3) @ r0<- vB 4033 and r9, r9, #15 4034 mov r0, r0, asl #24 @ optional op; may set condition codes 4035 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4036 mov r0, r0, asr #24 @ r0<- op, r0-r3 changed 4037 GET_INST_OPCODE(ip) @ extract opcode from rINST 4038 SET_VREG(r0, r9) @ vAA<- r0 4039 GOTO_OPCODE(ip) @ jump to next instruction 4040 /* 9-10 instructions */ 4041 4042 4043/* ------------------------------ */ 4044 .balign 64 4045.L_OP_INT_TO_CHAR: /* 0x8e */ 4046/* File: armv5te/OP_INT_TO_CHAR.S */ 4047/* File: armv5te/unop.S */ 4048 /* 4049 * Generic 32-bit unary operation. Provide an "instr" line that 4050 * specifies an instruction that performs "result = op r0". 4051 * This could be an ARM instruction or a function call. 4052 * 4053 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4054 * int-to-byte, int-to-char, int-to-short 4055 */ 4056 /* unop vA, vB */ 4057 mov r3, rINST, lsr #12 @ r3<- B 4058 mov r9, rINST, lsr #8 @ r9<- A+ 4059 GET_VREG(r0, r3) @ r0<- vB 4060 and r9, r9, #15 4061 mov r0, r0, asl #16 @ optional op; may set condition codes 4062 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4063 mov r0, r0, lsr #16 @ r0<- op, r0-r3 changed 4064 GET_INST_OPCODE(ip) @ extract opcode from rINST 4065 SET_VREG(r0, r9) @ vAA<- r0 4066 GOTO_OPCODE(ip) @ jump to next instruction 4067 /* 9-10 instructions */ 4068 4069 4070/* ------------------------------ */ 4071 .balign 64 4072.L_OP_INT_TO_SHORT: /* 0x8f */ 4073/* File: armv5te/OP_INT_TO_SHORT.S */ 4074/* File: armv5te/unop.S */ 4075 /* 4076 * Generic 32-bit unary operation. Provide an "instr" line that 4077 * specifies an instruction that performs "result = op r0". 4078 * This could be an ARM instruction or a function call. 4079 * 4080 * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 4081 * int-to-byte, int-to-char, int-to-short 4082 */ 4083 /* unop vA, vB */ 4084 mov r3, rINST, lsr #12 @ r3<- B 4085 mov r9, rINST, lsr #8 @ r9<- A+ 4086 GET_VREG(r0, r3) @ r0<- vB 4087 and r9, r9, #15 4088 mov r0, r0, asl #16 @ optional op; may set condition codes 4089 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 4090 mov r0, r0, asr #16 @ r0<- op, r0-r3 changed 4091 GET_INST_OPCODE(ip) @ extract opcode from rINST 4092 SET_VREG(r0, r9) @ vAA<- r0 4093 GOTO_OPCODE(ip) @ jump to next instruction 4094 /* 9-10 instructions */ 4095 4096 4097/* ------------------------------ */ 4098 .balign 64 4099.L_OP_ADD_INT: /* 0x90 */ 4100/* File: armv5te/OP_ADD_INT.S */ 4101/* File: armv5te/binop.S */ 4102 /* 4103 * Generic 32-bit binary operation. Provide an "instr" line that 4104 * specifies an instruction that performs "result = r0 op r1". 4105 * This could be an ARM instruction or a function call. (If the result 4106 * comes back in a register other than r0, you can override "result".) 4107 * 4108 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4109 * vCC (r1). Useful for integer division and modulus. Note that we 4110 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4111 * handles it correctly. 4112 * 4113 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4114 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4115 * mul-float, div-float, rem-float 4116 */ 4117 /* binop vAA, vBB, vCC */ 4118 FETCH(r0, 1) @ r0<- CCBB 4119 mov r9, rINST, lsr #8 @ r9<- AA 4120 mov r3, r0, lsr #8 @ r3<- CC 4121 and r2, r0, #255 @ r2<- BB 4122 GET_VREG(r1, r3) @ r1<- vCC 4123 GET_VREG(r0, r2) @ r0<- vBB 4124 .if 0 4125 cmp r1, #0 @ is second operand zero? 4126 beq common_errDivideByZero 4127 .endif 4128 4129 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4130 @ optional op; may set condition codes 4131 add r0, r0, r1 @ r0<- op, r0-r3 changed 4132 GET_INST_OPCODE(ip) @ extract opcode from rINST 4133 SET_VREG(r0, r9) @ vAA<- r0 4134 GOTO_OPCODE(ip) @ jump to next instruction 4135 /* 11-14 instructions */ 4136 4137 4138 4139/* ------------------------------ */ 4140 .balign 64 4141.L_OP_SUB_INT: /* 0x91 */ 4142/* File: armv5te/OP_SUB_INT.S */ 4143/* File: armv5te/binop.S */ 4144 /* 4145 * Generic 32-bit binary operation. Provide an "instr" line that 4146 * specifies an instruction that performs "result = r0 op r1". 4147 * This could be an ARM instruction or a function call. (If the result 4148 * comes back in a register other than r0, you can override "result".) 4149 * 4150 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4151 * vCC (r1). Useful for integer division and modulus. Note that we 4152 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4153 * handles it correctly. 4154 * 4155 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4156 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4157 * mul-float, div-float, rem-float 4158 */ 4159 /* binop vAA, vBB, vCC */ 4160 FETCH(r0, 1) @ r0<- CCBB 4161 mov r9, rINST, lsr #8 @ r9<- AA 4162 mov r3, r0, lsr #8 @ r3<- CC 4163 and r2, r0, #255 @ r2<- BB 4164 GET_VREG(r1, r3) @ r1<- vCC 4165 GET_VREG(r0, r2) @ r0<- vBB 4166 .if 0 4167 cmp r1, #0 @ is second operand zero? 4168 beq common_errDivideByZero 4169 .endif 4170 4171 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4172 @ optional op; may set condition codes 4173 sub r0, r0, r1 @ r0<- op, r0-r3 changed 4174 GET_INST_OPCODE(ip) @ extract opcode from rINST 4175 SET_VREG(r0, r9) @ vAA<- r0 4176 GOTO_OPCODE(ip) @ jump to next instruction 4177 /* 11-14 instructions */ 4178 4179 4180 4181/* ------------------------------ */ 4182 .balign 64 4183.L_OP_MUL_INT: /* 0x92 */ 4184/* File: armv5te/OP_MUL_INT.S */ 4185/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 4186/* File: armv5te/binop.S */ 4187 /* 4188 * Generic 32-bit binary operation. Provide an "instr" line that 4189 * specifies an instruction that performs "result = r0 op r1". 4190 * This could be an ARM instruction or a function call. (If the result 4191 * comes back in a register other than r0, you can override "result".) 4192 * 4193 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4194 * vCC (r1). Useful for integer division and modulus. Note that we 4195 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4196 * handles it correctly. 4197 * 4198 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4199 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4200 * mul-float, div-float, rem-float 4201 */ 4202 /* binop vAA, vBB, vCC */ 4203 FETCH(r0, 1) @ r0<- CCBB 4204 mov r9, rINST, lsr #8 @ r9<- AA 4205 mov r3, r0, lsr #8 @ r3<- CC 4206 and r2, r0, #255 @ r2<- BB 4207 GET_VREG(r1, r3) @ r1<- vCC 4208 GET_VREG(r0, r2) @ r0<- vBB 4209 .if 0 4210 cmp r1, #0 @ is second operand zero? 4211 beq common_errDivideByZero 4212 .endif 4213 4214 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4215 @ optional op; may set condition codes 4216 mul r0, r1, r0 @ r0<- op, r0-r3 changed 4217 GET_INST_OPCODE(ip) @ extract opcode from rINST 4218 SET_VREG(r0, r9) @ vAA<- r0 4219 GOTO_OPCODE(ip) @ jump to next instruction 4220 /* 11-14 instructions */ 4221 4222 4223 4224/* ------------------------------ */ 4225 .balign 64 4226.L_OP_DIV_INT: /* 0x93 */ 4227/* File: armv5te/OP_DIV_INT.S */ 4228/* File: armv5te/binop.S */ 4229 /* 4230 * Generic 32-bit binary operation. Provide an "instr" line that 4231 * specifies an instruction that performs "result = r0 op r1". 4232 * This could be an ARM instruction or a function call. (If the result 4233 * comes back in a register other than r0, you can override "result".) 4234 * 4235 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4236 * vCC (r1). Useful for integer division and modulus. Note that we 4237 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4238 * handles it correctly. 4239 * 4240 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4241 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4242 * mul-float, div-float, rem-float 4243 */ 4244 /* binop vAA, vBB, vCC */ 4245 FETCH(r0, 1) @ r0<- CCBB 4246 mov r9, rINST, lsr #8 @ r9<- AA 4247 mov r3, r0, lsr #8 @ r3<- CC 4248 and r2, r0, #255 @ r2<- BB 4249 GET_VREG(r1, r3) @ r1<- vCC 4250 GET_VREG(r0, r2) @ r0<- vBB 4251 .if 1 4252 cmp r1, #0 @ is second operand zero? 4253 beq common_errDivideByZero 4254 .endif 4255 4256 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4257 @ optional op; may set condition codes 4258 bl __aeabi_idiv @ r0<- op, r0-r3 changed 4259 GET_INST_OPCODE(ip) @ extract opcode from rINST 4260 SET_VREG(r0, r9) @ vAA<- r0 4261 GOTO_OPCODE(ip) @ jump to next instruction 4262 /* 11-14 instructions */ 4263 4264 4265 4266/* ------------------------------ */ 4267 .balign 64 4268.L_OP_REM_INT: /* 0x94 */ 4269/* File: armv5te/OP_REM_INT.S */ 4270/* idivmod returns quotient in r0 and remainder in r1 */ 4271/* File: armv5te/binop.S */ 4272 /* 4273 * Generic 32-bit binary operation. Provide an "instr" line that 4274 * specifies an instruction that performs "result = r0 op r1". 4275 * This could be an ARM instruction or a function call. (If the result 4276 * comes back in a register other than r0, you can override "result".) 4277 * 4278 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4279 * vCC (r1). Useful for integer division and modulus. Note that we 4280 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4281 * handles it correctly. 4282 * 4283 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4284 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4285 * mul-float, div-float, rem-float 4286 */ 4287 /* binop vAA, vBB, vCC */ 4288 FETCH(r0, 1) @ r0<- CCBB 4289 mov r9, rINST, lsr #8 @ r9<- AA 4290 mov r3, r0, lsr #8 @ r3<- CC 4291 and r2, r0, #255 @ r2<- BB 4292 GET_VREG(r1, r3) @ r1<- vCC 4293 GET_VREG(r0, r2) @ r0<- vBB 4294 .if 1 4295 cmp r1, #0 @ is second operand zero? 4296 beq common_errDivideByZero 4297 .endif 4298 4299 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4300 @ optional op; may set condition codes 4301 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 4302 GET_INST_OPCODE(ip) @ extract opcode from rINST 4303 SET_VREG(r1, r9) @ vAA<- r1 4304 GOTO_OPCODE(ip) @ jump to next instruction 4305 /* 11-14 instructions */ 4306 4307 4308 4309/* ------------------------------ */ 4310 .balign 64 4311.L_OP_AND_INT: /* 0x95 */ 4312/* File: armv5te/OP_AND_INT.S */ 4313/* File: armv5te/binop.S */ 4314 /* 4315 * Generic 32-bit binary operation. Provide an "instr" line that 4316 * specifies an instruction that performs "result = r0 op r1". 4317 * This could be an ARM instruction or a function call. (If the result 4318 * comes back in a register other than r0, you can override "result".) 4319 * 4320 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4321 * vCC (r1). Useful for integer division and modulus. Note that we 4322 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4323 * handles it correctly. 4324 * 4325 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4326 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4327 * mul-float, div-float, rem-float 4328 */ 4329 /* binop vAA, vBB, vCC */ 4330 FETCH(r0, 1) @ r0<- CCBB 4331 mov r9, rINST, lsr #8 @ r9<- AA 4332 mov r3, r0, lsr #8 @ r3<- CC 4333 and r2, r0, #255 @ r2<- BB 4334 GET_VREG(r1, r3) @ r1<- vCC 4335 GET_VREG(r0, r2) @ r0<- vBB 4336 .if 0 4337 cmp r1, #0 @ is second operand zero? 4338 beq common_errDivideByZero 4339 .endif 4340 4341 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4342 @ optional op; may set condition codes 4343 and r0, r0, r1 @ r0<- op, r0-r3 changed 4344 GET_INST_OPCODE(ip) @ extract opcode from rINST 4345 SET_VREG(r0, r9) @ vAA<- r0 4346 GOTO_OPCODE(ip) @ jump to next instruction 4347 /* 11-14 instructions */ 4348 4349 4350 4351/* ------------------------------ */ 4352 .balign 64 4353.L_OP_OR_INT: /* 0x96 */ 4354/* File: armv5te/OP_OR_INT.S */ 4355/* File: armv5te/binop.S */ 4356 /* 4357 * Generic 32-bit binary operation. Provide an "instr" line that 4358 * specifies an instruction that performs "result = r0 op r1". 4359 * This could be an ARM instruction or a function call. (If the result 4360 * comes back in a register other than r0, you can override "result".) 4361 * 4362 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4363 * vCC (r1). Useful for integer division and modulus. Note that we 4364 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4365 * handles it correctly. 4366 * 4367 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4368 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4369 * mul-float, div-float, rem-float 4370 */ 4371 /* binop vAA, vBB, vCC */ 4372 FETCH(r0, 1) @ r0<- CCBB 4373 mov r9, rINST, lsr #8 @ r9<- AA 4374 mov r3, r0, lsr #8 @ r3<- CC 4375 and r2, r0, #255 @ r2<- BB 4376 GET_VREG(r1, r3) @ r1<- vCC 4377 GET_VREG(r0, r2) @ r0<- vBB 4378 .if 0 4379 cmp r1, #0 @ is second operand zero? 4380 beq common_errDivideByZero 4381 .endif 4382 4383 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4384 @ optional op; may set condition codes 4385 orr r0, r0, r1 @ r0<- op, r0-r3 changed 4386 GET_INST_OPCODE(ip) @ extract opcode from rINST 4387 SET_VREG(r0, r9) @ vAA<- r0 4388 GOTO_OPCODE(ip) @ jump to next instruction 4389 /* 11-14 instructions */ 4390 4391 4392 4393/* ------------------------------ */ 4394 .balign 64 4395.L_OP_XOR_INT: /* 0x97 */ 4396/* File: armv5te/OP_XOR_INT.S */ 4397/* File: armv5te/binop.S */ 4398 /* 4399 * Generic 32-bit binary operation. Provide an "instr" line that 4400 * specifies an instruction that performs "result = r0 op r1". 4401 * This could be an ARM instruction or a function call. (If the result 4402 * comes back in a register other than r0, you can override "result".) 4403 * 4404 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4405 * vCC (r1). Useful for integer division and modulus. Note that we 4406 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4407 * handles it correctly. 4408 * 4409 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4410 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4411 * mul-float, div-float, rem-float 4412 */ 4413 /* binop vAA, vBB, vCC */ 4414 FETCH(r0, 1) @ r0<- CCBB 4415 mov r9, rINST, lsr #8 @ r9<- AA 4416 mov r3, r0, lsr #8 @ r3<- CC 4417 and r2, r0, #255 @ r2<- BB 4418 GET_VREG(r1, r3) @ r1<- vCC 4419 GET_VREG(r0, r2) @ r0<- vBB 4420 .if 0 4421 cmp r1, #0 @ is second operand zero? 4422 beq common_errDivideByZero 4423 .endif 4424 4425 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4426 @ optional op; may set condition codes 4427 eor r0, r0, r1 @ r0<- op, r0-r3 changed 4428 GET_INST_OPCODE(ip) @ extract opcode from rINST 4429 SET_VREG(r0, r9) @ vAA<- r0 4430 GOTO_OPCODE(ip) @ jump to next instruction 4431 /* 11-14 instructions */ 4432 4433 4434 4435/* ------------------------------ */ 4436 .balign 64 4437.L_OP_SHL_INT: /* 0x98 */ 4438/* File: armv5te/OP_SHL_INT.S */ 4439/* File: armv5te/binop.S */ 4440 /* 4441 * Generic 32-bit binary operation. Provide an "instr" line that 4442 * specifies an instruction that performs "result = r0 op r1". 4443 * This could be an ARM instruction or a function call. (If the result 4444 * comes back in a register other than r0, you can override "result".) 4445 * 4446 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4447 * vCC (r1). Useful for integer division and modulus. Note that we 4448 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4449 * handles it correctly. 4450 * 4451 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4452 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4453 * mul-float, div-float, rem-float 4454 */ 4455 /* binop vAA, vBB, vCC */ 4456 FETCH(r0, 1) @ r0<- CCBB 4457 mov r9, rINST, lsr #8 @ r9<- AA 4458 mov r3, r0, lsr #8 @ r3<- CC 4459 and r2, r0, #255 @ r2<- BB 4460 GET_VREG(r1, r3) @ r1<- vCC 4461 GET_VREG(r0, r2) @ r0<- vBB 4462 .if 0 4463 cmp r1, #0 @ is second operand zero? 4464 beq common_errDivideByZero 4465 .endif 4466 4467 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4468 and r1, r1, #31 @ optional op; may set condition codes 4469 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 4470 GET_INST_OPCODE(ip) @ extract opcode from rINST 4471 SET_VREG(r0, r9) @ vAA<- r0 4472 GOTO_OPCODE(ip) @ jump to next instruction 4473 /* 11-14 instructions */ 4474 4475 4476 4477/* ------------------------------ */ 4478 .balign 64 4479.L_OP_SHR_INT: /* 0x99 */ 4480/* File: armv5te/OP_SHR_INT.S */ 4481/* File: armv5te/binop.S */ 4482 /* 4483 * Generic 32-bit binary operation. Provide an "instr" line that 4484 * specifies an instruction that performs "result = r0 op r1". 4485 * This could be an ARM instruction or a function call. (If the result 4486 * comes back in a register other than r0, you can override "result".) 4487 * 4488 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4489 * vCC (r1). Useful for integer division and modulus. Note that we 4490 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4491 * handles it correctly. 4492 * 4493 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4494 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4495 * mul-float, div-float, rem-float 4496 */ 4497 /* binop vAA, vBB, vCC */ 4498 FETCH(r0, 1) @ r0<- CCBB 4499 mov r9, rINST, lsr #8 @ r9<- AA 4500 mov r3, r0, lsr #8 @ r3<- CC 4501 and r2, r0, #255 @ r2<- BB 4502 GET_VREG(r1, r3) @ r1<- vCC 4503 GET_VREG(r0, r2) @ r0<- vBB 4504 .if 0 4505 cmp r1, #0 @ is second operand zero? 4506 beq common_errDivideByZero 4507 .endif 4508 4509 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4510 and r1, r1, #31 @ optional op; may set condition codes 4511 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 4512 GET_INST_OPCODE(ip) @ extract opcode from rINST 4513 SET_VREG(r0, r9) @ vAA<- r0 4514 GOTO_OPCODE(ip) @ jump to next instruction 4515 /* 11-14 instructions */ 4516 4517 4518 4519/* ------------------------------ */ 4520 .balign 64 4521.L_OP_USHR_INT: /* 0x9a */ 4522/* File: armv5te/OP_USHR_INT.S */ 4523/* File: armv5te/binop.S */ 4524 /* 4525 * Generic 32-bit binary operation. Provide an "instr" line that 4526 * specifies an instruction that performs "result = r0 op r1". 4527 * This could be an ARM instruction or a function call. (If the result 4528 * comes back in a register other than r0, you can override "result".) 4529 * 4530 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4531 * vCC (r1). Useful for integer division and modulus. Note that we 4532 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 4533 * handles it correctly. 4534 * 4535 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 4536 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 4537 * mul-float, div-float, rem-float 4538 */ 4539 /* binop vAA, vBB, vCC */ 4540 FETCH(r0, 1) @ r0<- CCBB 4541 mov r9, rINST, lsr #8 @ r9<- AA 4542 mov r3, r0, lsr #8 @ r3<- CC 4543 and r2, r0, #255 @ r2<- BB 4544 GET_VREG(r1, r3) @ r1<- vCC 4545 GET_VREG(r0, r2) @ r0<- vBB 4546 .if 0 4547 cmp r1, #0 @ is second operand zero? 4548 beq common_errDivideByZero 4549 .endif 4550 4551 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4552 and r1, r1, #31 @ optional op; may set condition codes 4553 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 4554 GET_INST_OPCODE(ip) @ extract opcode from rINST 4555 SET_VREG(r0, r9) @ vAA<- r0 4556 GOTO_OPCODE(ip) @ jump to next instruction 4557 /* 11-14 instructions */ 4558 4559 4560 4561/* ------------------------------ */ 4562 .balign 64 4563.L_OP_ADD_LONG: /* 0x9b */ 4564/* File: armv5te/OP_ADD_LONG.S */ 4565/* File: armv5te/binopWide.S */ 4566 /* 4567 * Generic 64-bit binary operation. Provide an "instr" line that 4568 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4569 * This could be an ARM instruction or a function call. (If the result 4570 * comes back in a register other than r0, you can override "result".) 4571 * 4572 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4573 * vCC (r1). Useful for integer division and modulus. 4574 * 4575 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4576 * xor-long, add-double, sub-double, mul-double, div-double, 4577 * rem-double 4578 * 4579 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4580 */ 4581 /* binop vAA, vBB, vCC */ 4582 FETCH(r0, 1) @ r0<- CCBB 4583 mov r9, rINST, lsr #8 @ r9<- AA 4584 and r2, r0, #255 @ r2<- BB 4585 mov r3, r0, lsr #8 @ r3<- CC 4586 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4587 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4588 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4589 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4590 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4591 .if 0 4592 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4593 beq common_errDivideByZero 4594 .endif 4595 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4596 4597 adds r0, r0, r2 @ optional op; may set condition codes 4598 adc r1, r1, r3 @ result<- op, r0-r3 changed 4599 GET_INST_OPCODE(ip) @ extract opcode from rINST 4600 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4601 GOTO_OPCODE(ip) @ jump to next instruction 4602 /* 14-17 instructions */ 4603 4604 4605 4606/* ------------------------------ */ 4607 .balign 64 4608.L_OP_SUB_LONG: /* 0x9c */ 4609/* File: armv5te/OP_SUB_LONG.S */ 4610/* File: armv5te/binopWide.S */ 4611 /* 4612 * Generic 64-bit binary operation. Provide an "instr" line that 4613 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4614 * This could be an ARM instruction or a function call. (If the result 4615 * comes back in a register other than r0, you can override "result".) 4616 * 4617 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4618 * vCC (r1). Useful for integer division and modulus. 4619 * 4620 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4621 * xor-long, add-double, sub-double, mul-double, div-double, 4622 * rem-double 4623 * 4624 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4625 */ 4626 /* binop vAA, vBB, vCC */ 4627 FETCH(r0, 1) @ r0<- CCBB 4628 mov r9, rINST, lsr #8 @ r9<- AA 4629 and r2, r0, #255 @ r2<- BB 4630 mov r3, r0, lsr #8 @ r3<- CC 4631 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4632 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4633 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4634 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4635 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4636 .if 0 4637 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4638 beq common_errDivideByZero 4639 .endif 4640 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4641 4642 subs r0, r0, r2 @ optional op; may set condition codes 4643 sbc r1, r1, r3 @ result<- op, r0-r3 changed 4644 GET_INST_OPCODE(ip) @ extract opcode from rINST 4645 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4646 GOTO_OPCODE(ip) @ jump to next instruction 4647 /* 14-17 instructions */ 4648 4649 4650 4651/* ------------------------------ */ 4652 .balign 64 4653.L_OP_MUL_LONG: /* 0x9d */ 4654/* File: armv5te/OP_MUL_LONG.S */ 4655 /* 4656 * Signed 64-bit integer multiply. 4657 * 4658 * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 4659 * WX 4660 * x YZ 4661 * -------- 4662 * ZW ZX 4663 * YW YX 4664 * 4665 * The low word of the result holds ZX, the high word holds 4666 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 4667 * it doesn't fit in the low 64 bits. 4668 * 4669 * Unlike most ARM math operations, multiply instructions have 4670 * restrictions on using the same register more than once (Rd and Rm 4671 * cannot be the same). 4672 */ 4673 /* mul-long vAA, vBB, vCC */ 4674 FETCH(r0, 1) @ r0<- CCBB 4675 and r2, r0, #255 @ r2<- BB 4676 mov r3, r0, lsr #8 @ r3<- CC 4677 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4678 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4679 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4680 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4681 mul ip, r2, r1 @ ip<- ZxW 4682 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 4683 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 4684 mov r0, rINST, lsr #8 @ r0<- AA 4685 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 4686 add r0, rFP, r0, lsl #2 @ r0<- &fp[AA] 4687 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4688 b .LOP_MUL_LONG_finish 4689 4690/* ------------------------------ */ 4691 .balign 64 4692.L_OP_DIV_LONG: /* 0x9e */ 4693/* File: armv5te/OP_DIV_LONG.S */ 4694/* File: armv5te/binopWide.S */ 4695 /* 4696 * Generic 64-bit binary operation. Provide an "instr" line that 4697 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4698 * This could be an ARM instruction or a function call. (If the result 4699 * comes back in a register other than r0, you can override "result".) 4700 * 4701 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4702 * vCC (r1). Useful for integer division and modulus. 4703 * 4704 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4705 * xor-long, add-double, sub-double, mul-double, div-double, 4706 * rem-double 4707 * 4708 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4709 */ 4710 /* binop vAA, vBB, vCC */ 4711 FETCH(r0, 1) @ r0<- CCBB 4712 mov r9, rINST, lsr #8 @ r9<- AA 4713 and r2, r0, #255 @ r2<- BB 4714 mov r3, r0, lsr #8 @ r3<- CC 4715 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4716 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4717 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4718 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4719 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4720 .if 1 4721 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4722 beq common_errDivideByZero 4723 .endif 4724 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4725 4726 @ optional op; may set condition codes 4727 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4728 GET_INST_OPCODE(ip) @ extract opcode from rINST 4729 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4730 GOTO_OPCODE(ip) @ jump to next instruction 4731 /* 14-17 instructions */ 4732 4733 4734 4735/* ------------------------------ */ 4736 .balign 64 4737.L_OP_REM_LONG: /* 0x9f */ 4738/* File: armv5te/OP_REM_LONG.S */ 4739/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 4740/* File: armv5te/binopWide.S */ 4741 /* 4742 * Generic 64-bit binary operation. Provide an "instr" line that 4743 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4744 * This could be an ARM instruction or a function call. (If the result 4745 * comes back in a register other than r0, you can override "result".) 4746 * 4747 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4748 * vCC (r1). Useful for integer division and modulus. 4749 * 4750 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4751 * xor-long, add-double, sub-double, mul-double, div-double, 4752 * rem-double 4753 * 4754 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4755 */ 4756 /* binop vAA, vBB, vCC */ 4757 FETCH(r0, 1) @ r0<- CCBB 4758 mov r9, rINST, lsr #8 @ r9<- AA 4759 and r2, r0, #255 @ r2<- BB 4760 mov r3, r0, lsr #8 @ r3<- CC 4761 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4762 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4763 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4764 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4765 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4766 .if 1 4767 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4768 beq common_errDivideByZero 4769 .endif 4770 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4771 4772 @ optional op; may set condition codes 4773 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 4774 GET_INST_OPCODE(ip) @ extract opcode from rINST 4775 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 4776 GOTO_OPCODE(ip) @ jump to next instruction 4777 /* 14-17 instructions */ 4778 4779 4780 4781/* ------------------------------ */ 4782 .balign 64 4783.L_OP_AND_LONG: /* 0xa0 */ 4784/* File: armv5te/OP_AND_LONG.S */ 4785/* File: armv5te/binopWide.S */ 4786 /* 4787 * Generic 64-bit binary operation. Provide an "instr" line that 4788 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4789 * This could be an ARM instruction or a function call. (If the result 4790 * comes back in a register other than r0, you can override "result".) 4791 * 4792 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4793 * vCC (r1). Useful for integer division and modulus. 4794 * 4795 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4796 * xor-long, add-double, sub-double, mul-double, div-double, 4797 * rem-double 4798 * 4799 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4800 */ 4801 /* binop vAA, vBB, vCC */ 4802 FETCH(r0, 1) @ r0<- CCBB 4803 mov r9, rINST, lsr #8 @ r9<- AA 4804 and r2, r0, #255 @ r2<- BB 4805 mov r3, r0, lsr #8 @ r3<- CC 4806 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4807 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4808 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4809 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4810 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4811 .if 0 4812 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4813 beq common_errDivideByZero 4814 .endif 4815 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4816 4817 and r0, r0, r2 @ optional op; may set condition codes 4818 and r1, r1, r3 @ result<- op, r0-r3 changed 4819 GET_INST_OPCODE(ip) @ extract opcode from rINST 4820 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4821 GOTO_OPCODE(ip) @ jump to next instruction 4822 /* 14-17 instructions */ 4823 4824 4825 4826/* ------------------------------ */ 4827 .balign 64 4828.L_OP_OR_LONG: /* 0xa1 */ 4829/* File: armv5te/OP_OR_LONG.S */ 4830/* File: armv5te/binopWide.S */ 4831 /* 4832 * Generic 64-bit binary operation. Provide an "instr" line that 4833 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4834 * This could be an ARM instruction or a function call. (If the result 4835 * comes back in a register other than r0, you can override "result".) 4836 * 4837 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4838 * vCC (r1). Useful for integer division and modulus. 4839 * 4840 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4841 * xor-long, add-double, sub-double, mul-double, div-double, 4842 * rem-double 4843 * 4844 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4845 */ 4846 /* binop vAA, vBB, vCC */ 4847 FETCH(r0, 1) @ r0<- CCBB 4848 mov r9, rINST, lsr #8 @ r9<- AA 4849 and r2, r0, #255 @ r2<- BB 4850 mov r3, r0, lsr #8 @ r3<- CC 4851 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4852 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4853 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4854 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4855 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4856 .if 0 4857 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4858 beq common_errDivideByZero 4859 .endif 4860 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4861 4862 orr r0, r0, r2 @ optional op; may set condition codes 4863 orr r1, r1, r3 @ result<- op, r0-r3 changed 4864 GET_INST_OPCODE(ip) @ extract opcode from rINST 4865 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4866 GOTO_OPCODE(ip) @ jump to next instruction 4867 /* 14-17 instructions */ 4868 4869 4870 4871/* ------------------------------ */ 4872 .balign 64 4873.L_OP_XOR_LONG: /* 0xa2 */ 4874/* File: armv5te/OP_XOR_LONG.S */ 4875/* File: armv5te/binopWide.S */ 4876 /* 4877 * Generic 64-bit binary operation. Provide an "instr" line that 4878 * specifies an instruction that performs "result = r0-r1 op r2-r3". 4879 * This could be an ARM instruction or a function call. (If the result 4880 * comes back in a register other than r0, you can override "result".) 4881 * 4882 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4883 * vCC (r1). Useful for integer division and modulus. 4884 * 4885 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 4886 * xor-long, add-double, sub-double, mul-double, div-double, 4887 * rem-double 4888 * 4889 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 4890 */ 4891 /* binop vAA, vBB, vCC */ 4892 FETCH(r0, 1) @ r0<- CCBB 4893 mov r9, rINST, lsr #8 @ r9<- AA 4894 and r2, r0, #255 @ r2<- BB 4895 mov r3, r0, lsr #8 @ r3<- CC 4896 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4897 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 4898 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 4899 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 4900 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 4901 .if 0 4902 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 4903 beq common_errDivideByZero 4904 .endif 4905 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4906 4907 eor r0, r0, r2 @ optional op; may set condition codes 4908 eor r1, r1, r3 @ result<- op, r0-r3 changed 4909 GET_INST_OPCODE(ip) @ extract opcode from rINST 4910 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 4911 GOTO_OPCODE(ip) @ jump to next instruction 4912 /* 14-17 instructions */ 4913 4914 4915 4916/* ------------------------------ */ 4917 .balign 64 4918.L_OP_SHL_LONG: /* 0xa3 */ 4919/* File: armv5te/OP_SHL_LONG.S */ 4920 /* 4921 * Long integer shift. This is different from the generic 32/64-bit 4922 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4923 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4924 * 6 bits of the shift distance. 4925 */ 4926 /* shl-long vAA, vBB, vCC */ 4927 FETCH(r0, 1) @ r0<- CCBB 4928 mov r9, rINST, lsr #8 @ r9<- AA 4929 and r3, r0, #255 @ r3<- BB 4930 mov r0, r0, lsr #8 @ r0<- CC 4931 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4932 GET_VREG(r2, r0) @ r2<- vCC 4933 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4934 and r2, r2, #63 @ r2<- r2 & 0x3f 4935 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4936 4937 mov r1, r1, asl r2 @ r1<- r1 << r2 4938 rsb r3, r2, #32 @ r3<- 32 - r2 4939 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 4940 subs ip, r2, #32 @ ip<- r2 - 32 4941 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 4942 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4943 b .LOP_SHL_LONG_finish 4944 4945/* ------------------------------ */ 4946 .balign 64 4947.L_OP_SHR_LONG: /* 0xa4 */ 4948/* File: armv5te/OP_SHR_LONG.S */ 4949 /* 4950 * Long integer shift. This is different from the generic 32/64-bit 4951 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4952 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4953 * 6 bits of the shift distance. 4954 */ 4955 /* shr-long vAA, vBB, vCC */ 4956 FETCH(r0, 1) @ r0<- CCBB 4957 mov r9, rINST, lsr #8 @ r9<- AA 4958 and r3, r0, #255 @ r3<- BB 4959 mov r0, r0, lsr #8 @ r0<- CC 4960 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4961 GET_VREG(r2, r0) @ r2<- vCC 4962 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4963 and r2, r2, #63 @ r0<- r0 & 0x3f 4964 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4965 4966 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4967 rsb r3, r2, #32 @ r3<- 32 - r2 4968 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4969 subs ip, r2, #32 @ ip<- r2 - 32 4970 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 4971 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 4972 b .LOP_SHR_LONG_finish 4973 4974/* ------------------------------ */ 4975 .balign 64 4976.L_OP_USHR_LONG: /* 0xa5 */ 4977/* File: armv5te/OP_USHR_LONG.S */ 4978 /* 4979 * Long integer shift. This is different from the generic 32/64-bit 4980 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4981 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4982 * 6 bits of the shift distance. 4983 */ 4984 /* ushr-long vAA, vBB, vCC */ 4985 FETCH(r0, 1) @ r0<- CCBB 4986 mov r9, rINST, lsr #8 @ r9<- AA 4987 and r3, r0, #255 @ r3<- BB 4988 mov r0, r0, lsr #8 @ r0<- CC 4989 add r3, rFP, r3, lsl #2 @ r3<- &fp[BB] 4990 GET_VREG(r2, r0) @ r2<- vCC 4991 ldmia r3, {r0-r1} @ r0/r1<- vBB/vBB+1 4992 and r2, r2, #63 @ r0<- r0 & 0x3f 4993 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 4994 4995 mov r0, r0, lsr r2 @ r0<- r2 >> r2 4996 rsb r3, r2, #32 @ r3<- 32 - r2 4997 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 4998 subs ip, r2, #32 @ ip<- r2 - 32 4999 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 5000 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5001 b .LOP_USHR_LONG_finish 5002 5003/* ------------------------------ */ 5004 .balign 64 5005.L_OP_ADD_FLOAT: /* 0xa6 */ 5006/* File: arm-vfp/OP_ADD_FLOAT.S */ 5007/* File: arm-vfp/fbinop.S */ 5008 /* 5009 * Generic 32-bit floating-point operation. Provide an "instr" line that 5010 * specifies an instruction that performs "s2 = s0 op s1". Because we 5011 * use the "softfp" ABI, this must be an instruction, not a function call. 5012 * 5013 * For: add-float, sub-float, mul-float, div-float 5014 */ 5015 /* floatop vAA, vBB, vCC */ 5016 FETCH(r0, 1) @ r0<- CCBB 5017 mov r9, rINST, lsr #8 @ r9<- AA 5018 mov r3, r0, lsr #8 @ r3<- CC 5019 and r2, r0, #255 @ r2<- BB 5020 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5021 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5022 flds s1, [r3] @ s1<- vCC 5023 flds s0, [r2] @ s0<- vBB 5024 5025 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5026 fadds s2, s0, s1 @ s2<- op 5027 GET_INST_OPCODE(ip) @ extract opcode from rINST 5028 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5029 fsts s2, [r9] @ vAA<- s2 5030 GOTO_OPCODE(ip) @ jump to next instruction 5031 5032 5033/* ------------------------------ */ 5034 .balign 64 5035.L_OP_SUB_FLOAT: /* 0xa7 */ 5036/* File: arm-vfp/OP_SUB_FLOAT.S */ 5037/* File: arm-vfp/fbinop.S */ 5038 /* 5039 * Generic 32-bit floating-point operation. Provide an "instr" line that 5040 * specifies an instruction that performs "s2 = s0 op s1". Because we 5041 * use the "softfp" ABI, this must be an instruction, not a function call. 5042 * 5043 * For: add-float, sub-float, mul-float, div-float 5044 */ 5045 /* floatop vAA, vBB, vCC */ 5046 FETCH(r0, 1) @ r0<- CCBB 5047 mov r9, rINST, lsr #8 @ r9<- AA 5048 mov r3, r0, lsr #8 @ r3<- CC 5049 and r2, r0, #255 @ r2<- BB 5050 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5051 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5052 flds s1, [r3] @ s1<- vCC 5053 flds s0, [r2] @ s0<- vBB 5054 5055 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5056 fsubs s2, s0, s1 @ s2<- op 5057 GET_INST_OPCODE(ip) @ extract opcode from rINST 5058 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5059 fsts s2, [r9] @ vAA<- s2 5060 GOTO_OPCODE(ip) @ jump to next instruction 5061 5062 5063/* ------------------------------ */ 5064 .balign 64 5065.L_OP_MUL_FLOAT: /* 0xa8 */ 5066/* File: arm-vfp/OP_MUL_FLOAT.S */ 5067/* File: arm-vfp/fbinop.S */ 5068 /* 5069 * Generic 32-bit floating-point operation. Provide an "instr" line that 5070 * specifies an instruction that performs "s2 = s0 op s1". Because we 5071 * use the "softfp" ABI, this must be an instruction, not a function call. 5072 * 5073 * For: add-float, sub-float, mul-float, div-float 5074 */ 5075 /* floatop vAA, vBB, vCC */ 5076 FETCH(r0, 1) @ r0<- CCBB 5077 mov r9, rINST, lsr #8 @ r9<- AA 5078 mov r3, r0, lsr #8 @ r3<- CC 5079 and r2, r0, #255 @ r2<- BB 5080 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5081 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5082 flds s1, [r3] @ s1<- vCC 5083 flds s0, [r2] @ s0<- vBB 5084 5085 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5086 fmuls s2, s0, s1 @ s2<- op 5087 GET_INST_OPCODE(ip) @ extract opcode from rINST 5088 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5089 fsts s2, [r9] @ vAA<- s2 5090 GOTO_OPCODE(ip) @ jump to next instruction 5091 5092 5093/* ------------------------------ */ 5094 .balign 64 5095.L_OP_DIV_FLOAT: /* 0xa9 */ 5096/* File: arm-vfp/OP_DIV_FLOAT.S */ 5097/* File: arm-vfp/fbinop.S */ 5098 /* 5099 * Generic 32-bit floating-point operation. Provide an "instr" line that 5100 * specifies an instruction that performs "s2 = s0 op s1". Because we 5101 * use the "softfp" ABI, this must be an instruction, not a function call. 5102 * 5103 * For: add-float, sub-float, mul-float, div-float 5104 */ 5105 /* floatop vAA, vBB, vCC */ 5106 FETCH(r0, 1) @ r0<- CCBB 5107 mov r9, rINST, lsr #8 @ r9<- AA 5108 mov r3, r0, lsr #8 @ r3<- CC 5109 and r2, r0, #255 @ r2<- BB 5110 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5111 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5112 flds s1, [r3] @ s1<- vCC 5113 flds s0, [r2] @ s0<- vBB 5114 5115 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5116 fdivs s2, s0, s1 @ s2<- op 5117 GET_INST_OPCODE(ip) @ extract opcode from rINST 5118 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5119 fsts s2, [r9] @ vAA<- s2 5120 GOTO_OPCODE(ip) @ jump to next instruction 5121 5122 5123/* ------------------------------ */ 5124 .balign 64 5125.L_OP_REM_FLOAT: /* 0xaa */ 5126/* File: armv5te/OP_REM_FLOAT.S */ 5127/* EABI doesn't define a float remainder function, but libm does */ 5128/* File: armv5te/binop.S */ 5129 /* 5130 * Generic 32-bit binary operation. Provide an "instr" line that 5131 * specifies an instruction that performs "result = r0 op r1". 5132 * This could be an ARM instruction or a function call. (If the result 5133 * comes back in a register other than r0, you can override "result".) 5134 * 5135 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5136 * vCC (r1). Useful for integer division and modulus. Note that we 5137 * *don't* check for (INT_MIN / -1) here, because the ARM math lib 5138 * handles it correctly. 5139 * 5140 * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 5141 * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 5142 * mul-float, div-float, rem-float 5143 */ 5144 /* binop vAA, vBB, vCC */ 5145 FETCH(r0, 1) @ r0<- CCBB 5146 mov r9, rINST, lsr #8 @ r9<- AA 5147 mov r3, r0, lsr #8 @ r3<- CC 5148 and r2, r0, #255 @ r2<- BB 5149 GET_VREG(r1, r3) @ r1<- vCC 5150 GET_VREG(r0, r2) @ r0<- vBB 5151 .if 0 5152 cmp r1, #0 @ is second operand zero? 5153 beq common_errDivideByZero 5154 .endif 5155 5156 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5157 @ optional op; may set condition codes 5158 bl fmodf @ r0<- op, r0-r3 changed 5159 GET_INST_OPCODE(ip) @ extract opcode from rINST 5160 SET_VREG(r0, r9) @ vAA<- r0 5161 GOTO_OPCODE(ip) @ jump to next instruction 5162 /* 11-14 instructions */ 5163 5164 5165 5166/* ------------------------------ */ 5167 .balign 64 5168.L_OP_ADD_DOUBLE: /* 0xab */ 5169/* File: arm-vfp/OP_ADD_DOUBLE.S */ 5170/* File: arm-vfp/fbinopWide.S */ 5171 /* 5172 * Generic 64-bit double-precision floating point binary operation. 5173 * Provide an "instr" line that specifies an instruction that performs 5174 * "d2 = d0 op d1". 5175 * 5176 * for: add-double, sub-double, mul-double, div-double 5177 */ 5178 /* doubleop vAA, vBB, vCC */ 5179 FETCH(r0, 1) @ r0<- CCBB 5180 mov r9, rINST, lsr #8 @ r9<- AA 5181 mov r3, r0, lsr #8 @ r3<- CC 5182 and r2, r0, #255 @ r2<- BB 5183 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5184 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5185 fldd d1, [r3] @ d1<- vCC 5186 fldd d0, [r2] @ d0<- vBB 5187 5188 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5189 faddd d2, d0, d1 @ s2<- op 5190 GET_INST_OPCODE(ip) @ extract opcode from rINST 5191 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5192 fstd d2, [r9] @ vAA<- d2 5193 GOTO_OPCODE(ip) @ jump to next instruction 5194 5195 5196/* ------------------------------ */ 5197 .balign 64 5198.L_OP_SUB_DOUBLE: /* 0xac */ 5199/* File: arm-vfp/OP_SUB_DOUBLE.S */ 5200/* File: arm-vfp/fbinopWide.S */ 5201 /* 5202 * Generic 64-bit double-precision floating point binary operation. 5203 * Provide an "instr" line that specifies an instruction that performs 5204 * "d2 = d0 op d1". 5205 * 5206 * for: add-double, sub-double, mul-double, div-double 5207 */ 5208 /* doubleop vAA, vBB, vCC */ 5209 FETCH(r0, 1) @ r0<- CCBB 5210 mov r9, rINST, lsr #8 @ r9<- AA 5211 mov r3, r0, lsr #8 @ r3<- CC 5212 and r2, r0, #255 @ r2<- BB 5213 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5214 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5215 fldd d1, [r3] @ d1<- vCC 5216 fldd d0, [r2] @ d0<- vBB 5217 5218 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5219 fsubd d2, d0, d1 @ s2<- op 5220 GET_INST_OPCODE(ip) @ extract opcode from rINST 5221 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5222 fstd d2, [r9] @ vAA<- d2 5223 GOTO_OPCODE(ip) @ jump to next instruction 5224 5225 5226/* ------------------------------ */ 5227 .balign 64 5228.L_OP_MUL_DOUBLE: /* 0xad */ 5229/* File: arm-vfp/OP_MUL_DOUBLE.S */ 5230/* File: arm-vfp/fbinopWide.S */ 5231 /* 5232 * Generic 64-bit double-precision floating point binary operation. 5233 * Provide an "instr" line that specifies an instruction that performs 5234 * "d2 = d0 op d1". 5235 * 5236 * for: add-double, sub-double, mul-double, div-double 5237 */ 5238 /* doubleop vAA, vBB, vCC */ 5239 FETCH(r0, 1) @ r0<- CCBB 5240 mov r9, rINST, lsr #8 @ r9<- AA 5241 mov r3, r0, lsr #8 @ r3<- CC 5242 and r2, r0, #255 @ r2<- BB 5243 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5244 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5245 fldd d1, [r3] @ d1<- vCC 5246 fldd d0, [r2] @ d0<- vBB 5247 5248 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5249 fmuld d2, d0, d1 @ s2<- op 5250 GET_INST_OPCODE(ip) @ extract opcode from rINST 5251 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5252 fstd d2, [r9] @ vAA<- d2 5253 GOTO_OPCODE(ip) @ jump to next instruction 5254 5255 5256/* ------------------------------ */ 5257 .balign 64 5258.L_OP_DIV_DOUBLE: /* 0xae */ 5259/* File: arm-vfp/OP_DIV_DOUBLE.S */ 5260/* File: arm-vfp/fbinopWide.S */ 5261 /* 5262 * Generic 64-bit double-precision floating point binary operation. 5263 * Provide an "instr" line that specifies an instruction that performs 5264 * "d2 = d0 op d1". 5265 * 5266 * for: add-double, sub-double, mul-double, div-double 5267 */ 5268 /* doubleop vAA, vBB, vCC */ 5269 FETCH(r0, 1) @ r0<- CCBB 5270 mov r9, rINST, lsr #8 @ r9<- AA 5271 mov r3, r0, lsr #8 @ r3<- CC 5272 and r2, r0, #255 @ r2<- BB 5273 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vCC 5274 VREG_INDEX_TO_ADDR(r2, r2) @ r2<- &vBB 5275 fldd d1, [r3] @ d1<- vCC 5276 fldd d0, [r2] @ d0<- vBB 5277 5278 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5279 fdivd d2, d0, d1 @ s2<- op 5280 GET_INST_OPCODE(ip) @ extract opcode from rINST 5281 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vAA 5282 fstd d2, [r9] @ vAA<- d2 5283 GOTO_OPCODE(ip) @ jump to next instruction 5284 5285 5286/* ------------------------------ */ 5287 .balign 64 5288.L_OP_REM_DOUBLE: /* 0xaf */ 5289/* File: armv5te/OP_REM_DOUBLE.S */ 5290/* EABI doesn't define a double remainder function, but libm does */ 5291/* File: armv5te/binopWide.S */ 5292 /* 5293 * Generic 64-bit binary operation. Provide an "instr" line that 5294 * specifies an instruction that performs "result = r0-r1 op r2-r3". 5295 * This could be an ARM instruction or a function call. (If the result 5296 * comes back in a register other than r0, you can override "result".) 5297 * 5298 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5299 * vCC (r1). Useful for integer division and modulus. 5300 * 5301 * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 5302 * xor-long, add-double, sub-double, mul-double, div-double, 5303 * rem-double 5304 * 5305 * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 5306 */ 5307 /* binop vAA, vBB, vCC */ 5308 FETCH(r0, 1) @ r0<- CCBB 5309 mov r9, rINST, lsr #8 @ r9<- AA 5310 and r2, r0, #255 @ r2<- BB 5311 mov r3, r0, lsr #8 @ r3<- CC 5312 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 5313 add r2, rFP, r2, lsl #2 @ r2<- &fp[BB] 5314 add r3, rFP, r3, lsl #2 @ r3<- &fp[CC] 5315 ldmia r2, {r0-r1} @ r0/r1<- vBB/vBB+1 5316 ldmia r3, {r2-r3} @ r2/r3<- vCC/vCC+1 5317 .if 0 5318 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5319 beq common_errDivideByZero 5320 .endif 5321 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 5322 5323 @ optional op; may set condition codes 5324 bl fmod @ result<- op, r0-r3 changed 5325 GET_INST_OPCODE(ip) @ extract opcode from rINST 5326 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5327 GOTO_OPCODE(ip) @ jump to next instruction 5328 /* 14-17 instructions */ 5329 5330 5331 5332/* ------------------------------ */ 5333 .balign 64 5334.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 5335/* File: armv5te/OP_ADD_INT_2ADDR.S */ 5336/* File: armv5te/binop2addr.S */ 5337 /* 5338 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5339 * that specifies an instruction that performs "result = r0 op r1". 5340 * This could be an ARM instruction or a function call. (If the result 5341 * comes back in a register other than r0, you can override "result".) 5342 * 5343 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5344 * vCC (r1). Useful for integer division and modulus. 5345 * 5346 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5347 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5348 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5349 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5350 */ 5351 /* binop/2addr vA, vB */ 5352 mov r9, rINST, lsr #8 @ r9<- A+ 5353 mov r3, rINST, lsr #12 @ r3<- B 5354 and r9, r9, #15 5355 GET_VREG(r1, r3) @ r1<- vB 5356 GET_VREG(r0, r9) @ r0<- vA 5357 .if 0 5358 cmp r1, #0 @ is second operand zero? 5359 beq common_errDivideByZero 5360 .endif 5361 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5362 5363 @ optional op; may set condition codes 5364 add r0, r0, r1 @ r0<- op, r0-r3 changed 5365 GET_INST_OPCODE(ip) @ extract opcode from rINST 5366 SET_VREG(r0, r9) @ vAA<- r0 5367 GOTO_OPCODE(ip) @ jump to next instruction 5368 /* 10-13 instructions */ 5369 5370 5371 5372/* ------------------------------ */ 5373 .balign 64 5374.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 5375/* File: armv5te/OP_SUB_INT_2ADDR.S */ 5376/* File: armv5te/binop2addr.S */ 5377 /* 5378 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5379 * that specifies an instruction that performs "result = r0 op r1". 5380 * This could be an ARM instruction or a function call. (If the result 5381 * comes back in a register other than r0, you can override "result".) 5382 * 5383 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5384 * vCC (r1). Useful for integer division and modulus. 5385 * 5386 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5387 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5388 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5389 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5390 */ 5391 /* binop/2addr vA, vB */ 5392 mov r9, rINST, lsr #8 @ r9<- A+ 5393 mov r3, rINST, lsr #12 @ r3<- B 5394 and r9, r9, #15 5395 GET_VREG(r1, r3) @ r1<- vB 5396 GET_VREG(r0, r9) @ r0<- vA 5397 .if 0 5398 cmp r1, #0 @ is second operand zero? 5399 beq common_errDivideByZero 5400 .endif 5401 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5402 5403 @ optional op; may set condition codes 5404 sub r0, r0, r1 @ r0<- op, r0-r3 changed 5405 GET_INST_OPCODE(ip) @ extract opcode from rINST 5406 SET_VREG(r0, r9) @ vAA<- r0 5407 GOTO_OPCODE(ip) @ jump to next instruction 5408 /* 10-13 instructions */ 5409 5410 5411 5412/* ------------------------------ */ 5413 .balign 64 5414.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 5415/* File: armv5te/OP_MUL_INT_2ADDR.S */ 5416/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 5417/* File: armv5te/binop2addr.S */ 5418 /* 5419 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5420 * that specifies an instruction that performs "result = r0 op r1". 5421 * This could be an ARM instruction or a function call. (If the result 5422 * comes back in a register other than r0, you can override "result".) 5423 * 5424 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5425 * vCC (r1). Useful for integer division and modulus. 5426 * 5427 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5428 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5429 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5430 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5431 */ 5432 /* binop/2addr vA, vB */ 5433 mov r9, rINST, lsr #8 @ r9<- A+ 5434 mov r3, rINST, lsr #12 @ r3<- B 5435 and r9, r9, #15 5436 GET_VREG(r1, r3) @ r1<- vB 5437 GET_VREG(r0, r9) @ r0<- vA 5438 .if 0 5439 cmp r1, #0 @ is second operand zero? 5440 beq common_errDivideByZero 5441 .endif 5442 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5443 5444 @ optional op; may set condition codes 5445 mul r0, r1, r0 @ r0<- op, r0-r3 changed 5446 GET_INST_OPCODE(ip) @ extract opcode from rINST 5447 SET_VREG(r0, r9) @ vAA<- r0 5448 GOTO_OPCODE(ip) @ jump to next instruction 5449 /* 10-13 instructions */ 5450 5451 5452 5453/* ------------------------------ */ 5454 .balign 64 5455.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 5456/* File: armv5te/OP_DIV_INT_2ADDR.S */ 5457/* File: armv5te/binop2addr.S */ 5458 /* 5459 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5460 * that specifies an instruction that performs "result = r0 op r1". 5461 * This could be an ARM instruction or a function call. (If the result 5462 * comes back in a register other than r0, you can override "result".) 5463 * 5464 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5465 * vCC (r1). Useful for integer division and modulus. 5466 * 5467 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5468 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5469 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5470 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5471 */ 5472 /* binop/2addr vA, vB */ 5473 mov r9, rINST, lsr #8 @ r9<- A+ 5474 mov r3, rINST, lsr #12 @ r3<- B 5475 and r9, r9, #15 5476 GET_VREG(r1, r3) @ r1<- vB 5477 GET_VREG(r0, r9) @ r0<- vA 5478 .if 1 5479 cmp r1, #0 @ is second operand zero? 5480 beq common_errDivideByZero 5481 .endif 5482 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5483 5484 @ optional op; may set condition codes 5485 bl __aeabi_idiv @ r0<- op, r0-r3 changed 5486 GET_INST_OPCODE(ip) @ extract opcode from rINST 5487 SET_VREG(r0, r9) @ vAA<- r0 5488 GOTO_OPCODE(ip) @ jump to next instruction 5489 /* 10-13 instructions */ 5490 5491 5492 5493/* ------------------------------ */ 5494 .balign 64 5495.L_OP_REM_INT_2ADDR: /* 0xb4 */ 5496/* File: armv5te/OP_REM_INT_2ADDR.S */ 5497/* idivmod returns quotient in r0 and remainder in r1 */ 5498/* File: armv5te/binop2addr.S */ 5499 /* 5500 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5501 * that specifies an instruction that performs "result = r0 op r1". 5502 * This could be an ARM instruction or a function call. (If the result 5503 * comes back in a register other than r0, you can override "result".) 5504 * 5505 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5506 * vCC (r1). Useful for integer division and modulus. 5507 * 5508 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5509 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5510 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5511 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5512 */ 5513 /* binop/2addr vA, vB */ 5514 mov r9, rINST, lsr #8 @ r9<- A+ 5515 mov r3, rINST, lsr #12 @ r3<- B 5516 and r9, r9, #15 5517 GET_VREG(r1, r3) @ r1<- vB 5518 GET_VREG(r0, r9) @ r0<- vA 5519 .if 1 5520 cmp r1, #0 @ is second operand zero? 5521 beq common_errDivideByZero 5522 .endif 5523 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5524 5525 @ optional op; may set condition codes 5526 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 5527 GET_INST_OPCODE(ip) @ extract opcode from rINST 5528 SET_VREG(r1, r9) @ vAA<- r1 5529 GOTO_OPCODE(ip) @ jump to next instruction 5530 /* 10-13 instructions */ 5531 5532 5533 5534/* ------------------------------ */ 5535 .balign 64 5536.L_OP_AND_INT_2ADDR: /* 0xb5 */ 5537/* File: armv5te/OP_AND_INT_2ADDR.S */ 5538/* File: armv5te/binop2addr.S */ 5539 /* 5540 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5541 * that specifies an instruction that performs "result = r0 op r1". 5542 * This could be an ARM instruction or a function call. (If the result 5543 * comes back in a register other than r0, you can override "result".) 5544 * 5545 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5546 * vCC (r1). Useful for integer division and modulus. 5547 * 5548 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5549 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5550 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5551 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5552 */ 5553 /* binop/2addr vA, vB */ 5554 mov r9, rINST, lsr #8 @ r9<- A+ 5555 mov r3, rINST, lsr #12 @ r3<- B 5556 and r9, r9, #15 5557 GET_VREG(r1, r3) @ r1<- vB 5558 GET_VREG(r0, r9) @ r0<- vA 5559 .if 0 5560 cmp r1, #0 @ is second operand zero? 5561 beq common_errDivideByZero 5562 .endif 5563 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5564 5565 @ optional op; may set condition codes 5566 and r0, r0, r1 @ r0<- op, r0-r3 changed 5567 GET_INST_OPCODE(ip) @ extract opcode from rINST 5568 SET_VREG(r0, r9) @ vAA<- r0 5569 GOTO_OPCODE(ip) @ jump to next instruction 5570 /* 10-13 instructions */ 5571 5572 5573 5574/* ------------------------------ */ 5575 .balign 64 5576.L_OP_OR_INT_2ADDR: /* 0xb6 */ 5577/* File: armv5te/OP_OR_INT_2ADDR.S */ 5578/* File: armv5te/binop2addr.S */ 5579 /* 5580 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5581 * that specifies an instruction that performs "result = r0 op r1". 5582 * This could be an ARM instruction or a function call. (If the result 5583 * comes back in a register other than r0, you can override "result".) 5584 * 5585 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5586 * vCC (r1). Useful for integer division and modulus. 5587 * 5588 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5589 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5590 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5591 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5592 */ 5593 /* binop/2addr vA, vB */ 5594 mov r9, rINST, lsr #8 @ r9<- A+ 5595 mov r3, rINST, lsr #12 @ r3<- B 5596 and r9, r9, #15 5597 GET_VREG(r1, r3) @ r1<- vB 5598 GET_VREG(r0, r9) @ r0<- vA 5599 .if 0 5600 cmp r1, #0 @ is second operand zero? 5601 beq common_errDivideByZero 5602 .endif 5603 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5604 5605 @ optional op; may set condition codes 5606 orr r0, r0, r1 @ r0<- op, r0-r3 changed 5607 GET_INST_OPCODE(ip) @ extract opcode from rINST 5608 SET_VREG(r0, r9) @ vAA<- r0 5609 GOTO_OPCODE(ip) @ jump to next instruction 5610 /* 10-13 instructions */ 5611 5612 5613 5614/* ------------------------------ */ 5615 .balign 64 5616.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 5617/* File: armv5te/OP_XOR_INT_2ADDR.S */ 5618/* File: armv5te/binop2addr.S */ 5619 /* 5620 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5621 * that specifies an instruction that performs "result = r0 op r1". 5622 * This could be an ARM instruction or a function call. (If the result 5623 * comes back in a register other than r0, you can override "result".) 5624 * 5625 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5626 * vCC (r1). Useful for integer division and modulus. 5627 * 5628 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5629 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5630 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5631 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5632 */ 5633 /* binop/2addr vA, vB */ 5634 mov r9, rINST, lsr #8 @ r9<- A+ 5635 mov r3, rINST, lsr #12 @ r3<- B 5636 and r9, r9, #15 5637 GET_VREG(r1, r3) @ r1<- vB 5638 GET_VREG(r0, r9) @ r0<- vA 5639 .if 0 5640 cmp r1, #0 @ is second operand zero? 5641 beq common_errDivideByZero 5642 .endif 5643 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5644 5645 @ optional op; may set condition codes 5646 eor r0, r0, r1 @ r0<- op, r0-r3 changed 5647 GET_INST_OPCODE(ip) @ extract opcode from rINST 5648 SET_VREG(r0, r9) @ vAA<- r0 5649 GOTO_OPCODE(ip) @ jump to next instruction 5650 /* 10-13 instructions */ 5651 5652 5653 5654/* ------------------------------ */ 5655 .balign 64 5656.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 5657/* File: armv5te/OP_SHL_INT_2ADDR.S */ 5658/* File: armv5te/binop2addr.S */ 5659 /* 5660 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5661 * that specifies an instruction that performs "result = r0 op r1". 5662 * This could be an ARM instruction or a function call. (If the result 5663 * comes back in a register other than r0, you can override "result".) 5664 * 5665 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5666 * vCC (r1). Useful for integer division and modulus. 5667 * 5668 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5669 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5670 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5671 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5672 */ 5673 /* binop/2addr vA, vB */ 5674 mov r9, rINST, lsr #8 @ r9<- A+ 5675 mov r3, rINST, lsr #12 @ r3<- B 5676 and r9, r9, #15 5677 GET_VREG(r1, r3) @ r1<- vB 5678 GET_VREG(r0, r9) @ r0<- vA 5679 .if 0 5680 cmp r1, #0 @ is second operand zero? 5681 beq common_errDivideByZero 5682 .endif 5683 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5684 5685 and r1, r1, #31 @ optional op; may set condition codes 5686 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 5687 GET_INST_OPCODE(ip) @ extract opcode from rINST 5688 SET_VREG(r0, r9) @ vAA<- r0 5689 GOTO_OPCODE(ip) @ jump to next instruction 5690 /* 10-13 instructions */ 5691 5692 5693 5694/* ------------------------------ */ 5695 .balign 64 5696.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 5697/* File: armv5te/OP_SHR_INT_2ADDR.S */ 5698/* File: armv5te/binop2addr.S */ 5699 /* 5700 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5701 * that specifies an instruction that performs "result = r0 op r1". 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-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5709 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5710 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5711 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5712 */ 5713 /* binop/2addr vA, vB */ 5714 mov r9, rINST, lsr #8 @ r9<- A+ 5715 mov r3, rINST, lsr #12 @ r3<- B 5716 and r9, r9, #15 5717 GET_VREG(r1, r3) @ r1<- vB 5718 GET_VREG(r0, r9) @ r0<- vA 5719 .if 0 5720 cmp r1, #0 @ is second operand zero? 5721 beq common_errDivideByZero 5722 .endif 5723 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5724 5725 and r1, r1, #31 @ optional op; may set condition codes 5726 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 5727 GET_INST_OPCODE(ip) @ extract opcode from rINST 5728 SET_VREG(r0, r9) @ vAA<- r0 5729 GOTO_OPCODE(ip) @ jump to next instruction 5730 /* 10-13 instructions */ 5731 5732 5733 5734/* ------------------------------ */ 5735 .balign 64 5736.L_OP_USHR_INT_2ADDR: /* 0xba */ 5737/* File: armv5te/OP_USHR_INT_2ADDR.S */ 5738/* File: armv5te/binop2addr.S */ 5739 /* 5740 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 5741 * that specifies an instruction that performs "result = r0 op r1". 5742 * This could be an ARM instruction or a function call. (If the result 5743 * comes back in a register other than r0, you can override "result".) 5744 * 5745 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5746 * vCC (r1). Useful for integer division and modulus. 5747 * 5748 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 5749 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 5750 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 5751 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 5752 */ 5753 /* binop/2addr vA, vB */ 5754 mov r9, rINST, lsr #8 @ r9<- A+ 5755 mov r3, rINST, lsr #12 @ r3<- B 5756 and r9, r9, #15 5757 GET_VREG(r1, r3) @ r1<- vB 5758 GET_VREG(r0, r9) @ r0<- vA 5759 .if 0 5760 cmp r1, #0 @ is second operand zero? 5761 beq common_errDivideByZero 5762 .endif 5763 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5764 5765 and r1, r1, #31 @ optional op; may set condition codes 5766 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 5767 GET_INST_OPCODE(ip) @ extract opcode from rINST 5768 SET_VREG(r0, r9) @ vAA<- r0 5769 GOTO_OPCODE(ip) @ jump to next instruction 5770 /* 10-13 instructions */ 5771 5772 5773 5774/* ------------------------------ */ 5775 .balign 64 5776.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 5777/* File: armv5te/OP_ADD_LONG_2ADDR.S */ 5778/* File: armv5te/binopWide2addr.S */ 5779 /* 5780 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5781 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5782 * This could be an ARM instruction or a function call. (If the result 5783 * comes back in a register other than r0, you can override "result".) 5784 * 5785 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5786 * vCC (r1). Useful for integer division and modulus. 5787 * 5788 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5789 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5790 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5791 * rem-double/2addr 5792 */ 5793 /* binop/2addr vA, vB */ 5794 mov r9, rINST, lsr #8 @ r9<- A+ 5795 mov r1, rINST, lsr #12 @ r1<- B 5796 and r9, r9, #15 5797 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5798 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5799 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5800 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5801 .if 0 5802 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5803 beq common_errDivideByZero 5804 .endif 5805 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5806 5807 adds r0, r0, r2 @ optional op; may set condition codes 5808 adc r1, r1, r3 @ result<- op, r0-r3 changed 5809 GET_INST_OPCODE(ip) @ extract opcode from rINST 5810 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5811 GOTO_OPCODE(ip) @ jump to next instruction 5812 /* 12-15 instructions */ 5813 5814 5815 5816/* ------------------------------ */ 5817 .balign 64 5818.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 5819/* File: armv5te/OP_SUB_LONG_2ADDR.S */ 5820/* File: armv5te/binopWide2addr.S */ 5821 /* 5822 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5823 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5824 * This could be an ARM instruction or a function call. (If the result 5825 * comes back in a register other than r0, you can override "result".) 5826 * 5827 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5828 * vCC (r1). Useful for integer division and modulus. 5829 * 5830 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5831 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5832 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5833 * rem-double/2addr 5834 */ 5835 /* binop/2addr vA, vB */ 5836 mov r9, rINST, lsr #8 @ r9<- A+ 5837 mov r1, rINST, lsr #12 @ r1<- B 5838 and r9, r9, #15 5839 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5840 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5841 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5842 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5843 .if 0 5844 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5845 beq common_errDivideByZero 5846 .endif 5847 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5848 5849 subs r0, r0, r2 @ optional op; may set condition codes 5850 sbc r1, r1, r3 @ result<- op, r0-r3 changed 5851 GET_INST_OPCODE(ip) @ extract opcode from rINST 5852 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 5853 GOTO_OPCODE(ip) @ jump to next instruction 5854 /* 12-15 instructions */ 5855 5856 5857 5858/* ------------------------------ */ 5859 .balign 64 5860.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 5861/* File: armv5te/OP_MUL_LONG_2ADDR.S */ 5862 /* 5863 * Signed 64-bit integer multiply, "/2addr" version. 5864 * 5865 * See OP_MUL_LONG for an explanation. 5866 * 5867 * We get a little tight on registers, so to avoid looking up &fp[A] 5868 * again we stuff it into rINST. 5869 */ 5870 /* mul-long/2addr vA, vB */ 5871 mov r9, rINST, lsr #8 @ r9<- A+ 5872 mov r1, rINST, lsr #12 @ r1<- B 5873 and r9, r9, #15 5874 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5875 add rINST, rFP, r9, lsl #2 @ rINST<- &fp[A] 5876 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5877 ldmia rINST, {r0-r1} @ r0/r1<- vAA/vAA+1 5878 mul ip, r2, r1 @ ip<- ZxW 5879 umull r9, r10, r2, r0 @ r9/r10 <- ZxX 5880 mla r2, r0, r3, ip @ r2<- YxX + (ZxW) 5881 mov r0, rINST @ r0<- &fp[A] (free up rINST) 5882 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5883 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX)) 5884 GET_INST_OPCODE(ip) @ extract opcode from rINST 5885 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 5886 GOTO_OPCODE(ip) @ jump to next instruction 5887 5888 5889/* ------------------------------ */ 5890 .balign 64 5891.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 5892/* File: armv5te/OP_DIV_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 1 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 @ optional op; may set condition codes 5923 bl __aeabi_ldivmod @ 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/* ------------------------------ */ 5932 .balign 64 5933.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5934/* File: armv5te/OP_REM_LONG_2ADDR.S */ 5935/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 5936/* File: armv5te/binopWide2addr.S */ 5937 /* 5938 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5939 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5940 * This could be an ARM instruction or a function call. (If the result 5941 * comes back in a register other than r0, you can override "result".) 5942 * 5943 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5944 * vCC (r1). Useful for integer division and modulus. 5945 * 5946 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5947 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5948 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5949 * rem-double/2addr 5950 */ 5951 /* binop/2addr vA, vB */ 5952 mov r9, rINST, lsr #8 @ r9<- A+ 5953 mov r1, rINST, lsr #12 @ r1<- B 5954 and r9, r9, #15 5955 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5956 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5957 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 5958 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 5959 .if 1 5960 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 5961 beq common_errDivideByZero 5962 .endif 5963 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 5964 5965 @ optional op; may set condition codes 5966 bl __aeabi_ldivmod @ result<- op, r0-r3 changed 5967 GET_INST_OPCODE(ip) @ extract opcode from rINST 5968 stmia r9, {r2,r3} @ vAA/vAA+1<- r2/r3 5969 GOTO_OPCODE(ip) @ jump to next instruction 5970 /* 12-15 instructions */ 5971 5972 5973 5974/* ------------------------------ */ 5975 .balign 64 5976.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 5977/* File: armv5te/OP_AND_LONG_2ADDR.S */ 5978/* File: armv5te/binopWide2addr.S */ 5979 /* 5980 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 5981 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 5982 * This could be an ARM instruction or a function call. (If the result 5983 * comes back in a register other than r0, you can override "result".) 5984 * 5985 * If "chkzero" is set to 1, we perform a divide-by-zero check on 5986 * vCC (r1). Useful for integer division and modulus. 5987 * 5988 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 5989 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 5990 * sub-double/2addr, mul-double/2addr, div-double/2addr, 5991 * rem-double/2addr 5992 */ 5993 /* binop/2addr vA, vB */ 5994 mov r9, rINST, lsr #8 @ r9<- A+ 5995 mov r1, rINST, lsr #12 @ r1<- B 5996 and r9, r9, #15 5997 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 5998 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 5999 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6000 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6001 .if 0 6002 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6003 beq common_errDivideByZero 6004 .endif 6005 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6006 6007 and r0, r0, r2 @ optional op; may set condition codes 6008 and r1, r1, r3 @ result<- op, r0-r3 changed 6009 GET_INST_OPCODE(ip) @ extract opcode from rINST 6010 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6011 GOTO_OPCODE(ip) @ jump to next instruction 6012 /* 12-15 instructions */ 6013 6014 6015 6016/* ------------------------------ */ 6017 .balign 64 6018.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 6019/* File: armv5te/OP_OR_LONG_2ADDR.S */ 6020/* File: armv5te/binopWide2addr.S */ 6021 /* 6022 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6023 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6024 * This could be an ARM instruction or a function call. (If the result 6025 * comes back in a register other than r0, you can override "result".) 6026 * 6027 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6028 * vCC (r1). Useful for integer division and modulus. 6029 * 6030 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6031 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6032 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6033 * rem-double/2addr 6034 */ 6035 /* binop/2addr vA, vB */ 6036 mov r9, rINST, lsr #8 @ r9<- A+ 6037 mov r1, rINST, lsr #12 @ r1<- B 6038 and r9, r9, #15 6039 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6040 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6041 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6042 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6043 .if 0 6044 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6045 beq common_errDivideByZero 6046 .endif 6047 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6048 6049 orr r0, r0, r2 @ optional op; may set condition codes 6050 orr r1, r1, r3 @ result<- op, r0-r3 changed 6051 GET_INST_OPCODE(ip) @ extract opcode from rINST 6052 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6053 GOTO_OPCODE(ip) @ jump to next instruction 6054 /* 12-15 instructions */ 6055 6056 6057 6058/* ------------------------------ */ 6059 .balign 64 6060.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 6061/* File: armv5te/OP_XOR_LONG_2ADDR.S */ 6062/* File: armv5te/binopWide2addr.S */ 6063 /* 6064 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6065 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6066 * This could be an ARM instruction or a function call. (If the result 6067 * comes back in a register other than r0, you can override "result".) 6068 * 6069 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6070 * vCC (r1). Useful for integer division and modulus. 6071 * 6072 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6073 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6074 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6075 * rem-double/2addr 6076 */ 6077 /* binop/2addr vA, vB */ 6078 mov r9, rINST, lsr #8 @ r9<- A+ 6079 mov r1, rINST, lsr #12 @ r1<- B 6080 and r9, r9, #15 6081 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6082 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6083 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6084 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6085 .if 0 6086 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6087 beq common_errDivideByZero 6088 .endif 6089 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6090 6091 eor r0, r0, r2 @ optional op; may set condition codes 6092 eor r1, r1, r3 @ result<- op, r0-r3 changed 6093 GET_INST_OPCODE(ip) @ extract opcode from rINST 6094 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6095 GOTO_OPCODE(ip) @ jump to next instruction 6096 /* 12-15 instructions */ 6097 6098 6099 6100/* ------------------------------ */ 6101 .balign 64 6102.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 6103/* File: armv5te/OP_SHL_LONG_2ADDR.S */ 6104 /* 6105 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6106 * 32-bit shift distance. 6107 */ 6108 /* shl-long/2addr vA, vB */ 6109 mov r9, rINST, lsr #8 @ r9<- A+ 6110 mov r3, rINST, lsr #12 @ r3<- B 6111 and r9, r9, #15 6112 GET_VREG(r2, r3) @ r2<- vB 6113 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6114 and r2, r2, #63 @ r2<- r2 & 0x3f 6115 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6116 6117 mov r1, r1, asl r2 @ r1<- r1 << r2 6118 rsb r3, r2, #32 @ r3<- 32 - r2 6119 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 6120 subs ip, r2, #32 @ ip<- r2 - 32 6121 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6122 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 6123 mov r0, r0, asl r2 @ r0<- r0 << r2 6124 b .LOP_SHL_LONG_2ADDR_finish 6125 6126/* ------------------------------ */ 6127 .balign 64 6128.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 6129/* File: armv5te/OP_SHR_LONG_2ADDR.S */ 6130 /* 6131 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6132 * 32-bit shift distance. 6133 */ 6134 /* shr-long/2addr vA, vB */ 6135 mov r9, rINST, lsr #8 @ r9<- A+ 6136 mov r3, rINST, lsr #12 @ r3<- B 6137 and r9, r9, #15 6138 GET_VREG(r2, r3) @ r2<- vB 6139 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6140 and r2, r2, #63 @ r2<- r2 & 0x3f 6141 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6142 6143 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6144 rsb r3, r2, #32 @ r3<- 32 - r2 6145 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6146 subs ip, r2, #32 @ ip<- r2 - 32 6147 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6148 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 6149 mov r1, r1, asr r2 @ r1<- r1 >> r2 6150 b .LOP_SHR_LONG_2ADDR_finish 6151 6152/* ------------------------------ */ 6153 .balign 64 6154.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 6155/* File: armv5te/OP_USHR_LONG_2ADDR.S */ 6156 /* 6157 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 6158 * 32-bit shift distance. 6159 */ 6160 /* ushr-long/2addr vA, vB */ 6161 mov r9, rINST, lsr #8 @ r9<- A+ 6162 mov r3, rINST, lsr #12 @ r3<- B 6163 and r9, r9, #15 6164 GET_VREG(r2, r3) @ r2<- vB 6165 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6166 and r2, r2, #63 @ r2<- r2 & 0x3f 6167 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6168 6169 mov r0, r0, lsr r2 @ r0<- r2 >> r2 6170 rsb r3, r2, #32 @ r3<- 32 - r2 6171 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2)) 6172 subs ip, r2, #32 @ ip<- r2 - 32 6173 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6174 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 6175 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 6176 b .LOP_USHR_LONG_2ADDR_finish 6177 6178/* ------------------------------ */ 6179 .balign 64 6180.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 6181/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */ 6182/* File: arm-vfp/fbinop2addr.S */ 6183 /* 6184 * Generic 32-bit floating point "/2addr" binary operation. Provide 6185 * an "instr" line that specifies an instruction that performs 6186 * "s2 = s0 op s1". 6187 * 6188 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6189 */ 6190 /* binop/2addr vA, vB */ 6191 mov r3, rINST, lsr #12 @ r3<- B 6192 mov r9, rINST, lsr #8 @ r9<- A+ 6193 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6194 and r9, r9, #15 @ r9<- A 6195 flds s1, [r3] @ s1<- vB 6196 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6197 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6198 flds s0, [r9] @ s0<- vA 6199 6200 fadds s2, s0, s1 @ s2<- op 6201 GET_INST_OPCODE(ip) @ extract opcode from rINST 6202 fsts s2, [r9] @ vAA<- s2 6203 GOTO_OPCODE(ip) @ jump to next instruction 6204 6205 6206/* ------------------------------ */ 6207 .balign 64 6208.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 6209/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */ 6210/* File: arm-vfp/fbinop2addr.S */ 6211 /* 6212 * Generic 32-bit floating point "/2addr" binary operation. Provide 6213 * an "instr" line that specifies an instruction that performs 6214 * "s2 = s0 op s1". 6215 * 6216 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6217 */ 6218 /* binop/2addr vA, vB */ 6219 mov r3, rINST, lsr #12 @ r3<- B 6220 mov r9, rINST, lsr #8 @ r9<- A+ 6221 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6222 and r9, r9, #15 @ r9<- A 6223 flds s1, [r3] @ s1<- vB 6224 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6225 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6226 flds s0, [r9] @ s0<- vA 6227 6228 fsubs s2, s0, s1 @ s2<- op 6229 GET_INST_OPCODE(ip) @ extract opcode from rINST 6230 fsts s2, [r9] @ vAA<- s2 6231 GOTO_OPCODE(ip) @ jump to next instruction 6232 6233 6234/* ------------------------------ */ 6235 .balign 64 6236.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 6237/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */ 6238/* File: arm-vfp/fbinop2addr.S */ 6239 /* 6240 * Generic 32-bit floating point "/2addr" binary operation. Provide 6241 * an "instr" line that specifies an instruction that performs 6242 * "s2 = s0 op s1". 6243 * 6244 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6245 */ 6246 /* binop/2addr vA, vB */ 6247 mov r3, rINST, lsr #12 @ r3<- B 6248 mov r9, rINST, lsr #8 @ r9<- A+ 6249 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6250 and r9, r9, #15 @ r9<- A 6251 flds s1, [r3] @ s1<- vB 6252 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6253 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6254 flds s0, [r9] @ s0<- vA 6255 6256 fmuls s2, s0, s1 @ s2<- op 6257 GET_INST_OPCODE(ip) @ extract opcode from rINST 6258 fsts s2, [r9] @ vAA<- s2 6259 GOTO_OPCODE(ip) @ jump to next instruction 6260 6261 6262/* ------------------------------ */ 6263 .balign 64 6264.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 6265/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */ 6266/* File: arm-vfp/fbinop2addr.S */ 6267 /* 6268 * Generic 32-bit floating point "/2addr" binary operation. Provide 6269 * an "instr" line that specifies an instruction that performs 6270 * "s2 = s0 op s1". 6271 * 6272 * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr 6273 */ 6274 /* binop/2addr vA, vB */ 6275 mov r3, rINST, lsr #12 @ r3<- B 6276 mov r9, rINST, lsr #8 @ r9<- A+ 6277 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6278 and r9, r9, #15 @ r9<- A 6279 flds s1, [r3] @ s1<- vB 6280 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6281 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6282 flds s0, [r9] @ s0<- vA 6283 6284 fdivs s2, s0, s1 @ s2<- op 6285 GET_INST_OPCODE(ip) @ extract opcode from rINST 6286 fsts s2, [r9] @ vAA<- s2 6287 GOTO_OPCODE(ip) @ jump to next instruction 6288 6289 6290/* ------------------------------ */ 6291 .balign 64 6292.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 6293/* File: armv5te/OP_REM_FLOAT_2ADDR.S */ 6294/* EABI doesn't define a float remainder function, but libm does */ 6295/* File: armv5te/binop2addr.S */ 6296 /* 6297 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 6298 * that specifies an instruction that performs "result = r0 op r1". 6299 * This could be an ARM instruction or a function call. (If the result 6300 * comes back in a register other than r0, you can override "result".) 6301 * 6302 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6303 * vCC (r1). Useful for integer division and modulus. 6304 * 6305 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 6306 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 6307 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 6308 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 6309 */ 6310 /* binop/2addr vA, vB */ 6311 mov r9, rINST, lsr #8 @ r9<- A+ 6312 mov r3, rINST, lsr #12 @ r3<- B 6313 and r9, r9, #15 6314 GET_VREG(r1, r3) @ r1<- vB 6315 GET_VREG(r0, r9) @ r0<- vA 6316 .if 0 6317 cmp r1, #0 @ is second operand zero? 6318 beq common_errDivideByZero 6319 .endif 6320 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6321 6322 @ optional op; may set condition codes 6323 bl fmodf @ r0<- op, r0-r3 changed 6324 GET_INST_OPCODE(ip) @ extract opcode from rINST 6325 SET_VREG(r0, r9) @ vAA<- r0 6326 GOTO_OPCODE(ip) @ jump to next instruction 6327 /* 10-13 instructions */ 6328 6329 6330 6331/* ------------------------------ */ 6332 .balign 64 6333.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 6334/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */ 6335/* File: arm-vfp/fbinopWide2addr.S */ 6336 /* 6337 * Generic 64-bit floating point "/2addr" binary operation. Provide 6338 * an "instr" line that specifies an instruction that performs 6339 * "d2 = d0 op d1". 6340 * 6341 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6342 * div-double/2addr 6343 */ 6344 /* binop/2addr vA, vB */ 6345 mov r3, rINST, lsr #12 @ r3<- B 6346 mov r9, rINST, lsr #8 @ r9<- A+ 6347 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6348 and r9, r9, #15 @ r9<- A 6349 fldd d1, [r3] @ d1<- vB 6350 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6351 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6352 fldd d0, [r9] @ d0<- vA 6353 6354 faddd d2, d0, d1 @ d2<- op 6355 GET_INST_OPCODE(ip) @ extract opcode from rINST 6356 fstd d2, [r9] @ vAA<- d2 6357 GOTO_OPCODE(ip) @ jump to next instruction 6358 6359 6360/* ------------------------------ */ 6361 .balign 64 6362.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 6363/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */ 6364/* File: arm-vfp/fbinopWide2addr.S */ 6365 /* 6366 * Generic 64-bit floating point "/2addr" binary operation. Provide 6367 * an "instr" line that specifies an instruction that performs 6368 * "d2 = d0 op d1". 6369 * 6370 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6371 * div-double/2addr 6372 */ 6373 /* binop/2addr vA, vB */ 6374 mov r3, rINST, lsr #12 @ r3<- B 6375 mov r9, rINST, lsr #8 @ r9<- A+ 6376 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6377 and r9, r9, #15 @ r9<- A 6378 fldd d1, [r3] @ d1<- vB 6379 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6380 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6381 fldd d0, [r9] @ d0<- vA 6382 6383 fsubd d2, d0, d1 @ d2<- op 6384 GET_INST_OPCODE(ip) @ extract opcode from rINST 6385 fstd d2, [r9] @ vAA<- d2 6386 GOTO_OPCODE(ip) @ jump to next instruction 6387 6388 6389/* ------------------------------ */ 6390 .balign 64 6391.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 6392/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */ 6393/* File: arm-vfp/fbinopWide2addr.S */ 6394 /* 6395 * Generic 64-bit floating point "/2addr" binary operation. Provide 6396 * an "instr" line that specifies an instruction that performs 6397 * "d2 = d0 op d1". 6398 * 6399 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6400 * div-double/2addr 6401 */ 6402 /* binop/2addr vA, vB */ 6403 mov r3, rINST, lsr #12 @ r3<- B 6404 mov r9, rINST, lsr #8 @ r9<- A+ 6405 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6406 and r9, r9, #15 @ r9<- A 6407 fldd d1, [r3] @ d1<- vB 6408 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6409 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6410 fldd d0, [r9] @ d0<- vA 6411 6412 fmuld d2, d0, d1 @ d2<- op 6413 GET_INST_OPCODE(ip) @ extract opcode from rINST 6414 fstd d2, [r9] @ vAA<- d2 6415 GOTO_OPCODE(ip) @ jump to next instruction 6416 6417 6418/* ------------------------------ */ 6419 .balign 64 6420.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 6421/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */ 6422/* File: arm-vfp/fbinopWide2addr.S */ 6423 /* 6424 * Generic 64-bit floating point "/2addr" binary operation. Provide 6425 * an "instr" line that specifies an instruction that performs 6426 * "d2 = d0 op d1". 6427 * 6428 * For: add-double/2addr, sub-double/2addr, mul-double/2addr, 6429 * div-double/2addr 6430 */ 6431 /* binop/2addr vA, vB */ 6432 mov r3, rINST, lsr #12 @ r3<- B 6433 mov r9, rINST, lsr #8 @ r9<- A+ 6434 VREG_INDEX_TO_ADDR(r3, r3) @ r3<- &vB 6435 and r9, r9, #15 @ r9<- A 6436 fldd d1, [r3] @ d1<- vB 6437 VREG_INDEX_TO_ADDR(r9, r9) @ r9<- &vA 6438 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6439 fldd d0, [r9] @ d0<- vA 6440 6441 fdivd d2, d0, d1 @ d2<- op 6442 GET_INST_OPCODE(ip) @ extract opcode from rINST 6443 fstd d2, [r9] @ vAA<- d2 6444 GOTO_OPCODE(ip) @ jump to next instruction 6445 6446 6447/* ------------------------------ */ 6448 .balign 64 6449.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 6450/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */ 6451/* EABI doesn't define a double remainder function, but libm does */ 6452/* File: armv5te/binopWide2addr.S */ 6453 /* 6454 * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 6455 * that specifies an instruction that performs "result = r0-r1 op r2-r3". 6456 * This could be an ARM instruction or a function call. (If the result 6457 * comes back in a register other than r0, you can override "result".) 6458 * 6459 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6460 * vCC (r1). Useful for integer division and modulus. 6461 * 6462 * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 6463 * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 6464 * sub-double/2addr, mul-double/2addr, div-double/2addr, 6465 * rem-double/2addr 6466 */ 6467 /* binop/2addr vA, vB */ 6468 mov r9, rINST, lsr #8 @ r9<- A+ 6469 mov r1, rINST, lsr #12 @ r1<- B 6470 and r9, r9, #15 6471 add r1, rFP, r1, lsl #2 @ r1<- &fp[B] 6472 add r9, rFP, r9, lsl #2 @ r9<- &fp[A] 6473 ldmia r1, {r2-r3} @ r2/r3<- vBB/vBB+1 6474 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 6475 .if 0 6476 orrs ip, r2, r3 @ second arg (r2-r3) is zero? 6477 beq common_errDivideByZero 6478 .endif 6479 FETCH_ADVANCE_INST(1) @ advance rPC, load rINST 6480 6481 @ optional op; may set condition codes 6482 bl fmod @ result<- op, r0-r3 changed 6483 GET_INST_OPCODE(ip) @ extract opcode from rINST 6484 stmia r9, {r0,r1} @ vAA/vAA+1<- r0/r1 6485 GOTO_OPCODE(ip) @ jump to next instruction 6486 /* 12-15 instructions */ 6487 6488 6489 6490/* ------------------------------ */ 6491 .balign 64 6492.L_OP_ADD_INT_LIT16: /* 0xd0 */ 6493/* File: armv5te/OP_ADD_INT_LIT16.S */ 6494/* File: armv5te/binopLit16.S */ 6495 /* 6496 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6497 * that specifies an instruction that performs "result = r0 op r1". 6498 * This could be an ARM instruction or a function call. (If the result 6499 * comes back in a register other than r0, you can override "result".) 6500 * 6501 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6502 * vCC (r1). Useful for integer division and modulus. 6503 * 6504 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6505 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6506 */ 6507 /* binop/lit16 vA, vB, #+CCCC */ 6508 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6509 mov r2, rINST, lsr #12 @ r2<- B 6510 mov r9, rINST, lsr #8 @ r9<- A+ 6511 GET_VREG(r0, r2) @ r0<- vB 6512 and r9, r9, #15 6513 .if 0 6514 cmp r1, #0 @ is second operand zero? 6515 beq common_errDivideByZero 6516 .endif 6517 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6518 6519 add r0, r0, r1 @ r0<- op, r0-r3 changed 6520 GET_INST_OPCODE(ip) @ extract opcode from rINST 6521 SET_VREG(r0, r9) @ vAA<- r0 6522 GOTO_OPCODE(ip) @ jump to next instruction 6523 /* 10-13 instructions */ 6524 6525 6526 6527/* ------------------------------ */ 6528 .balign 64 6529.L_OP_RSUB_INT: /* 0xd1 */ 6530/* File: armv5te/OP_RSUB_INT.S */ 6531/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 6532/* File: armv5te/binopLit16.S */ 6533 /* 6534 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6535 * that specifies an instruction that performs "result = r0 op r1". 6536 * This could be an ARM instruction or a function call. (If the result 6537 * comes back in a register other than r0, you can override "result".) 6538 * 6539 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6540 * vCC (r1). Useful for integer division and modulus. 6541 * 6542 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6543 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6544 */ 6545 /* binop/lit16 vA, vB, #+CCCC */ 6546 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6547 mov r2, rINST, lsr #12 @ r2<- B 6548 mov r9, rINST, lsr #8 @ r9<- A+ 6549 GET_VREG(r0, r2) @ r0<- vB 6550 and r9, r9, #15 6551 .if 0 6552 cmp r1, #0 @ is second operand zero? 6553 beq common_errDivideByZero 6554 .endif 6555 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6556 6557 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6558 GET_INST_OPCODE(ip) @ extract opcode from rINST 6559 SET_VREG(r0, r9) @ vAA<- r0 6560 GOTO_OPCODE(ip) @ jump to next instruction 6561 /* 10-13 instructions */ 6562 6563 6564 6565/* ------------------------------ */ 6566 .balign 64 6567.L_OP_MUL_INT_LIT16: /* 0xd2 */ 6568/* File: armv5te/OP_MUL_INT_LIT16.S */ 6569/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6570/* File: armv5te/binopLit16.S */ 6571 /* 6572 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6573 * that specifies an instruction that performs "result = r0 op r1". 6574 * This could be an ARM instruction or a function call. (If the result 6575 * comes back in a register other than r0, you can override "result".) 6576 * 6577 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6578 * vCC (r1). Useful for integer division and modulus. 6579 * 6580 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6581 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6582 */ 6583 /* binop/lit16 vA, vB, #+CCCC */ 6584 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6585 mov r2, rINST, lsr #12 @ r2<- B 6586 mov r9, rINST, lsr #8 @ r9<- A+ 6587 GET_VREG(r0, r2) @ r0<- vB 6588 and r9, r9, #15 6589 .if 0 6590 cmp r1, #0 @ is second operand zero? 6591 beq common_errDivideByZero 6592 .endif 6593 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6594 6595 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6596 GET_INST_OPCODE(ip) @ extract opcode from rINST 6597 SET_VREG(r0, r9) @ vAA<- r0 6598 GOTO_OPCODE(ip) @ jump to next instruction 6599 /* 10-13 instructions */ 6600 6601 6602 6603/* ------------------------------ */ 6604 .balign 64 6605.L_OP_DIV_INT_LIT16: /* 0xd3 */ 6606/* File: armv5te/OP_DIV_INT_LIT16.S */ 6607/* File: armv5te/binopLit16.S */ 6608 /* 6609 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6610 * that specifies an instruction that performs "result = r0 op r1". 6611 * This could be an ARM instruction or a function call. (If the result 6612 * comes back in a register other than r0, you can override "result".) 6613 * 6614 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6615 * vCC (r1). Useful for integer division and modulus. 6616 * 6617 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6618 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6619 */ 6620 /* binop/lit16 vA, vB, #+CCCC */ 6621 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6622 mov r2, rINST, lsr #12 @ r2<- B 6623 mov r9, rINST, lsr #8 @ r9<- A+ 6624 GET_VREG(r0, r2) @ r0<- vB 6625 and r9, r9, #15 6626 .if 1 6627 cmp r1, #0 @ is second operand zero? 6628 beq common_errDivideByZero 6629 .endif 6630 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6631 6632 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6633 GET_INST_OPCODE(ip) @ extract opcode from rINST 6634 SET_VREG(r0, r9) @ vAA<- r0 6635 GOTO_OPCODE(ip) @ jump to next instruction 6636 /* 10-13 instructions */ 6637 6638 6639 6640/* ------------------------------ */ 6641 .balign 64 6642.L_OP_REM_INT_LIT16: /* 0xd4 */ 6643/* File: armv5te/OP_REM_INT_LIT16.S */ 6644/* idivmod returns quotient in r0 and remainder in r1 */ 6645/* File: armv5te/binopLit16.S */ 6646 /* 6647 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6648 * that specifies an instruction that performs "result = r0 op r1". 6649 * This could be an ARM instruction or a function call. (If the result 6650 * comes back in a register other than r0, you can override "result".) 6651 * 6652 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6653 * vCC (r1). Useful for integer division and modulus. 6654 * 6655 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6656 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6657 */ 6658 /* binop/lit16 vA, vB, #+CCCC */ 6659 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6660 mov r2, rINST, lsr #12 @ r2<- B 6661 mov r9, rINST, lsr #8 @ r9<- A+ 6662 GET_VREG(r0, r2) @ r0<- vB 6663 and r9, r9, #15 6664 .if 1 6665 cmp r1, #0 @ is second operand zero? 6666 beq common_errDivideByZero 6667 .endif 6668 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6669 6670 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6671 GET_INST_OPCODE(ip) @ extract opcode from rINST 6672 SET_VREG(r1, r9) @ vAA<- r1 6673 GOTO_OPCODE(ip) @ jump to next instruction 6674 /* 10-13 instructions */ 6675 6676 6677 6678/* ------------------------------ */ 6679 .balign 64 6680.L_OP_AND_INT_LIT16: /* 0xd5 */ 6681/* File: armv5te/OP_AND_INT_LIT16.S */ 6682/* File: armv5te/binopLit16.S */ 6683 /* 6684 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6685 * that specifies an instruction that performs "result = r0 op r1". 6686 * This could be an ARM instruction or a function call. (If the result 6687 * comes back in a register other than r0, you can override "result".) 6688 * 6689 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6690 * vCC (r1). Useful for integer division and modulus. 6691 * 6692 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6693 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6694 */ 6695 /* binop/lit16 vA, vB, #+CCCC */ 6696 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6697 mov r2, rINST, lsr #12 @ r2<- B 6698 mov r9, rINST, lsr #8 @ r9<- A+ 6699 GET_VREG(r0, r2) @ r0<- vB 6700 and r9, r9, #15 6701 .if 0 6702 cmp r1, #0 @ is second operand zero? 6703 beq common_errDivideByZero 6704 .endif 6705 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6706 6707 and r0, r0, r1 @ r0<- op, r0-r3 changed 6708 GET_INST_OPCODE(ip) @ extract opcode from rINST 6709 SET_VREG(r0, r9) @ vAA<- r0 6710 GOTO_OPCODE(ip) @ jump to next instruction 6711 /* 10-13 instructions */ 6712 6713 6714 6715/* ------------------------------ */ 6716 .balign 64 6717.L_OP_OR_INT_LIT16: /* 0xd6 */ 6718/* File: armv5te/OP_OR_INT_LIT16.S */ 6719/* File: armv5te/binopLit16.S */ 6720 /* 6721 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6722 * that specifies an instruction that performs "result = r0 op r1". 6723 * This could be an ARM instruction or a function call. (If the result 6724 * comes back in a register other than r0, you can override "result".) 6725 * 6726 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6727 * vCC (r1). Useful for integer division and modulus. 6728 * 6729 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6730 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6731 */ 6732 /* binop/lit16 vA, vB, #+CCCC */ 6733 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6734 mov r2, rINST, lsr #12 @ r2<- B 6735 mov r9, rINST, lsr #8 @ r9<- A+ 6736 GET_VREG(r0, r2) @ r0<- vB 6737 and r9, r9, #15 6738 .if 0 6739 cmp r1, #0 @ is second operand zero? 6740 beq common_errDivideByZero 6741 .endif 6742 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6743 6744 orr r0, r0, r1 @ r0<- op, r0-r3 changed 6745 GET_INST_OPCODE(ip) @ extract opcode from rINST 6746 SET_VREG(r0, r9) @ vAA<- r0 6747 GOTO_OPCODE(ip) @ jump to next instruction 6748 /* 10-13 instructions */ 6749 6750 6751 6752/* ------------------------------ */ 6753 .balign 64 6754.L_OP_XOR_INT_LIT16: /* 0xd7 */ 6755/* File: armv5te/OP_XOR_INT_LIT16.S */ 6756/* File: armv5te/binopLit16.S */ 6757 /* 6758 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 6759 * that specifies an instruction that performs "result = r0 op r1". 6760 * This could be an ARM instruction or a function call. (If the result 6761 * comes back in a register other than r0, you can override "result".) 6762 * 6763 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6764 * vCC (r1). Useful for integer division and modulus. 6765 * 6766 * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 6767 * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 6768 */ 6769 /* binop/lit16 vA, vB, #+CCCC */ 6770 FETCH_S(r1, 1) @ r1<- ssssCCCC (sign-extended) 6771 mov r2, rINST, lsr #12 @ r2<- B 6772 mov r9, rINST, lsr #8 @ r9<- A+ 6773 GET_VREG(r0, r2) @ r0<- vB 6774 and r9, r9, #15 6775 .if 0 6776 cmp r1, #0 @ is second operand zero? 6777 beq common_errDivideByZero 6778 .endif 6779 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6780 6781 eor r0, r0, r1 @ r0<- op, r0-r3 changed 6782 GET_INST_OPCODE(ip) @ extract opcode from rINST 6783 SET_VREG(r0, r9) @ vAA<- r0 6784 GOTO_OPCODE(ip) @ jump to next instruction 6785 /* 10-13 instructions */ 6786 6787 6788 6789/* ------------------------------ */ 6790 .balign 64 6791.L_OP_ADD_INT_LIT8: /* 0xd8 */ 6792/* File: armv5te/OP_ADD_INT_LIT8.S */ 6793/* File: armv5te/binopLit8.S */ 6794 /* 6795 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6796 * that specifies an instruction that performs "result = r0 op r1". 6797 * This could be an ARM instruction or a function call. (If the result 6798 * comes back in a register other than r0, you can override "result".) 6799 * 6800 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6801 * vCC (r1). Useful for integer division and modulus. 6802 * 6803 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6804 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6805 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6806 */ 6807 /* binop/lit8 vAA, vBB, #+CC */ 6808 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6809 mov r9, rINST, lsr #8 @ r9<- AA 6810 and r2, r3, #255 @ r2<- BB 6811 GET_VREG(r0, r2) @ r0<- vBB 6812 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6813 .if 0 6814 @cmp r1, #0 @ is second operand zero? 6815 beq common_errDivideByZero 6816 .endif 6817 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6818 6819 @ optional op; may set condition codes 6820 add r0, r0, r1 @ r0<- op, r0-r3 changed 6821 GET_INST_OPCODE(ip) @ extract opcode from rINST 6822 SET_VREG(r0, r9) @ vAA<- r0 6823 GOTO_OPCODE(ip) @ jump to next instruction 6824 /* 10-12 instructions */ 6825 6826 6827 6828/* ------------------------------ */ 6829 .balign 64 6830.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 6831/* File: armv5te/OP_RSUB_INT_LIT8.S */ 6832/* File: armv5te/binopLit8.S */ 6833 /* 6834 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6835 * that specifies an instruction that performs "result = r0 op r1". 6836 * This could be an ARM instruction or a function call. (If the result 6837 * comes back in a register other than r0, you can override "result".) 6838 * 6839 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6840 * vCC (r1). Useful for integer division and modulus. 6841 * 6842 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6843 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6844 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6845 */ 6846 /* binop/lit8 vAA, vBB, #+CC */ 6847 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6848 mov r9, rINST, lsr #8 @ r9<- AA 6849 and r2, r3, #255 @ r2<- BB 6850 GET_VREG(r0, r2) @ r0<- vBB 6851 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6852 .if 0 6853 @cmp r1, #0 @ is second operand zero? 6854 beq common_errDivideByZero 6855 .endif 6856 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6857 6858 @ optional op; may set condition codes 6859 rsb r0, r0, r1 @ r0<- op, r0-r3 changed 6860 GET_INST_OPCODE(ip) @ extract opcode from rINST 6861 SET_VREG(r0, r9) @ vAA<- r0 6862 GOTO_OPCODE(ip) @ jump to next instruction 6863 /* 10-12 instructions */ 6864 6865 6866 6867/* ------------------------------ */ 6868 .balign 64 6869.L_OP_MUL_INT_LIT8: /* 0xda */ 6870/* File: armv5te/OP_MUL_INT_LIT8.S */ 6871/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */ 6872/* File: armv5te/binopLit8.S */ 6873 /* 6874 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6875 * that specifies an instruction that performs "result = r0 op r1". 6876 * This could be an ARM instruction or a function call. (If the result 6877 * comes back in a register other than r0, you can override "result".) 6878 * 6879 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6880 * vCC (r1). Useful for integer division and modulus. 6881 * 6882 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6883 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6884 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6885 */ 6886 /* binop/lit8 vAA, vBB, #+CC */ 6887 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6888 mov r9, rINST, lsr #8 @ r9<- AA 6889 and r2, r3, #255 @ r2<- BB 6890 GET_VREG(r0, r2) @ r0<- vBB 6891 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6892 .if 0 6893 @cmp r1, #0 @ is second operand zero? 6894 beq common_errDivideByZero 6895 .endif 6896 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6897 6898 @ optional op; may set condition codes 6899 mul r0, r1, r0 @ r0<- op, r0-r3 changed 6900 GET_INST_OPCODE(ip) @ extract opcode from rINST 6901 SET_VREG(r0, r9) @ vAA<- r0 6902 GOTO_OPCODE(ip) @ jump to next instruction 6903 /* 10-12 instructions */ 6904 6905 6906 6907/* ------------------------------ */ 6908 .balign 64 6909.L_OP_DIV_INT_LIT8: /* 0xdb */ 6910/* File: armv5te/OP_DIV_INT_LIT8.S */ 6911/* File: armv5te/binopLit8.S */ 6912 /* 6913 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6914 * that specifies an instruction that performs "result = r0 op r1". 6915 * This could be an ARM instruction or a function call. (If the result 6916 * comes back in a register other than r0, you can override "result".) 6917 * 6918 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6919 * vCC (r1). Useful for integer division and modulus. 6920 * 6921 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6922 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6923 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6924 */ 6925 /* binop/lit8 vAA, vBB, #+CC */ 6926 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6927 mov r9, rINST, lsr #8 @ r9<- AA 6928 and r2, r3, #255 @ r2<- BB 6929 GET_VREG(r0, r2) @ r0<- vBB 6930 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6931 .if 1 6932 @cmp r1, #0 @ is second operand zero? 6933 beq common_errDivideByZero 6934 .endif 6935 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6936 6937 @ optional op; may set condition codes 6938 bl __aeabi_idiv @ r0<- op, r0-r3 changed 6939 GET_INST_OPCODE(ip) @ extract opcode from rINST 6940 SET_VREG(r0, r9) @ vAA<- r0 6941 GOTO_OPCODE(ip) @ jump to next instruction 6942 /* 10-12 instructions */ 6943 6944 6945 6946/* ------------------------------ */ 6947 .balign 64 6948.L_OP_REM_INT_LIT8: /* 0xdc */ 6949/* File: armv5te/OP_REM_INT_LIT8.S */ 6950/* idivmod returns quotient in r0 and remainder in r1 */ 6951/* File: armv5te/binopLit8.S */ 6952 /* 6953 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6954 * that specifies an instruction that performs "result = r0 op r1". 6955 * This could be an ARM instruction or a function call. (If the result 6956 * comes back in a register other than r0, you can override "result".) 6957 * 6958 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6959 * vCC (r1). Useful for integer division and modulus. 6960 * 6961 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 6962 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 6963 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 6964 */ 6965 /* binop/lit8 vAA, vBB, #+CC */ 6966 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 6967 mov r9, rINST, lsr #8 @ r9<- AA 6968 and r2, r3, #255 @ r2<- BB 6969 GET_VREG(r0, r2) @ r0<- vBB 6970 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 6971 .if 1 6972 @cmp r1, #0 @ is second operand zero? 6973 beq common_errDivideByZero 6974 .endif 6975 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 6976 6977 @ optional op; may set condition codes 6978 bl __aeabi_idivmod @ r1<- op, r0-r3 changed 6979 GET_INST_OPCODE(ip) @ extract opcode from rINST 6980 SET_VREG(r1, r9) @ vAA<- r1 6981 GOTO_OPCODE(ip) @ jump to next instruction 6982 /* 10-12 instructions */ 6983 6984 6985 6986/* ------------------------------ */ 6987 .balign 64 6988.L_OP_AND_INT_LIT8: /* 0xdd */ 6989/* File: armv5te/OP_AND_INT_LIT8.S */ 6990/* File: armv5te/binopLit8.S */ 6991 /* 6992 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 6993 * that specifies an instruction that performs "result = r0 op r1". 6994 * This could be an ARM instruction or a function call. (If the result 6995 * comes back in a register other than r0, you can override "result".) 6996 * 6997 * If "chkzero" is set to 1, we perform a divide-by-zero check on 6998 * vCC (r1). Useful for integer division and modulus. 6999 * 7000 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7001 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7002 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7003 */ 7004 /* binop/lit8 vAA, vBB, #+CC */ 7005 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7006 mov r9, rINST, lsr #8 @ r9<- AA 7007 and r2, r3, #255 @ r2<- BB 7008 GET_VREG(r0, r2) @ r0<- vBB 7009 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7010 .if 0 7011 @cmp r1, #0 @ is second operand zero? 7012 beq common_errDivideByZero 7013 .endif 7014 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7015 7016 @ optional op; may set condition codes 7017 and r0, r0, r1 @ r0<- op, r0-r3 changed 7018 GET_INST_OPCODE(ip) @ extract opcode from rINST 7019 SET_VREG(r0, r9) @ vAA<- r0 7020 GOTO_OPCODE(ip) @ jump to next instruction 7021 /* 10-12 instructions */ 7022 7023 7024 7025/* ------------------------------ */ 7026 .balign 64 7027.L_OP_OR_INT_LIT8: /* 0xde */ 7028/* File: armv5te/OP_OR_INT_LIT8.S */ 7029/* File: armv5te/binopLit8.S */ 7030 /* 7031 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7032 * that specifies an instruction that performs "result = r0 op r1". 7033 * This could be an ARM instruction or a function call. (If the result 7034 * comes back in a register other than r0, you can override "result".) 7035 * 7036 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7037 * vCC (r1). Useful for integer division and modulus. 7038 * 7039 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7040 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7041 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7042 */ 7043 /* binop/lit8 vAA, vBB, #+CC */ 7044 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7045 mov r9, rINST, lsr #8 @ r9<- AA 7046 and r2, r3, #255 @ r2<- BB 7047 GET_VREG(r0, r2) @ r0<- vBB 7048 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7049 .if 0 7050 @cmp r1, #0 @ is second operand zero? 7051 beq common_errDivideByZero 7052 .endif 7053 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7054 7055 @ optional op; may set condition codes 7056 orr r0, r0, r1 @ r0<- op, r0-r3 changed 7057 GET_INST_OPCODE(ip) @ extract opcode from rINST 7058 SET_VREG(r0, r9) @ vAA<- r0 7059 GOTO_OPCODE(ip) @ jump to next instruction 7060 /* 10-12 instructions */ 7061 7062 7063 7064/* ------------------------------ */ 7065 .balign 64 7066.L_OP_XOR_INT_LIT8: /* 0xdf */ 7067/* File: armv5te/OP_XOR_INT_LIT8.S */ 7068/* File: armv5te/binopLit8.S */ 7069 /* 7070 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7071 * that specifies an instruction that performs "result = r0 op r1". 7072 * This could be an ARM instruction or a function call. (If the result 7073 * comes back in a register other than r0, you can override "result".) 7074 * 7075 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7076 * vCC (r1). Useful for integer division and modulus. 7077 * 7078 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7079 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7080 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7081 */ 7082 /* binop/lit8 vAA, vBB, #+CC */ 7083 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7084 mov r9, rINST, lsr #8 @ r9<- AA 7085 and r2, r3, #255 @ r2<- BB 7086 GET_VREG(r0, r2) @ r0<- vBB 7087 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7088 .if 0 7089 @cmp r1, #0 @ is second operand zero? 7090 beq common_errDivideByZero 7091 .endif 7092 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7093 7094 @ optional op; may set condition codes 7095 eor r0, r0, r1 @ r0<- op, r0-r3 changed 7096 GET_INST_OPCODE(ip) @ extract opcode from rINST 7097 SET_VREG(r0, r9) @ vAA<- r0 7098 GOTO_OPCODE(ip) @ jump to next instruction 7099 /* 10-12 instructions */ 7100 7101 7102 7103/* ------------------------------ */ 7104 .balign 64 7105.L_OP_SHL_INT_LIT8: /* 0xe0 */ 7106/* File: armv5te/OP_SHL_INT_LIT8.S */ 7107/* File: armv5te/binopLit8.S */ 7108 /* 7109 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7110 * that specifies an instruction that performs "result = r0 op r1". 7111 * This could be an ARM instruction or a function call. (If the result 7112 * comes back in a register other than r0, you can override "result".) 7113 * 7114 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7115 * vCC (r1). Useful for integer division and modulus. 7116 * 7117 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7118 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7119 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7120 */ 7121 /* binop/lit8 vAA, vBB, #+CC */ 7122 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7123 mov r9, rINST, lsr #8 @ r9<- AA 7124 and r2, r3, #255 @ r2<- BB 7125 GET_VREG(r0, r2) @ r0<- vBB 7126 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7127 .if 0 7128 @cmp r1, #0 @ is second operand zero? 7129 beq common_errDivideByZero 7130 .endif 7131 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7132 7133 and r1, r1, #31 @ optional op; may set condition codes 7134 mov r0, r0, asl r1 @ r0<- op, r0-r3 changed 7135 GET_INST_OPCODE(ip) @ extract opcode from rINST 7136 SET_VREG(r0, r9) @ vAA<- r0 7137 GOTO_OPCODE(ip) @ jump to next instruction 7138 /* 10-12 instructions */ 7139 7140 7141 7142/* ------------------------------ */ 7143 .balign 64 7144.L_OP_SHR_INT_LIT8: /* 0xe1 */ 7145/* File: armv5te/OP_SHR_INT_LIT8.S */ 7146/* File: armv5te/binopLit8.S */ 7147 /* 7148 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7149 * that specifies an instruction that performs "result = r0 op r1". 7150 * This could be an ARM instruction or a function call. (If the result 7151 * comes back in a register other than r0, you can override "result".) 7152 * 7153 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7154 * vCC (r1). Useful for integer division and modulus. 7155 * 7156 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7157 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7158 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7159 */ 7160 /* binop/lit8 vAA, vBB, #+CC */ 7161 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7162 mov r9, rINST, lsr #8 @ r9<- AA 7163 and r2, r3, #255 @ r2<- BB 7164 GET_VREG(r0, r2) @ r0<- vBB 7165 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7166 .if 0 7167 @cmp r1, #0 @ is second operand zero? 7168 beq common_errDivideByZero 7169 .endif 7170 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7171 7172 and r1, r1, #31 @ optional op; may set condition codes 7173 mov r0, r0, asr r1 @ r0<- op, r0-r3 changed 7174 GET_INST_OPCODE(ip) @ extract opcode from rINST 7175 SET_VREG(r0, r9) @ vAA<- r0 7176 GOTO_OPCODE(ip) @ jump to next instruction 7177 /* 10-12 instructions */ 7178 7179 7180 7181/* ------------------------------ */ 7182 .balign 64 7183.L_OP_USHR_INT_LIT8: /* 0xe2 */ 7184/* File: armv5te/OP_USHR_INT_LIT8.S */ 7185/* File: armv5te/binopLit8.S */ 7186 /* 7187 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 7188 * that specifies an instruction that performs "result = r0 op r1". 7189 * This could be an ARM instruction or a function call. (If the result 7190 * comes back in a register other than r0, you can override "result".) 7191 * 7192 * If "chkzero" is set to 1, we perform a divide-by-zero check on 7193 * vCC (r1). Useful for integer division and modulus. 7194 * 7195 * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 7196 * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 7197 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 7198 */ 7199 /* binop/lit8 vAA, vBB, #+CC */ 7200 FETCH_S(r3, 1) @ r3<- ssssCCBB (sign-extended for CC) 7201 mov r9, rINST, lsr #8 @ r9<- AA 7202 and r2, r3, #255 @ r2<- BB 7203 GET_VREG(r0, r2) @ r0<- vBB 7204 movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 7205 .if 0 7206 @cmp r1, #0 @ is second operand zero? 7207 beq common_errDivideByZero 7208 .endif 7209 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7210 7211 and r1, r1, #31 @ optional op; may set condition codes 7212 mov r0, r0, lsr r1 @ r0<- op, r0-r3 changed 7213 GET_INST_OPCODE(ip) @ extract opcode from rINST 7214 SET_VREG(r0, r9) @ vAA<- r0 7215 GOTO_OPCODE(ip) @ jump to next instruction 7216 /* 10-12 instructions */ 7217 7218 7219 7220/* ------------------------------ */ 7221 .balign 64 7222.L_OP_UNUSED_E3: /* 0xe3 */ 7223/* File: armv5te/OP_UNUSED_E3.S */ 7224/* File: armv5te/unused.S */ 7225 bl common_abort 7226 7227 7228 7229/* ------------------------------ */ 7230 .balign 64 7231.L_OP_UNUSED_E4: /* 0xe4 */ 7232/* File: armv5te/OP_UNUSED_E4.S */ 7233/* File: armv5te/unused.S */ 7234 bl common_abort 7235 7236 7237 7238/* ------------------------------ */ 7239 .balign 64 7240.L_OP_UNUSED_E5: /* 0xe5 */ 7241/* File: armv5te/OP_UNUSED_E5.S */ 7242/* File: armv5te/unused.S */ 7243 bl common_abort 7244 7245 7246 7247/* ------------------------------ */ 7248 .balign 64 7249.L_OP_UNUSED_E6: /* 0xe6 */ 7250/* File: armv5te/OP_UNUSED_E6.S */ 7251/* File: armv5te/unused.S */ 7252 bl common_abort 7253 7254 7255 7256/* ------------------------------ */ 7257 .balign 64 7258.L_OP_UNUSED_E7: /* 0xe7 */ 7259/* File: armv5te/OP_UNUSED_E7.S */ 7260/* File: armv5te/unused.S */ 7261 bl common_abort 7262 7263 7264 7265/* ------------------------------ */ 7266 .balign 64 7267.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */ 7268/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */ 7269/* File: armv5te/OP_IGET_WIDE.S */ 7270 /* 7271 * Wide 32-bit instance field get. 7272 */ 7273 /* iget-wide vA, vB, field@CCCC */ 7274 mov r0, rINST, lsr #12 @ r0<- B 7275 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7276 FETCH(r1, 1) @ r1<- field ref CCCC 7277 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7278 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7279 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7280 cmp r0, #0 @ is resolved entry null? 7281 bne .LOP_IGET_WIDE_VOLATILE_finish @ no, already resolved 72828: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7283 EXPORT_PC() @ resolve() could throw 7284 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7285 bl dvmResolveInstField @ r0<- resolved InstField ptr 7286 cmp r0, #0 7287 bne .LOP_IGET_WIDE_VOLATILE_finish 7288 b common_exceptionThrown 7289 7290 7291/* ------------------------------ */ 7292 .balign 64 7293.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */ 7294/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */ 7295/* File: armv5te/OP_IPUT_WIDE.S */ 7296 /* iput-wide vA, vB, field@CCCC */ 7297 mov r0, rINST, lsr #12 @ r0<- B 7298 ldr r3, [rGLUE, #offGlue_methodClassDex] @ r3<- DvmDex 7299 FETCH(r1, 1) @ r1<- field ref CCCC 7300 ldr r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields 7301 GET_VREG(r9, r0) @ r9<- fp[B], the object pointer 7302 ldr r0, [r2, r1, lsl #2] @ r0<- resolved InstField ptr 7303 cmp r0, #0 @ is resolved entry null? 7304 bne .LOP_IPUT_WIDE_VOLATILE_finish @ no, already resolved 73058: ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7306 EXPORT_PC() @ resolve() could throw 7307 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 7308 bl dvmResolveInstField @ r0<- resolved InstField ptr 7309 cmp r0, #0 @ success? 7310 bne .LOP_IPUT_WIDE_VOLATILE_finish @ yes, finish up 7311 b common_exceptionThrown 7312 7313 7314/* ------------------------------ */ 7315 .balign 64 7316.L_OP_SGET_WIDE_VOLATILE: /* 0xea */ 7317/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */ 7318/* File: armv5te/OP_SGET_WIDE.S */ 7319 /* 7320 * 64-bit SGET handler. 7321 */ 7322 /* sget-wide vAA, field@BBBB */ 7323 ldr r2, [rGLUE, #offGlue_methodClassDex] @ r2<- DvmDex 7324 FETCH(r1, 1) @ r1<- field ref BBBB 7325 ldr r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields 7326 ldr r0, [r2, r1, lsl #2] @ r0<- resolved StaticField ptr 7327 cmp r0, #0 @ is resolved entry null? 7328 beq .LOP_SGET_WIDE_VOLATILE_resolve @ yes, do resolve 7329.LOP_SGET_WIDE_VOLATILE_finish: 7330 mov r9, rINST, lsr #8 @ r9<- AA 7331 .if 1 7332 add r0, r0, #offStaticField_value @ r0<- pointer to data 7333 bl android_quasiatomic_read_64 @ r0/r1<- contents of field 7334 .else 7335 ldrd r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned) 7336 .endif 7337 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7338 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7339 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 7340 GET_INST_OPCODE(ip) @ extract opcode from rINST 7341 GOTO_OPCODE(ip) @ jump to next instruction 7342 7343 7344/* ------------------------------ */ 7345 .balign 64 7346.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */ 7347/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */ 7348/* File: armv5te/OP_SPUT_WIDE.S */ 7349 /* 7350 * 64-bit SPUT handler. 7351 */ 7352 /* sput-wide vAA, field@BBBB */ 7353 ldr r0, [rGLUE, #offGlue_methodClassDex] @ r0<- DvmDex 7354 FETCH(r1, 1) @ r1<- field ref BBBB 7355 ldr r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields 7356 mov r9, rINST, lsr #8 @ r9<- AA 7357 ldr r2, [r0, r1, lsl #2] @ r2<- resolved StaticField ptr 7358 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 7359 cmp r2, #0 @ is resolved entry null? 7360 beq .LOP_SPUT_WIDE_VOLATILE_resolve @ yes, do resolve 7361.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9 7362 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7363 ldmia r9, {r0-r1} @ r0/r1<- vAA/vAA+1 7364 GET_INST_OPCODE(r10) @ extract opcode from rINST 7365 .if 1 7366 add r2, r2, #offStaticField_value @ r2<- pointer to data 7367 bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2 7368 .else 7369 strd r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1 7370 .endif 7371 GOTO_OPCODE(r10) @ jump to next instruction 7372 7373 7374/* ------------------------------ */ 7375 .balign 64 7376.L_OP_BREAKPOINT: /* 0xec */ 7377/* File: armv5te/OP_BREAKPOINT.S */ 7378/* File: armv5te/unused.S */ 7379 bl common_abort 7380 7381 7382 7383/* ------------------------------ */ 7384 .balign 64 7385.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 7386/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */ 7387 /* 7388 * Handle a throw-verification-error instruction. This throws an 7389 * exception for an error discovered during verification. The 7390 * exception is indicated by AA, with some detail provided by BBBB. 7391 */ 7392 /* op AA, ref@BBBB */ 7393 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7394 FETCH(r2, 1) @ r2<- BBBB 7395 EXPORT_PC() @ export the PC 7396 mov r1, rINST, lsr #8 @ r1<- AA 7397 bl dvmThrowVerificationError @ always throws 7398 b common_exceptionThrown @ handle exception 7399 7400 7401/* ------------------------------ */ 7402 .balign 64 7403.L_OP_EXECUTE_INLINE: /* 0xee */ 7404/* File: armv5te/OP_EXECUTE_INLINE.S */ 7405 /* 7406 * Execute a "native inline" instruction. 7407 * 7408 * We need to call an InlineOp4Func: 7409 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7410 * 7411 * The first four args are in r0-r3, pointer to return value storage 7412 * is on the stack. The function's return value is a flag that tells 7413 * us if an exception was thrown. 7414 */ 7415 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 7416 FETCH(r10, 1) @ r10<- BBBB 7417 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7418 EXPORT_PC() @ can throw 7419 sub sp, sp, #8 @ make room for arg, +64 bit align 7420 mov r0, rINST, lsr #12 @ r0<- B 7421 str r1, [sp] @ push &glue->retval 7422 bl .LOP_EXECUTE_INLINE_continue @ make call; will return after 7423 add sp, sp, #8 @ pop stack 7424 cmp r0, #0 @ test boolean result of inline 7425 beq common_exceptionThrown @ returned false, handle exception 7426 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7427 GET_INST_OPCODE(ip) @ extract opcode from rINST 7428 GOTO_OPCODE(ip) @ jump to next instruction 7429 7430/* ------------------------------ */ 7431 .balign 64 7432.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ 7433/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */ 7434 /* 7435 * Execute a "native inline" instruction, using "/range" semantics. 7436 * Same idea as execute-inline, but we get the args differently. 7437 * 7438 * We need to call an InlineOp4Func: 7439 * bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult) 7440 * 7441 * The first four args are in r0-r3, pointer to return value storage 7442 * is on the stack. The function's return value is a flag that tells 7443 * us if an exception was thrown. 7444 */ 7445 /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */ 7446 FETCH(r10, 1) @ r10<- BBBB 7447 add r1, rGLUE, #offGlue_retval @ r1<- &glue->retval 7448 EXPORT_PC() @ can throw 7449 sub sp, sp, #8 @ make room for arg, +64 bit align 7450 mov r0, rINST, lsr #8 @ r0<- AA 7451 str r1, [sp] @ push &glue->retval 7452 bl .LOP_EXECUTE_INLINE_RANGE_continue @ make call; will return after 7453 add sp, sp, #8 @ pop stack 7454 cmp r0, #0 @ test boolean result of inline 7455 beq common_exceptionThrown @ returned false, handle exception 7456 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7457 GET_INST_OPCODE(ip) @ extract opcode from rINST 7458 GOTO_OPCODE(ip) @ jump to next instruction 7459 7460/* ------------------------------ */ 7461 .balign 64 7462.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 7463/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */ 7464 /* 7465 * invoke-direct-empty is a no-op in a "standard" interpreter. 7466 */ 7467 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 7468 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 7469 GOTO_OPCODE(ip) @ execute it 7470 7471/* ------------------------------ */ 7472 .balign 64 7473.L_OP_UNUSED_F1: /* 0xf1 */ 7474/* File: armv5te/OP_UNUSED_F1.S */ 7475/* File: armv5te/unused.S */ 7476 bl common_abort 7477 7478 7479 7480/* ------------------------------ */ 7481 .balign 64 7482.L_OP_IGET_QUICK: /* 0xf2 */ 7483/* File: armv5te/OP_IGET_QUICK.S */ 7484 /* For: iget-quick, iget-object-quick */ 7485 /* op vA, vB, offset@CCCC */ 7486 mov r2, rINST, lsr #12 @ r2<- B 7487 GET_VREG(r3, r2) @ r3<- object we're operating on 7488 FETCH(r1, 1) @ r1<- field byte offset 7489 cmp r3, #0 @ check object for null 7490 mov r2, rINST, lsr #8 @ r2<- A(+) 7491 beq common_errNullObject @ object was null 7492 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7493 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7494 and r2, r2, #15 7495 GET_INST_OPCODE(ip) @ extract opcode from rINST 7496 SET_VREG(r0, r2) @ fp[A]<- r0 7497 GOTO_OPCODE(ip) @ jump to next instruction 7498 7499 7500/* ------------------------------ */ 7501 .balign 64 7502.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 7503/* File: armv5te/OP_IGET_WIDE_QUICK.S */ 7504 /* iget-wide-quick vA, vB, offset@CCCC */ 7505 mov r2, rINST, lsr #12 @ r2<- B 7506 GET_VREG(r3, r2) @ r3<- object we're operating on 7507 FETCH(ip, 1) @ ip<- field byte offset 7508 cmp r3, #0 @ check object for null 7509 mov r2, rINST, lsr #8 @ r2<- A(+) 7510 beq common_errNullObject @ object was null 7511 ldrd r0, [r3, ip] @ r0<- obj.field (64 bits, aligned) 7512 and r2, r2, #15 7513 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7514 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 7515 GET_INST_OPCODE(ip) @ extract opcode from rINST 7516 stmia r3, {r0-r1} @ fp[A]<- r0/r1 7517 GOTO_OPCODE(ip) @ jump to next instruction 7518 7519 7520/* ------------------------------ */ 7521 .balign 64 7522.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 7523/* File: armv5te/OP_IGET_OBJECT_QUICK.S */ 7524/* File: armv5te/OP_IGET_QUICK.S */ 7525 /* For: iget-quick, iget-object-quick */ 7526 /* op vA, vB, offset@CCCC */ 7527 mov r2, rINST, lsr #12 @ r2<- B 7528 GET_VREG(r3, r2) @ r3<- object we're operating on 7529 FETCH(r1, 1) @ r1<- field byte offset 7530 cmp r3, #0 @ check object for null 7531 mov r2, rINST, lsr #8 @ r2<- A(+) 7532 beq common_errNullObject @ object was null 7533 ldr r0, [r3, r1] @ r0<- obj.field (always 32 bits) 7534 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7535 and r2, r2, #15 7536 GET_INST_OPCODE(ip) @ extract opcode from rINST 7537 SET_VREG(r0, r2) @ fp[A]<- r0 7538 GOTO_OPCODE(ip) @ jump to next instruction 7539 7540 7541 7542/* ------------------------------ */ 7543 .balign 64 7544.L_OP_IPUT_QUICK: /* 0xf5 */ 7545/* File: armv5te/OP_IPUT_QUICK.S */ 7546 /* For: iput-quick, iput-object-quick */ 7547 /* op vA, vB, offset@CCCC */ 7548 mov r2, rINST, lsr #12 @ r2<- B 7549 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7550 FETCH(r1, 1) @ r1<- field byte offset 7551 cmp r3, #0 @ check object for null 7552 mov r2, rINST, lsr #8 @ r2<- A(+) 7553 beq common_errNullObject @ object was null 7554 and r2, r2, #15 7555 GET_VREG(r0, r2) @ r0<- fp[A] 7556 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7557 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7558 GET_INST_OPCODE(ip) @ extract opcode from rINST 7559 GOTO_OPCODE(ip) @ jump to next instruction 7560 7561 7562/* ------------------------------ */ 7563 .balign 64 7564.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 7565/* File: armv5te/OP_IPUT_WIDE_QUICK.S */ 7566 /* iput-wide-quick vA, vB, offset@CCCC */ 7567 mov r0, rINST, lsr #8 @ r0<- A(+) 7568 mov r1, rINST, lsr #12 @ r1<- B 7569 and r0, r0, #15 7570 GET_VREG(r2, r1) @ r2<- fp[B], the object pointer 7571 add r3, rFP, r0, lsl #2 @ r3<- &fp[A] 7572 cmp r2, #0 @ check object for null 7573 ldmia r3, {r0-r1} @ r0/r1<- fp[A] 7574 beq common_errNullObject @ object was null 7575 FETCH(r3, 1) @ r3<- field byte offset 7576 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7577 strd r0, [r2, r3] @ obj.field (64 bits, aligned)<- r0/r1 7578 GET_INST_OPCODE(ip) @ extract opcode from rINST 7579 GOTO_OPCODE(ip) @ jump to next instruction 7580 7581 7582/* ------------------------------ */ 7583 .balign 64 7584.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 7585/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */ 7586/* File: armv5te/OP_IPUT_QUICK.S */ 7587 /* For: iput-quick, iput-object-quick */ 7588 /* op vA, vB, offset@CCCC */ 7589 mov r2, rINST, lsr #12 @ r2<- B 7590 GET_VREG(r3, r2) @ r3<- fp[B], the object pointer 7591 FETCH(r1, 1) @ r1<- field byte offset 7592 cmp r3, #0 @ check object for null 7593 mov r2, rINST, lsr #8 @ r2<- A(+) 7594 beq common_errNullObject @ object was null 7595 and r2, r2, #15 7596 GET_VREG(r0, r2) @ r0<- fp[A] 7597 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7598 str r0, [r3, r1] @ obj.field (always 32 bits)<- r0 7599 GET_INST_OPCODE(ip) @ extract opcode from rINST 7600 GOTO_OPCODE(ip) @ jump to next instruction 7601 7602 7603 7604/* ------------------------------ */ 7605 .balign 64 7606.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 7607/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7608 /* 7609 * Handle an optimized virtual method call. 7610 * 7611 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7612 */ 7613 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7614 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7615 FETCH(r3, 2) @ r3<- FEDC or CCCC 7616 FETCH(r1, 1) @ r1<- BBBB 7617 .if (!0) 7618 and r3, r3, #15 @ r3<- C (or stays CCCC) 7619 .endif 7620 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7621 cmp r2, #0 @ is "this" null? 7622 beq common_errNullObject @ null "this", throw exception 7623 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7624 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7625 EXPORT_PC() @ invoke must export 7626 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7627 bl common_invokeMethodNoRange @ continue on 7628 7629/* ------------------------------ */ 7630 .balign 64 7631.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 7632/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 7633/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */ 7634 /* 7635 * Handle an optimized virtual method call. 7636 * 7637 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 7638 */ 7639 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7640 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7641 FETCH(r3, 2) @ r3<- FEDC or CCCC 7642 FETCH(r1, 1) @ r1<- BBBB 7643 .if (!1) 7644 and r3, r3, #15 @ r3<- C (or stays CCCC) 7645 .endif 7646 GET_VREG(r2, r3) @ r2<- vC ("this" ptr) 7647 cmp r2, #0 @ is "this" null? 7648 beq common_errNullObject @ null "this", throw exception 7649 ldr r2, [r2, #offObject_clazz] @ r2<- thisPtr->clazz 7650 ldr r2, [r2, #offClassObject_vtable] @ r2<- thisPtr->clazz->vtable 7651 EXPORT_PC() @ invoke must export 7652 ldr r0, [r2, r1, lsl #2] @ r3<- vtable[BBBB] 7653 bl common_invokeMethodRange @ continue on 7654 7655 7656/* ------------------------------ */ 7657 .balign 64 7658.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 7659/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7660 /* 7661 * Handle an optimized "super" method call. 7662 * 7663 * for: [opt] invoke-super-quick, invoke-super-quick/range 7664 */ 7665 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7666 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7667 FETCH(r10, 2) @ r10<- GFED or CCCC 7668 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7669 .if (!0) 7670 and r10, r10, #15 @ r10<- D (or stays CCCC) 7671 .endif 7672 FETCH(r1, 1) @ r1<- BBBB 7673 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7674 EXPORT_PC() @ must export for invoke 7675 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7676 GET_VREG(r3, r10) @ r3<- "this" 7677 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7678 cmp r3, #0 @ null "this" ref? 7679 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7680 beq common_errNullObject @ "this" is null, throw exception 7681 bl common_invokeMethodNoRange @ continue on 7682 7683 7684/* ------------------------------ */ 7685 .balign 64 7686.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 7687/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */ 7688/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */ 7689 /* 7690 * Handle an optimized "super" method call. 7691 * 7692 * for: [opt] invoke-super-quick, invoke-super-quick/range 7693 */ 7694 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 7695 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 7696 FETCH(r10, 2) @ r10<- GFED or CCCC 7697 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 7698 .if (!1) 7699 and r10, r10, #15 @ r10<- D (or stays CCCC) 7700 .endif 7701 FETCH(r1, 1) @ r1<- BBBB 7702 ldr r2, [r2, #offMethod_clazz] @ r2<- method->clazz 7703 EXPORT_PC() @ must export for invoke 7704 ldr r2, [r2, #offClassObject_super] @ r2<- method->clazz->super 7705 GET_VREG(r3, r10) @ r3<- "this" 7706 ldr r2, [r2, #offClassObject_vtable] @ r2<- ...clazz->super->vtable 7707 cmp r3, #0 @ null "this" ref? 7708 ldr r0, [r2, r1, lsl #2] @ r0<- super->vtable[BBBB] 7709 beq common_errNullObject @ "this" is null, throw exception 7710 bl common_invokeMethodRange @ continue on 7711 7712 7713 7714/* ------------------------------ */ 7715 .balign 64 7716.L_OP_UNUSED_FC: /* 0xfc */ 7717/* File: armv5te/OP_UNUSED_FC.S */ 7718/* File: armv5te/unused.S */ 7719 bl common_abort 7720 7721 7722 7723/* ------------------------------ */ 7724 .balign 64 7725.L_OP_UNUSED_FD: /* 0xfd */ 7726/* File: armv5te/OP_UNUSED_FD.S */ 7727/* File: armv5te/unused.S */ 7728 bl common_abort 7729 7730 7731 7732/* ------------------------------ */ 7733 .balign 64 7734.L_OP_UNUSED_FE: /* 0xfe */ 7735/* File: armv5te/OP_UNUSED_FE.S */ 7736/* File: armv5te/unused.S */ 7737 bl common_abort 7738 7739 7740 7741/* ------------------------------ */ 7742 .balign 64 7743.L_OP_UNUSED_FF: /* 0xff */ 7744/* File: armv5te/OP_UNUSED_FF.S */ 7745/* File: armv5te/unused.S */ 7746 bl common_abort 7747 7748 7749 7750 7751 .balign 64 7752 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 7753 .global dvmAsmInstructionEnd 7754dvmAsmInstructionEnd: 7755 7756/* 7757 * =========================================================================== 7758 * Sister implementations 7759 * =========================================================================== 7760 */ 7761 .global dvmAsmSisterStart 7762 .type dvmAsmSisterStart, %function 7763 .text 7764 .balign 4 7765dvmAsmSisterStart: 7766 7767/* continuation for OP_CONST_STRING */ 7768 7769 /* 7770 * Continuation if the String has not yet been resolved. 7771 * r1: BBBB (String ref) 7772 * r9: target register 7773 */ 7774.LOP_CONST_STRING_resolve: 7775 EXPORT_PC() 7776 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7777 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7778 bl dvmResolveString @ r0<- String reference 7779 cmp r0, #0 @ failed? 7780 beq common_exceptionThrown @ yup, handle the exception 7781 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7782 GET_INST_OPCODE(ip) @ extract opcode from rINST 7783 SET_VREG(r0, r9) @ vAA<- r0 7784 GOTO_OPCODE(ip) @ jump to next instruction 7785 7786 7787/* continuation for OP_CONST_STRING_JUMBO */ 7788 7789 /* 7790 * Continuation if the String has not yet been resolved. 7791 * r1: BBBBBBBB (String ref) 7792 * r9: target register 7793 */ 7794.LOP_CONST_STRING_JUMBO_resolve: 7795 EXPORT_PC() 7796 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7797 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7798 bl dvmResolveString @ r0<- String reference 7799 cmp r0, #0 @ failed? 7800 beq common_exceptionThrown @ yup, handle the exception 7801 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 7802 GET_INST_OPCODE(ip) @ extract opcode from rINST 7803 SET_VREG(r0, r9) @ vAA<- r0 7804 GOTO_OPCODE(ip) @ jump to next instruction 7805 7806 7807/* continuation for OP_CONST_CLASS */ 7808 7809 /* 7810 * Continuation if the Class has not yet been resolved. 7811 * r1: BBBB (Class ref) 7812 * r9: target register 7813 */ 7814.LOP_CONST_CLASS_resolve: 7815 EXPORT_PC() 7816 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7817 mov r2, #1 @ r2<- true 7818 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7819 bl dvmResolveClass @ r0<- Class reference 7820 cmp r0, #0 @ failed? 7821 beq common_exceptionThrown @ yup, handle the exception 7822 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7823 GET_INST_OPCODE(ip) @ extract opcode from rINST 7824 SET_VREG(r0, r9) @ vAA<- r0 7825 GOTO_OPCODE(ip) @ jump to next instruction 7826 7827 7828/* continuation for OP_CHECK_CAST */ 7829 7830 /* 7831 * Trivial test failed, need to perform full check. This is common. 7832 * r0 holds obj->clazz 7833 * r1 holds class resolved from BBBB 7834 * r9 holds object 7835 */ 7836.LOP_CHECK_CAST_fullcheck: 7837 bl dvmInstanceofNonTrivial @ r0<- boolean result 7838 cmp r0, #0 @ failed? 7839 bne .LOP_CHECK_CAST_okay @ no, success 7840 7841 @ A cast has failed. We need to throw a ClassCastException with the 7842 @ class of the object that failed to be cast. 7843 EXPORT_PC() @ about to throw 7844 ldr r3, [r9, #offObject_clazz] @ r3<- obj->clazz 7845 ldr r0, .LstrClassCastExceptionPtr 7846 ldr r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor 7847 bl dvmThrowExceptionWithClassMessage 7848 b common_exceptionThrown 7849 7850 /* 7851 * Resolution required. This is the least-likely path. 7852 * 7853 * r2 holds BBBB 7854 * r9 holds object 7855 */ 7856.LOP_CHECK_CAST_resolve: 7857 EXPORT_PC() @ resolve() could throw 7858 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7859 mov r1, r2 @ r1<- BBBB 7860 mov r2, #0 @ r2<- false 7861 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7862 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7863 cmp r0, #0 @ got null? 7864 beq common_exceptionThrown @ yes, handle exception 7865 mov r1, r0 @ r1<- class resolved from BBB 7866 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 7867 b .LOP_CHECK_CAST_resolved @ pick up where we left off 7868 7869.LstrClassCastExceptionPtr: 7870 .word .LstrClassCastException 7871 7872 7873/* continuation for OP_INSTANCE_OF */ 7874 7875 /* 7876 * Trivial test failed, need to perform full check. This is common. 7877 * r0 holds obj->clazz 7878 * r1 holds class resolved from BBBB 7879 * r9 holds A 7880 */ 7881.LOP_INSTANCE_OF_fullcheck: 7882 bl dvmInstanceofNonTrivial @ r0<- boolean result 7883 @ fall through to OP_INSTANCE_OF_store 7884 7885 /* 7886 * r0 holds boolean result 7887 * r9 holds A 7888 */ 7889.LOP_INSTANCE_OF_store: 7890 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7891 SET_VREG(r0, r9) @ vA<- r0 7892 GET_INST_OPCODE(ip) @ extract opcode from rINST 7893 GOTO_OPCODE(ip) @ jump to next instruction 7894 7895 /* 7896 * Trivial test succeeded, save and bail. 7897 * r9 holds A 7898 */ 7899.LOP_INSTANCE_OF_trivial: 7900 mov r0, #1 @ indicate success 7901 @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper 7902 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7903 SET_VREG(r0, r9) @ vA<- r0 7904 GET_INST_OPCODE(ip) @ extract opcode from rINST 7905 GOTO_OPCODE(ip) @ jump to next instruction 7906 7907 /* 7908 * Resolution required. This is the least-likely path. 7909 * 7910 * r3 holds BBBB 7911 * r9 holds A 7912 */ 7913.LOP_INSTANCE_OF_resolve: 7914 EXPORT_PC() @ resolve() could throw 7915 ldr r0, [rGLUE, #offGlue_method] @ r0<- glue->method 7916 mov r1, r3 @ r1<- BBBB 7917 mov r2, #1 @ r2<- true 7918 ldr r0, [r0, #offMethod_clazz] @ r0<- method->clazz 7919 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7920 cmp r0, #0 @ got null? 7921 beq common_exceptionThrown @ yes, handle exception 7922 mov r1, r0 @ r1<- class resolved from BBB 7923 mov r3, rINST, lsr #12 @ r3<- B 7924 GET_VREG(r0, r3) @ r0<- vB (object) 7925 ldr r0, [r0, #offObject_clazz] @ r0<- obj->clazz 7926 b .LOP_INSTANCE_OF_resolved @ pick up where we left off 7927 7928 7929/* continuation for OP_NEW_INSTANCE */ 7930 7931 .balign 32 @ minimize cache lines 7932.LOP_NEW_INSTANCE_finish: @ r0=new object 7933 mov r3, rINST, lsr #8 @ r3<- AA 7934 cmp r0, #0 @ failed? 7935 beq common_exceptionThrown @ yes, handle the exception 7936 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 7937 GET_INST_OPCODE(ip) @ extract opcode from rINST 7938 SET_VREG(r0, r3) @ vAA<- r0 7939 GOTO_OPCODE(ip) @ jump to next instruction 7940 7941 /* 7942 * Class initialization required. 7943 * 7944 * r0 holds class object 7945 */ 7946.LOP_NEW_INSTANCE_needinit: 7947 mov r9, r0 @ save r0 7948 bl dvmInitClass @ initialize class 7949 cmp r0, #0 @ check boolean result 7950 mov r0, r9 @ restore r0 7951 bne .LOP_NEW_INSTANCE_initialized @ success, continue 7952 b common_exceptionThrown @ failed, deal with init exception 7953 7954 /* 7955 * Resolution required. This is the least-likely path. 7956 * 7957 * r1 holds BBBB 7958 */ 7959.LOP_NEW_INSTANCE_resolve: 7960 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7961 mov r2, #0 @ r2<- false 7962 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7963 bl dvmResolveClass @ r0<- resolved ClassObject ptr 7964 cmp r0, #0 @ got null? 7965 bne .LOP_NEW_INSTANCE_resolved @ no, continue 7966 b common_exceptionThrown @ yes, handle exception 7967 7968.LstrInstantiationErrorPtr: 7969 .word .LstrInstantiationError 7970 7971 7972/* continuation for OP_NEW_ARRAY */ 7973 7974 7975 /* 7976 * Resolve class. (This is an uncommon case.) 7977 * 7978 * r1 holds array length 7979 * r2 holds class ref CCCC 7980 */ 7981.LOP_NEW_ARRAY_resolve: 7982 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 7983 mov r9, r1 @ r9<- length (save) 7984 mov r1, r2 @ r1<- CCCC 7985 mov r2, #0 @ r2<- false 7986 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 7987 bl dvmResolveClass @ r0<- call(clazz, ref) 7988 cmp r0, #0 @ got null? 7989 mov r1, r9 @ r1<- length (restore) 7990 beq common_exceptionThrown @ yes, handle exception 7991 @ fall through to OP_NEW_ARRAY_finish 7992 7993 /* 7994 * Finish allocation. 7995 * 7996 * r0 holds class 7997 * r1 holds array length 7998 */ 7999.LOP_NEW_ARRAY_finish: 8000 mov r2, #ALLOC_DONT_TRACK @ don't track in local refs table 8001 bl dvmAllocArrayByClass @ r0<- call(clazz, length, flags) 8002 cmp r0, #0 @ failed? 8003 mov r2, rINST, lsr #8 @ r2<- A+ 8004 beq common_exceptionThrown @ yes, handle the exception 8005 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8006 and r2, r2, #15 @ r2<- A 8007 GET_INST_OPCODE(ip) @ extract opcode from rINST 8008 SET_VREG(r0, r2) @ vA<- r0 8009 GOTO_OPCODE(ip) @ jump to next instruction 8010 8011 8012/* continuation for OP_FILLED_NEW_ARRAY */ 8013 8014 /* 8015 * On entry: 8016 * r0 holds array class 8017 * r10 holds AA or BA 8018 */ 8019.LOP_FILLED_NEW_ARRAY_continue: 8020 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8021 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8022 ldrb r3, [r3, #1] @ r3<- descriptor[1] 8023 .if 0 8024 mov r1, r10 @ r1<- AA (length) 8025 .else 8026 mov r1, r10, lsr #4 @ r1<- B (length) 8027 .endif 8028 cmp r3, #'I' @ array of ints? 8029 cmpne r3, #'L' @ array of objects? 8030 cmpne r3, #'[' @ array of arrays? 8031 mov r9, r1 @ save length in r9 8032 bne .LOP_FILLED_NEW_ARRAY_notimpl @ no, not handled yet 8033 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8034 cmp r0, #0 @ null return? 8035 beq common_exceptionThrown @ alloc failed, handle exception 8036 8037 FETCH(r1, 2) @ r1<- FEDC or CCCC 8038 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8039 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8040 subs r9, r9, #1 @ length--, check for neg 8041 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8042 bmi 2f @ was zero, bail 8043 8044 @ copy values from registers into the array 8045 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8046 .if 0 8047 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 80481: ldr r3, [r2], #4 @ r3<- *r2++ 8049 subs r9, r9, #1 @ count-- 8050 str r3, [r0], #4 @ *contents++ = vX 8051 bpl 1b 8052 @ continue at 2 8053 .else 8054 cmp r9, #4 @ length was initially 5? 8055 and r2, r10, #15 @ r2<- A 8056 bne 1f @ <= 4 args, branch 8057 GET_VREG(r3, r2) @ r3<- vA 8058 sub r9, r9, #1 @ count-- 8059 str r3, [r0, #16] @ contents[4] = vA 80601: and r2, r1, #15 @ r2<- F/E/D/C 8061 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8062 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8063 subs r9, r9, #1 @ count-- 8064 str r3, [r0], #4 @ *contents++ = vX 8065 bpl 1b 8066 @ continue at 2 8067 .endif 8068 80692: 8070 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8071 GOTO_OPCODE(ip) @ execute it 8072 8073 /* 8074 * Throw an exception indicating that we have not implemented this 8075 * mode of filled-new-array. 8076 */ 8077.LOP_FILLED_NEW_ARRAY_notimpl: 8078 ldr r0, .L_strInternalError 8079 ldr r1, .L_strFilledNewArrayNotImpl 8080 bl dvmThrowException 8081 b common_exceptionThrown 8082 8083 .if (!0) @ define in one or the other, not both 8084.L_strFilledNewArrayNotImpl: 8085 .word .LstrFilledNewArrayNotImpl 8086.L_strInternalError: 8087 .word .LstrInternalError 8088 .endif 8089 8090 8091/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 8092 8093 /* 8094 * On entry: 8095 * r0 holds array class 8096 * r10 holds AA or BA 8097 */ 8098.LOP_FILLED_NEW_ARRAY_RANGE_continue: 8099 ldr r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor 8100 mov r2, #ALLOC_DONT_TRACK @ r2<- alloc flags 8101 ldrb r3, [r3, #1] @ r3<- descriptor[1] 8102 .if 1 8103 mov r1, r10 @ r1<- AA (length) 8104 .else 8105 mov r1, r10, lsr #4 @ r1<- B (length) 8106 .endif 8107 cmp r3, #'I' @ array of ints? 8108 cmpne r3, #'L' @ array of objects? 8109 cmpne r3, #'[' @ array of arrays? 8110 mov r9, r1 @ save length in r9 8111 bne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl @ no, not handled yet 8112 bl dvmAllocArrayByClass @ r0<- call(arClass, length, flags) 8113 cmp r0, #0 @ null return? 8114 beq common_exceptionThrown @ alloc failed, handle exception 8115 8116 FETCH(r1, 2) @ r1<- FEDC or CCCC 8117 str r0, [rGLUE, #offGlue_retval] @ retval.l <- new array 8118 add r0, r0, #offArrayObject_contents @ r0<- newArray->contents 8119 subs r9, r9, #1 @ length--, check for neg 8120 FETCH_ADVANCE_INST(3) @ advance to next instr, load rINST 8121 bmi 2f @ was zero, bail 8122 8123 @ copy values from registers into the array 8124 @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA 8125 .if 1 8126 add r2, rFP, r1, lsl #2 @ r2<- &fp[CCCC] 81271: ldr r3, [r2], #4 @ r3<- *r2++ 8128 subs r9, r9, #1 @ count-- 8129 str r3, [r0], #4 @ *contents++ = vX 8130 bpl 1b 8131 @ continue at 2 8132 .else 8133 cmp r9, #4 @ length was initially 5? 8134 and r2, r10, #15 @ r2<- A 8135 bne 1f @ <= 4 args, branch 8136 GET_VREG(r3, r2) @ r3<- vA 8137 sub r9, r9, #1 @ count-- 8138 str r3, [r0, #16] @ contents[4] = vA 81391: and r2, r1, #15 @ r2<- F/E/D/C 8140 GET_VREG(r3, r2) @ r3<- vF/vE/vD/vC 8141 mov r1, r1, lsr #4 @ r1<- next reg in low 4 8142 subs r9, r9, #1 @ count-- 8143 str r3, [r0], #4 @ *contents++ = vX 8144 bpl 1b 8145 @ continue at 2 8146 .endif 8147 81482: 8149 GET_INST_OPCODE(ip) @ ip<- opcode from rINST 8150 GOTO_OPCODE(ip) @ execute it 8151 8152 /* 8153 * Throw an exception indicating that we have not implemented this 8154 * mode of filled-new-array. 8155 */ 8156.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 8157 ldr r0, .L_strInternalError 8158 ldr r1, .L_strFilledNewArrayNotImpl 8159 bl dvmThrowException 8160 b common_exceptionThrown 8161 8162 .if (!1) @ define in one or the other, not both 8163.L_strFilledNewArrayNotImpl: 8164 .word .LstrFilledNewArrayNotImpl 8165.L_strInternalError: 8166 .word .LstrInternalError 8167 .endif 8168 8169 8170/* continuation for OP_CMPL_FLOAT */ 8171.LOP_CMPL_FLOAT_finish: 8172 SET_VREG(r0, r9) @ vAA<- r0 8173 GOTO_OPCODE(ip) @ jump to next instruction 8174 8175 8176/* continuation for OP_CMPG_FLOAT */ 8177.LOP_CMPG_FLOAT_finish: 8178 SET_VREG(r0, r9) @ vAA<- r0 8179 GOTO_OPCODE(ip) @ jump to next instruction 8180 8181 8182/* continuation for OP_CMPL_DOUBLE */ 8183.LOP_CMPL_DOUBLE_finish: 8184 SET_VREG(r0, r9) @ vAA<- r0 8185 GOTO_OPCODE(ip) @ jump to next instruction 8186 8187 8188/* continuation for OP_CMPG_DOUBLE */ 8189.LOP_CMPG_DOUBLE_finish: 8190 SET_VREG(r0, r9) @ vAA<- r0 8191 GOTO_OPCODE(ip) @ jump to next instruction 8192 8193 8194/* continuation for OP_CMP_LONG */ 8195 8196.LOP_CMP_LONG_less: 8197 mvn r1, #0 @ r1<- -1 8198 @ Want to cond code the next mov so we can avoid branch, but don't see it; 8199 @ instead, we just replicate the tail end. 8200 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8201 SET_VREG(r1, r9) @ vAA<- r1 8202 GET_INST_OPCODE(ip) @ extract opcode from rINST 8203 GOTO_OPCODE(ip) @ jump to next instruction 8204 8205.LOP_CMP_LONG_greater: 8206 mov r1, #1 @ r1<- 1 8207 @ fall through to _finish 8208 8209.LOP_CMP_LONG_finish: 8210 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8211 SET_VREG(r1, r9) @ vAA<- r1 8212 GET_INST_OPCODE(ip) @ extract opcode from rINST 8213 GOTO_OPCODE(ip) @ jump to next instruction 8214 8215 8216/* continuation for OP_AGET_WIDE */ 8217 8218.LOP_AGET_WIDE_finish: 8219 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8220 ldrd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8221 add r9, rFP, r9, lsl #2 @ r9<- &fp[AA] 8222 GET_INST_OPCODE(ip) @ extract opcode from rINST 8223 stmia r9, {r2-r3} @ vAA/vAA+1<- r2/r3 8224 GOTO_OPCODE(ip) @ jump to next instruction 8225 8226 8227/* continuation for OP_APUT_WIDE */ 8228 8229.LOP_APUT_WIDE_finish: 8230 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8231 ldmia r9, {r2-r3} @ r2/r3<- vAA/vAA+1 8232 GET_INST_OPCODE(ip) @ extract opcode from rINST 8233 strd r2, [r0, #offArrayObject_contents] @ r2/r3<- vBB[vCC] 8234 GOTO_OPCODE(ip) @ jump to next instruction 8235 8236 8237/* continuation for OP_APUT_OBJECT */ 8238 /* 8239 * On entry: 8240 * r1 = vBB (arrayObj) 8241 * r9 = vAA (obj) 8242 * r10 = offset into array (vBB + vCC * width) 8243 */ 8244.LOP_APUT_OBJECT_finish: 8245 cmp r9, #0 @ storing null reference? 8246 beq .LOP_APUT_OBJECT_skip_check @ yes, skip type checks 8247 ldr r0, [r9, #offObject_clazz] @ r0<- obj->clazz 8248 ldr r1, [r1, #offObject_clazz] @ r1<- arrayObj->clazz 8249 bl dvmCanPutArrayElement @ test object type vs. array type 8250 cmp r0, #0 @ okay? 8251 beq common_errArrayStore @ no 8252.LOP_APUT_OBJECT_skip_check: 8253 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8254 GET_INST_OPCODE(ip) @ extract opcode from rINST 8255 str r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA 8256 GOTO_OPCODE(ip) @ jump to next instruction 8257 8258 8259/* continuation for OP_IGET */ 8260 8261 /* 8262 * Currently: 8263 * r0 holds resolved field 8264 * r9 holds object 8265 */ 8266.LOP_IGET_finish: 8267 @bl common_squeak0 8268 cmp r9, #0 @ check object for null 8269 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8270 beq common_errNullObject @ object was null 8271 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8272 mov r2, rINST, lsr #8 @ r2<- A+ 8273 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8274 and r2, r2, #15 @ r2<- A 8275 GET_INST_OPCODE(ip) @ extract opcode from rINST 8276 SET_VREG(r0, r2) @ fp[A]<- r0 8277 GOTO_OPCODE(ip) @ jump to next instruction 8278 8279 8280/* continuation for OP_IGET_WIDE */ 8281 8282 /* 8283 * Currently: 8284 * r0 holds resolved field 8285 * r9 holds object 8286 */ 8287.LOP_IGET_WIDE_finish: 8288 cmp r9, #0 @ check object for null 8289 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8290 beq common_errNullObject @ object was null 8291 .if 0 8292 add r0, r9, r3 @ r0<- address of field 8293 bl android_quasiatomic_read_64 @ r0/r1<- contents of field 8294 .else 8295 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 8296 .endif 8297 mov r2, rINST, lsr #8 @ r2<- A+ 8298 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8299 and r2, r2, #15 @ r2<- A 8300 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 8301 GET_INST_OPCODE(ip) @ extract opcode from rINST 8302 stmia r3, {r0-r1} @ fp[A]<- r0/r1 8303 GOTO_OPCODE(ip) @ jump to next instruction 8304 8305 8306/* continuation for OP_IGET_OBJECT */ 8307 8308 /* 8309 * Currently: 8310 * r0 holds resolved field 8311 * r9 holds object 8312 */ 8313.LOP_IGET_OBJECT_finish: 8314 @bl common_squeak0 8315 cmp r9, #0 @ check object for null 8316 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8317 beq common_errNullObject @ object was null 8318 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8319 mov r2, rINST, lsr #8 @ r2<- A+ 8320 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8321 and r2, r2, #15 @ r2<- A 8322 GET_INST_OPCODE(ip) @ extract opcode from rINST 8323 SET_VREG(r0, r2) @ fp[A]<- r0 8324 GOTO_OPCODE(ip) @ jump to next instruction 8325 8326 8327/* continuation for OP_IGET_BOOLEAN */ 8328 8329 /* 8330 * Currently: 8331 * r0 holds resolved field 8332 * r9 holds object 8333 */ 8334.LOP_IGET_BOOLEAN_finish: 8335 @bl common_squeak1 8336 cmp r9, #0 @ check object for null 8337 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8338 beq common_errNullObject @ object was null 8339 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8340 mov r2, rINST, lsr #8 @ r2<- A+ 8341 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8342 and r2, r2, #15 @ r2<- A 8343 GET_INST_OPCODE(ip) @ extract opcode from rINST 8344 SET_VREG(r0, r2) @ fp[A]<- r0 8345 GOTO_OPCODE(ip) @ jump to next instruction 8346 8347 8348/* continuation for OP_IGET_BYTE */ 8349 8350 /* 8351 * Currently: 8352 * r0 holds resolved field 8353 * r9 holds object 8354 */ 8355.LOP_IGET_BYTE_finish: 8356 @bl common_squeak2 8357 cmp r9, #0 @ check object for null 8358 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8359 beq common_errNullObject @ object was null 8360 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8361 mov r2, rINST, lsr #8 @ r2<- A+ 8362 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8363 and r2, r2, #15 @ r2<- A 8364 GET_INST_OPCODE(ip) @ extract opcode from rINST 8365 SET_VREG(r0, r2) @ fp[A]<- r0 8366 GOTO_OPCODE(ip) @ jump to next instruction 8367 8368 8369/* continuation for OP_IGET_CHAR */ 8370 8371 /* 8372 * Currently: 8373 * r0 holds resolved field 8374 * r9 holds object 8375 */ 8376.LOP_IGET_CHAR_finish: 8377 @bl common_squeak3 8378 cmp r9, #0 @ check object for null 8379 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8380 beq common_errNullObject @ object was null 8381 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8382 mov r2, rINST, lsr #8 @ r2<- A+ 8383 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8384 and r2, r2, #15 @ r2<- A 8385 GET_INST_OPCODE(ip) @ extract opcode from rINST 8386 SET_VREG(r0, r2) @ fp[A]<- r0 8387 GOTO_OPCODE(ip) @ jump to next instruction 8388 8389 8390/* continuation for OP_IGET_SHORT */ 8391 8392 /* 8393 * Currently: 8394 * r0 holds resolved field 8395 * r9 holds object 8396 */ 8397.LOP_IGET_SHORT_finish: 8398 @bl common_squeak4 8399 cmp r9, #0 @ check object for null 8400 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8401 beq common_errNullObject @ object was null 8402 ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) 8403 mov r2, rINST, lsr #8 @ r2<- A+ 8404 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8405 and r2, r2, #15 @ r2<- A 8406 GET_INST_OPCODE(ip) @ extract opcode from rINST 8407 SET_VREG(r0, r2) @ fp[A]<- r0 8408 GOTO_OPCODE(ip) @ jump to next instruction 8409 8410 8411/* continuation for OP_IPUT */ 8412 8413 /* 8414 * Currently: 8415 * r0 holds resolved field 8416 * r9 holds object 8417 */ 8418.LOP_IPUT_finish: 8419 @bl common_squeak0 8420 mov r1, rINST, lsr #8 @ r1<- A+ 8421 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8422 and r1, r1, #15 @ r1<- A 8423 cmp r9, #0 @ check object for null 8424 GET_VREG(r0, r1) @ r0<- fp[A] 8425 beq common_errNullObject @ object was null 8426 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8427 GET_INST_OPCODE(ip) @ extract opcode from rINST 8428 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8429 GOTO_OPCODE(ip) @ jump to next instruction 8430 8431 8432/* continuation for OP_IPUT_WIDE */ 8433 8434 /* 8435 * Currently: 8436 * r0 holds resolved field 8437 * r9 holds object 8438 */ 8439.LOP_IPUT_WIDE_finish: 8440 mov r2, rINST, lsr #8 @ r2<- A+ 8441 cmp r9, #0 @ check object for null 8442 and r2, r2, #15 @ r2<- A 8443 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8444 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 8445 beq common_errNullObject @ object was null 8446 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8447 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 8448 GET_INST_OPCODE(r10) @ extract opcode from rINST 8449 .if 0 8450 add r2, r9, r3 @ r2<- target address 8451 bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2 8452 .else 8453 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 8454 .endif 8455 GOTO_OPCODE(r10) @ jump to next instruction 8456 8457 8458/* continuation for OP_IPUT_OBJECT */ 8459 8460 /* 8461 * Currently: 8462 * r0 holds resolved field 8463 * r9 holds object 8464 */ 8465.LOP_IPUT_OBJECT_finish: 8466 @bl common_squeak0 8467 mov r1, rINST, lsr #8 @ r1<- A+ 8468 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8469 and r1, r1, #15 @ r1<- A 8470 cmp r9, #0 @ check object for null 8471 GET_VREG(r0, r1) @ r0<- fp[A] 8472 beq common_errNullObject @ object was null 8473 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8474 GET_INST_OPCODE(ip) @ extract opcode from rINST 8475 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8476 GOTO_OPCODE(ip) @ jump to next instruction 8477 8478 8479/* continuation for OP_IPUT_BOOLEAN */ 8480 8481 /* 8482 * Currently: 8483 * r0 holds resolved field 8484 * r9 holds object 8485 */ 8486.LOP_IPUT_BOOLEAN_finish: 8487 @bl common_squeak1 8488 mov r1, rINST, lsr #8 @ r1<- A+ 8489 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8490 and r1, r1, #15 @ r1<- A 8491 cmp r9, #0 @ check object for null 8492 GET_VREG(r0, r1) @ r0<- fp[A] 8493 beq common_errNullObject @ object was null 8494 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8495 GET_INST_OPCODE(ip) @ extract opcode from rINST 8496 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8497 GOTO_OPCODE(ip) @ jump to next instruction 8498 8499 8500/* continuation for OP_IPUT_BYTE */ 8501 8502 /* 8503 * Currently: 8504 * r0 holds resolved field 8505 * r9 holds object 8506 */ 8507.LOP_IPUT_BYTE_finish: 8508 @bl common_squeak2 8509 mov r1, rINST, lsr #8 @ r1<- A+ 8510 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8511 and r1, r1, #15 @ r1<- A 8512 cmp r9, #0 @ check object for null 8513 GET_VREG(r0, r1) @ r0<- fp[A] 8514 beq common_errNullObject @ object was null 8515 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8516 GET_INST_OPCODE(ip) @ extract opcode from rINST 8517 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8518 GOTO_OPCODE(ip) @ jump to next instruction 8519 8520 8521/* continuation for OP_IPUT_CHAR */ 8522 8523 /* 8524 * Currently: 8525 * r0 holds resolved field 8526 * r9 holds object 8527 */ 8528.LOP_IPUT_CHAR_finish: 8529 @bl common_squeak3 8530 mov r1, rINST, lsr #8 @ r1<- A+ 8531 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8532 and r1, r1, #15 @ r1<- A 8533 cmp r9, #0 @ check object for null 8534 GET_VREG(r0, r1) @ r0<- fp[A] 8535 beq common_errNullObject @ object was null 8536 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8537 GET_INST_OPCODE(ip) @ extract opcode from rINST 8538 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8539 GOTO_OPCODE(ip) @ jump to next instruction 8540 8541 8542/* continuation for OP_IPUT_SHORT */ 8543 8544 /* 8545 * Currently: 8546 * r0 holds resolved field 8547 * r9 holds object 8548 */ 8549.LOP_IPUT_SHORT_finish: 8550 @bl common_squeak4 8551 mov r1, rINST, lsr #8 @ r1<- A+ 8552 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 8553 and r1, r1, #15 @ r1<- A 8554 cmp r9, #0 @ check object for null 8555 GET_VREG(r0, r1) @ r0<- fp[A] 8556 beq common_errNullObject @ object was null 8557 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 8558 GET_INST_OPCODE(ip) @ extract opcode from rINST 8559 str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 8560 GOTO_OPCODE(ip) @ jump to next instruction 8561 8562 8563/* continuation for OP_SGET */ 8564 8565 /* 8566 * Continuation if the field has not yet been resolved. 8567 * r1: BBBB field ref 8568 */ 8569.LOP_SGET_resolve: 8570 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8571 EXPORT_PC() @ resolve() could throw, so export now 8572 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8573 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8574 cmp r0, #0 @ success? 8575 bne .LOP_SGET_finish @ yes, finish 8576 b common_exceptionThrown @ no, handle exception 8577 8578 8579/* continuation for OP_SGET_WIDE */ 8580 8581 /* 8582 * Continuation if the field has not yet been resolved. 8583 * r1: BBBB field ref 8584 * 8585 * Returns StaticField pointer in r0. 8586 */ 8587.LOP_SGET_WIDE_resolve: 8588 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8589 EXPORT_PC() @ resolve() could throw, so export now 8590 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8591 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8592 cmp r0, #0 @ success? 8593 bne .LOP_SGET_WIDE_finish @ yes, finish 8594 b common_exceptionThrown @ no, handle exception 8595 8596 8597/* continuation for OP_SGET_OBJECT */ 8598 8599 /* 8600 * Continuation if the field has not yet been resolved. 8601 * r1: BBBB field ref 8602 */ 8603.LOP_SGET_OBJECT_resolve: 8604 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8605 EXPORT_PC() @ resolve() could throw, so export now 8606 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8607 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8608 cmp r0, #0 @ success? 8609 bne .LOP_SGET_OBJECT_finish @ yes, finish 8610 b common_exceptionThrown @ no, handle exception 8611 8612 8613/* continuation for OP_SGET_BOOLEAN */ 8614 8615 /* 8616 * Continuation if the field has not yet been resolved. 8617 * r1: BBBB field ref 8618 */ 8619.LOP_SGET_BOOLEAN_resolve: 8620 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8621 EXPORT_PC() @ resolve() could throw, so export now 8622 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8623 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8624 cmp r0, #0 @ success? 8625 bne .LOP_SGET_BOOLEAN_finish @ yes, finish 8626 b common_exceptionThrown @ no, handle exception 8627 8628 8629/* continuation for OP_SGET_BYTE */ 8630 8631 /* 8632 * Continuation if the field has not yet been resolved. 8633 * r1: BBBB field ref 8634 */ 8635.LOP_SGET_BYTE_resolve: 8636 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8637 EXPORT_PC() @ resolve() could throw, so export now 8638 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8639 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8640 cmp r0, #0 @ success? 8641 bne .LOP_SGET_BYTE_finish @ yes, finish 8642 b common_exceptionThrown @ no, handle exception 8643 8644 8645/* continuation for OP_SGET_CHAR */ 8646 8647 /* 8648 * Continuation if the field has not yet been resolved. 8649 * r1: BBBB field ref 8650 */ 8651.LOP_SGET_CHAR_resolve: 8652 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8653 EXPORT_PC() @ resolve() could throw, so export now 8654 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8655 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8656 cmp r0, #0 @ success? 8657 bne .LOP_SGET_CHAR_finish @ yes, finish 8658 b common_exceptionThrown @ no, handle exception 8659 8660 8661/* continuation for OP_SGET_SHORT */ 8662 8663 /* 8664 * Continuation if the field has not yet been resolved. 8665 * r1: BBBB field ref 8666 */ 8667.LOP_SGET_SHORT_resolve: 8668 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8669 EXPORT_PC() @ resolve() could throw, so export now 8670 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8671 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8672 cmp r0, #0 @ success? 8673 bne .LOP_SGET_SHORT_finish @ yes, finish 8674 b common_exceptionThrown @ no, handle exception 8675 8676 8677/* continuation for OP_SPUT */ 8678 8679 /* 8680 * Continuation if the field has not yet been resolved. 8681 * r1: BBBB field ref 8682 */ 8683.LOP_SPUT_resolve: 8684 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8685 EXPORT_PC() @ resolve() could throw, so export now 8686 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8687 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8688 cmp r0, #0 @ success? 8689 bne .LOP_SPUT_finish @ yes, finish 8690 b common_exceptionThrown @ no, handle exception 8691 8692 8693/* continuation for OP_SPUT_WIDE */ 8694 8695 /* 8696 * Continuation if the field has not yet been resolved. 8697 * r1: BBBB field ref 8698 * r9: &fp[AA] 8699 * 8700 * Returns StaticField pointer in r2. 8701 */ 8702.LOP_SPUT_WIDE_resolve: 8703 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8704 EXPORT_PC() @ resolve() could throw, so export now 8705 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8706 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8707 cmp r0, #0 @ success? 8708 mov r2, r0 @ copy to r2 8709 bne .LOP_SPUT_WIDE_finish @ yes, finish 8710 b common_exceptionThrown @ no, handle exception 8711 8712 8713/* continuation for OP_SPUT_OBJECT */ 8714 8715 /* 8716 * Continuation if the field has not yet been resolved. 8717 * r1: BBBB field ref 8718 */ 8719.LOP_SPUT_OBJECT_resolve: 8720 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8721 EXPORT_PC() @ resolve() could throw, so export now 8722 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8723 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8724 cmp r0, #0 @ success? 8725 bne .LOP_SPUT_OBJECT_finish @ yes, finish 8726 b common_exceptionThrown @ no, handle exception 8727 8728 8729/* continuation for OP_SPUT_BOOLEAN */ 8730 8731 /* 8732 * Continuation if the field has not yet been resolved. 8733 * r1: BBBB field ref 8734 */ 8735.LOP_SPUT_BOOLEAN_resolve: 8736 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8737 EXPORT_PC() @ resolve() could throw, so export now 8738 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8739 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8740 cmp r0, #0 @ success? 8741 bne .LOP_SPUT_BOOLEAN_finish @ yes, finish 8742 b common_exceptionThrown @ no, handle exception 8743 8744 8745/* continuation for OP_SPUT_BYTE */ 8746 8747 /* 8748 * Continuation if the field has not yet been resolved. 8749 * r1: BBBB field ref 8750 */ 8751.LOP_SPUT_BYTE_resolve: 8752 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8753 EXPORT_PC() @ resolve() could throw, so export now 8754 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8755 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8756 cmp r0, #0 @ success? 8757 bne .LOP_SPUT_BYTE_finish @ yes, finish 8758 b common_exceptionThrown @ no, handle exception 8759 8760 8761/* continuation for OP_SPUT_CHAR */ 8762 8763 /* 8764 * Continuation if the field has not yet been resolved. 8765 * r1: BBBB field ref 8766 */ 8767.LOP_SPUT_CHAR_resolve: 8768 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8769 EXPORT_PC() @ resolve() could throw, so export now 8770 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8771 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8772 cmp r0, #0 @ success? 8773 bne .LOP_SPUT_CHAR_finish @ yes, finish 8774 b common_exceptionThrown @ no, handle exception 8775 8776 8777/* continuation for OP_SPUT_SHORT */ 8778 8779 /* 8780 * Continuation if the field has not yet been resolved. 8781 * r1: BBBB field ref 8782 */ 8783.LOP_SPUT_SHORT_resolve: 8784 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 8785 EXPORT_PC() @ resolve() could throw, so export now 8786 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 8787 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 8788 cmp r0, #0 @ success? 8789 bne .LOP_SPUT_SHORT_finish @ yes, finish 8790 b common_exceptionThrown @ no, handle exception 8791 8792 8793/* continuation for OP_INVOKE_VIRTUAL */ 8794 8795 /* 8796 * At this point: 8797 * r0 = resolved base method 8798 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8799 */ 8800.LOP_INVOKE_VIRTUAL_continue: 8801 GET_VREG(r1, r10) @ r1<- "this" ptr 8802 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8803 cmp r1, #0 @ is "this" null? 8804 beq common_errNullObject @ null "this", throw exception 8805 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8806 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8807 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8808 bl common_invokeMethodNoRange @ continue on 8809 8810 8811/* continuation for OP_INVOKE_SUPER */ 8812 8813 /* 8814 * At this point: 8815 * r0 = resolved base method 8816 * r9 = method->clazz 8817 */ 8818.LOP_INVOKE_SUPER_continue: 8819 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8820 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8821 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8822 EXPORT_PC() @ must export for invoke 8823 cmp r2, r3 @ compare (methodIndex, vtableCount) 8824 bcs .LOP_INVOKE_SUPER_nsm @ method not present in superclass 8825 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8826 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8827 bl common_invokeMethodNoRange @ continue on 8828 8829.LOP_INVOKE_SUPER_resolve: 8830 mov r0, r9 @ r0<- method->clazz 8831 mov r2, #METHOD_VIRTUAL @ resolver method type 8832 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8833 cmp r0, #0 @ got null? 8834 bne .LOP_INVOKE_SUPER_continue @ no, continue 8835 b common_exceptionThrown @ yes, handle exception 8836 8837 /* 8838 * Throw a NoSuchMethodError with the method name as the message. 8839 * r0 = resolved base method 8840 */ 8841.LOP_INVOKE_SUPER_nsm: 8842 ldr r1, [r0, #offMethod_name] @ r1<- method name 8843 b common_errNoSuchMethod 8844 8845 8846/* continuation for OP_INVOKE_DIRECT */ 8847 8848 /* 8849 * On entry: 8850 * r1 = reference (BBBB or CCCC) 8851 * r10 = "this" register 8852 */ 8853.LOP_INVOKE_DIRECT_resolve: 8854 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8855 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8856 mov r2, #METHOD_DIRECT @ resolver method type 8857 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8858 cmp r0, #0 @ got null? 8859 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8860 bne .LOP_INVOKE_DIRECT_finish @ no, continue 8861 b common_exceptionThrown @ yes, handle exception 8862 8863 8864/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 8865 8866 /* 8867 * At this point: 8868 * r0 = resolved base method 8869 * r10 = C or CCCC (index of first arg, which is the "this" ptr) 8870 */ 8871.LOP_INVOKE_VIRTUAL_RANGE_continue: 8872 GET_VREG(r1, r10) @ r1<- "this" ptr 8873 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8874 cmp r1, #0 @ is "this" null? 8875 beq common_errNullObject @ null "this", throw exception 8876 ldr r3, [r1, #offObject_clazz] @ r1<- thisPtr->clazz 8877 ldr r3, [r3, #offClassObject_vtable] @ r3<- thisPtr->clazz->vtable 8878 ldr r0, [r3, r2, lsl #2] @ r3<- vtable[methodIndex] 8879 bl common_invokeMethodRange @ continue on 8880 8881 8882/* continuation for OP_INVOKE_SUPER_RANGE */ 8883 8884 /* 8885 * At this point: 8886 * r0 = resolved base method 8887 * r9 = method->clazz 8888 */ 8889.LOP_INVOKE_SUPER_RANGE_continue: 8890 ldr r1, [r9, #offClassObject_super] @ r1<- method->clazz->super 8891 ldrh r2, [r0, #offMethod_methodIndex] @ r2<- baseMethod->methodIndex 8892 ldr r3, [r1, #offClassObject_vtableCount] @ r3<- super->vtableCount 8893 EXPORT_PC() @ must export for invoke 8894 cmp r2, r3 @ compare (methodIndex, vtableCount) 8895 bcs .LOP_INVOKE_SUPER_RANGE_nsm @ method not present in superclass 8896 ldr r1, [r1, #offClassObject_vtable] @ r1<- ...clazz->super->vtable 8897 ldr r0, [r1, r2, lsl #2] @ r3<- vtable[methodIndex] 8898 bl common_invokeMethodRange @ continue on 8899 8900.LOP_INVOKE_SUPER_RANGE_resolve: 8901 mov r0, r9 @ r0<- method->clazz 8902 mov r2, #METHOD_VIRTUAL @ resolver method type 8903 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8904 cmp r0, #0 @ got null? 8905 bne .LOP_INVOKE_SUPER_RANGE_continue @ no, continue 8906 b common_exceptionThrown @ yes, handle exception 8907 8908 /* 8909 * Throw a NoSuchMethodError with the method name as the message. 8910 * r0 = resolved base method 8911 */ 8912.LOP_INVOKE_SUPER_RANGE_nsm: 8913 ldr r1, [r0, #offMethod_name] @ r1<- method name 8914 b common_errNoSuchMethod 8915 8916 8917/* continuation for OP_INVOKE_DIRECT_RANGE */ 8918 8919 /* 8920 * On entry: 8921 * r1 = reference (BBBB or CCCC) 8922 * r10 = "this" register 8923 */ 8924.LOP_INVOKE_DIRECT_RANGE_resolve: 8925 ldr r3, [rGLUE, #offGlue_method] @ r3<- glue->method 8926 ldr r0, [r3, #offMethod_clazz] @ r0<- method->clazz 8927 mov r2, #METHOD_DIRECT @ resolver method type 8928 bl dvmResolveMethod @ r0<- call(clazz, ref, flags) 8929 cmp r0, #0 @ got null? 8930 GET_VREG(r2, r10) @ r2<- "this" ptr (reload) 8931 bne .LOP_INVOKE_DIRECT_RANGE_finish @ no, continue 8932 b common_exceptionThrown @ yes, handle exception 8933 8934 8935/* continuation for OP_FLOAT_TO_LONG */ 8936/* 8937 * Convert the float in r0 to a long in r0/r1. 8938 * 8939 * We have to clip values to long min/max per the specification. The 8940 * expected common case is a "reasonable" value that converts directly 8941 * to modest integer. The EABI convert function isn't doing this for us. 8942 */ 8943f2l_doconv: 8944 stmfd sp!, {r4, lr} 8945 mov r1, #0x5f000000 @ (float)maxlong 8946 mov r4, r0 8947 bl __aeabi_fcmpge @ is arg >= maxlong? 8948 cmp r0, #0 @ nonzero == yes 8949 mvnne r0, #0 @ return maxlong (7fffffff) 8950 mvnne r1, #0x80000000 8951 ldmnefd sp!, {r4, pc} 8952 8953 mov r0, r4 @ recover arg 8954 mov r1, #0xdf000000 @ (float)minlong 8955 bl __aeabi_fcmple @ is arg <= minlong? 8956 cmp r0, #0 @ nonzero == yes 8957 movne r0, #0 @ return minlong (80000000) 8958 movne r1, #0x80000000 8959 ldmnefd sp!, {r4, pc} 8960 8961 mov r0, r4 @ recover arg 8962 mov r1, r4 8963 bl __aeabi_fcmpeq @ is arg == self? 8964 cmp r0, #0 @ zero == no 8965 moveq r1, #0 @ return zero for NaN 8966 ldmeqfd sp!, {r4, pc} 8967 8968 mov r0, r4 @ recover arg 8969 bl __aeabi_f2lz @ convert float to long 8970 ldmfd sp!, {r4, pc} 8971 8972 8973/* continuation for OP_DOUBLE_TO_LONG */ 8974/* 8975 * Convert the double in r0/r1 to a long in r0/r1. 8976 * 8977 * We have to clip values to long min/max per the specification. The 8978 * expected common case is a "reasonable" value that converts directly 8979 * to modest integer. The EABI convert function isn't doing this for us. 8980 */ 8981d2l_doconv: 8982 stmfd sp!, {r4, r5, lr} @ save regs 8983 mov r3, #0x43000000 @ maxlong, as a double (high word) 8984 add r3, #0x00e00000 @ 0x43e00000 8985 mov r2, #0 @ maxlong, as a double (low word) 8986 sub sp, sp, #4 @ align for EABI 8987 mov r4, r0 @ save a copy of r0 8988 mov r5, r1 @ and r1 8989 bl __aeabi_dcmpge @ is arg >= maxlong? 8990 cmp r0, #0 @ nonzero == yes 8991 mvnne r0, #0 @ return maxlong (7fffffffffffffff) 8992 mvnne r1, #0x80000000 8993 bne 1f 8994 8995 mov r0, r4 @ recover arg 8996 mov r1, r5 8997 mov r3, #0xc3000000 @ minlong, as a double (high word) 8998 add r3, #0x00e00000 @ 0xc3e00000 8999 mov r2, #0 @ minlong, as a double (low word) 9000 bl __aeabi_dcmple @ is arg <= minlong? 9001 cmp r0, #0 @ nonzero == yes 9002 movne r0, #0 @ return minlong (8000000000000000) 9003 movne r1, #0x80000000 9004 bne 1f 9005 9006 mov r0, r4 @ recover arg 9007 mov r1, r5 9008 mov r2, r4 @ compare against self 9009 mov r3, r5 9010 bl __aeabi_dcmpeq @ is arg == self? 9011 cmp r0, #0 @ zero == no 9012 moveq r1, #0 @ return zero for NaN 9013 beq 1f 9014 9015 mov r0, r4 @ recover arg 9016 mov r1, r5 9017 bl __aeabi_d2lz @ convert double to long 9018 90191: 9020 add sp, sp, #4 9021 ldmfd sp!, {r4, r5, pc} 9022 9023 9024/* continuation for OP_MUL_LONG */ 9025 9026.LOP_MUL_LONG_finish: 9027 GET_INST_OPCODE(ip) @ extract opcode from rINST 9028 stmia r0, {r9-r10} @ vAA/vAA+1<- r9/r10 9029 GOTO_OPCODE(ip) @ jump to next instruction 9030 9031 9032/* continuation for OP_SHL_LONG */ 9033 9034.LOP_SHL_LONG_finish: 9035 mov r0, r0, asl r2 @ r0<- r0 << r2 9036 GET_INST_OPCODE(ip) @ extract opcode from rINST 9037 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9038 GOTO_OPCODE(ip) @ jump to next instruction 9039 9040 9041/* continuation for OP_SHR_LONG */ 9042 9043.LOP_SHR_LONG_finish: 9044 mov r1, r1, asr r2 @ r1<- r1 >> r2 9045 GET_INST_OPCODE(ip) @ extract opcode from rINST 9046 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9047 GOTO_OPCODE(ip) @ jump to next instruction 9048 9049 9050/* continuation for OP_USHR_LONG */ 9051 9052.LOP_USHR_LONG_finish: 9053 mov r1, r1, lsr r2 @ r1<- r1 >>> r2 9054 GET_INST_OPCODE(ip) @ extract opcode from rINST 9055 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9056 GOTO_OPCODE(ip) @ jump to next instruction 9057 9058 9059/* continuation for OP_SHL_LONG_2ADDR */ 9060 9061.LOP_SHL_LONG_2ADDR_finish: 9062 GET_INST_OPCODE(ip) @ extract opcode from rINST 9063 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9064 GOTO_OPCODE(ip) @ jump to next instruction 9065 9066 9067/* continuation for OP_SHR_LONG_2ADDR */ 9068 9069.LOP_SHR_LONG_2ADDR_finish: 9070 GET_INST_OPCODE(ip) @ extract opcode from rINST 9071 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9072 GOTO_OPCODE(ip) @ jump to next instruction 9073 9074 9075/* continuation for OP_USHR_LONG_2ADDR */ 9076 9077.LOP_USHR_LONG_2ADDR_finish: 9078 GET_INST_OPCODE(ip) @ extract opcode from rINST 9079 stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 9080 GOTO_OPCODE(ip) @ jump to next instruction 9081 9082 9083/* continuation for OP_IGET_WIDE_VOLATILE */ 9084 9085 /* 9086 * Currently: 9087 * r0 holds resolved field 9088 * r9 holds object 9089 */ 9090.LOP_IGET_WIDE_VOLATILE_finish: 9091 cmp r9, #0 @ check object for null 9092 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9093 beq common_errNullObject @ object was null 9094 .if 1 9095 add r0, r9, r3 @ r0<- address of field 9096 bl android_quasiatomic_read_64 @ r0/r1<- contents of field 9097 .else 9098 ldrd r0, [r9, r3] @ r0/r1<- obj.field (64-bit align ok) 9099 .endif 9100 mov r2, rINST, lsr #8 @ r2<- A+ 9101 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9102 and r2, r2, #15 @ r2<- A 9103 add r3, rFP, r2, lsl #2 @ r3<- &fp[A] 9104 GET_INST_OPCODE(ip) @ extract opcode from rINST 9105 stmia r3, {r0-r1} @ fp[A]<- r0/r1 9106 GOTO_OPCODE(ip) @ jump to next instruction 9107 9108 9109/* continuation for OP_IPUT_WIDE_VOLATILE */ 9110 9111 /* 9112 * Currently: 9113 * r0 holds resolved field 9114 * r9 holds object 9115 */ 9116.LOP_IPUT_WIDE_VOLATILE_finish: 9117 mov r2, rINST, lsr #8 @ r2<- A+ 9118 cmp r9, #0 @ check object for null 9119 and r2, r2, #15 @ r2<- A 9120 ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field 9121 add r2, rFP, r2, lsl #2 @ r3<- &fp[A] 9122 beq common_errNullObject @ object was null 9123 FETCH_ADVANCE_INST(2) @ advance rPC, load rINST 9124 ldmia r2, {r0-r1} @ r0/r1<- fp[A] 9125 GET_INST_OPCODE(r10) @ extract opcode from rINST 9126 .if 1 9127 add r2, r9, r3 @ r2<- target address 9128 bl android_quasiatomic_swap_64 @ stores r0/r1 into addr r2 9129 .else 9130 strd r0, [r9, r3] @ obj.field (64 bits, aligned)<- r0/r1 9131 .endif 9132 GOTO_OPCODE(r10) @ jump to next instruction 9133 9134 9135/* continuation for OP_SGET_WIDE_VOLATILE */ 9136 9137 /* 9138 * Continuation if the field has not yet been resolved. 9139 * r1: BBBB field ref 9140 * 9141 * Returns StaticField pointer in r0. 9142 */ 9143.LOP_SGET_WIDE_VOLATILE_resolve: 9144 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9145 EXPORT_PC() @ resolve() could throw, so export now 9146 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9147 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9148 cmp r0, #0 @ success? 9149 bne .LOP_SGET_WIDE_VOLATILE_finish @ yes, finish 9150 b common_exceptionThrown @ no, handle exception 9151 9152 9153/* continuation for OP_SPUT_WIDE_VOLATILE */ 9154 9155 /* 9156 * Continuation if the field has not yet been resolved. 9157 * r1: BBBB field ref 9158 * r9: &fp[AA] 9159 * 9160 * Returns StaticField pointer in r2. 9161 */ 9162.LOP_SPUT_WIDE_VOLATILE_resolve: 9163 ldr r2, [rGLUE, #offGlue_method] @ r2<- current method 9164 EXPORT_PC() @ resolve() could throw, so export now 9165 ldr r0, [r2, #offMethod_clazz] @ r0<- method->clazz 9166 bl dvmResolveStaticField @ r0<- resolved StaticField ptr 9167 cmp r0, #0 @ success? 9168 mov r2, r0 @ copy to r2 9169 bne .LOP_SPUT_WIDE_VOLATILE_finish @ yes, finish 9170 b common_exceptionThrown @ no, handle exception 9171 9172 9173/* continuation for OP_EXECUTE_INLINE */ 9174 9175 /* 9176 * Extract args, call function. 9177 * r0 = #of args (0-4) 9178 * r10 = call index 9179 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9180 * 9181 * Other ideas: 9182 * - Use a jump table from the main piece to jump directly into the 9183 * AND/LDR pairs. Costs a data load, saves a branch. 9184 * - Have five separate pieces that do the loading, so we can work the 9185 * interleave a little better. Increases code size. 9186 */ 9187.LOP_EXECUTE_INLINE_continue: 9188 rsb r0, r0, #4 @ r0<- 4-r0 9189 FETCH(r9, 2) @ r9<- FEDC 9190 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9191 bl common_abort @ (skipped due to ARM prefetch) 91924: and ip, r9, #0xf000 @ isolate F 9193 ldr r3, [rFP, ip, lsr #10] @ r3<- vF (shift right 12, left 2) 91943: and ip, r9, #0x0f00 @ isolate E 9195 ldr r2, [rFP, ip, lsr #6] @ r2<- vE 91962: and ip, r9, #0x00f0 @ isolate D 9197 ldr r1, [rFP, ip, lsr #2] @ r1<- vD 91981: and ip, r9, #0x000f @ isolate C 9199 ldr r0, [rFP, ip, lsl #2] @ r0<- vC 92000: 9201 ldr r9, .LOP_EXECUTE_INLINE_table @ table of InlineOperation 9202 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9203 @ (not reached) 9204 9205.LOP_EXECUTE_INLINE_table: 9206 .word gDvmInlineOpsTable 9207 9208 9209/* continuation for OP_EXECUTE_INLINE_RANGE */ 9210 9211 /* 9212 * Extract args, call function. 9213 * r0 = #of args (0-4) 9214 * r10 = call index 9215 * lr = return addr, above [DO NOT bl out of here w/o preserving LR] 9216 */ 9217.LOP_EXECUTE_INLINE_RANGE_continue: 9218 rsb r0, r0, #4 @ r0<- 4-r0 9219 FETCH(r9, 2) @ r9<- CCCC 9220 add pc, pc, r0, lsl #3 @ computed goto, 2 instrs each 9221 bl common_abort @ (skipped due to ARM prefetch) 92224: add ip, r9, #3 @ base+3 9223 GET_VREG(r3, ip) @ r3<- vBase[3] 92243: add ip, r9, #2 @ base+2 9225 GET_VREG(r2, ip) @ r2<- vBase[2] 92262: add ip, r9, #1 @ base+1 9227 GET_VREG(r1, ip) @ r1<- vBase[1] 92281: add ip, r9, #0 @ (nop) 9229 GET_VREG(r0, ip) @ r0<- vBase[0] 92300: 9231 ldr r9, .LOP_EXECUTE_INLINE_RANGE_table @ table of InlineOperation 9232 LDR_PC "[r9, r10, lsl #4]" @ sizeof=16, "func" is first entry 9233 @ (not reached) 9234 9235.LOP_EXECUTE_INLINE_RANGE_table: 9236 .word gDvmInlineOpsTable 9237 9238 9239 .size dvmAsmSisterStart, .-dvmAsmSisterStart 9240 .global dvmAsmSisterEnd 9241dvmAsmSisterEnd: 9242 9243/* File: armv5te/footer.S */ 9244 9245/* 9246 * =========================================================================== 9247 * Common subroutines and data 9248 * =========================================================================== 9249 */ 9250 9251 9252 9253 .text 9254 .align 2 9255 9256#if defined(WITH_JIT) 9257#if defined(WITH_SELF_VERIFICATION) 9258 .global dvmJitToInterpPunt 9259dvmJitToInterpPunt: 9260 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9261 mov r2,#kSVSPunt @ r2<- interpreter entry point 9262 mov r3, #0 9263 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9264 b jitSVShadowRunEnd @ doesn't return 9265 9266 .global dvmJitToInterpSingleStep 9267dvmJitToInterpSingleStep: 9268 str lr,[rGLUE,#offGlue_jitResumeNPC] 9269 str r1,[rGLUE,#offGlue_jitResumeDPC] 9270 mov r2,#kSVSSingleStep @ r2<- interpreter entry point 9271 b jitSVShadowRunEnd @ doesn't return 9272 9273 .global dvmJitToInterpTraceSelectNoChain 9274dvmJitToInterpTraceSelectNoChain: 9275 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9276 mov r0,rPC @ pass our target PC 9277 mov r2,#kSVSTraceSelectNoChain @ r2<- interpreter entry point 9278 mov r3, #0 9279 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9280 b jitSVShadowRunEnd @ doesn't return 9281 9282 .global dvmJitToInterpTraceSelect 9283dvmJitToInterpTraceSelect: 9284 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9285 ldr r0,[lr, #-1] @ pass our target PC 9286 mov r2,#kSVSTraceSelect @ r2<- interpreter entry point 9287 mov r3, #0 9288 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9289 b jitSVShadowRunEnd @ doesn't return 9290 9291 .global dvmJitToInterpBackwardBranch 9292dvmJitToInterpBackwardBranch: 9293 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9294 ldr r0,[lr, #-1] @ pass our target PC 9295 mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point 9296 mov r3, #0 9297 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9298 b jitSVShadowRunEnd @ doesn't return 9299 9300 .global dvmJitToInterpNormal 9301dvmJitToInterpNormal: 9302 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9303 ldr r0,[lr, #-1] @ pass our target PC 9304 mov r2,#kSVSNormal @ r2<- interpreter entry point 9305 mov r3, #0 9306 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9307 b jitSVShadowRunEnd @ doesn't return 9308 9309 .global dvmJitToInterpNoChain 9310dvmJitToInterpNoChain: 9311 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9312 mov r0,rPC @ pass our target PC 9313 mov r2,#kSVSNoChain @ r2<- interpreter entry point 9314 mov r3, #0 9315 str r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9316 b jitSVShadowRunEnd @ doesn't return 9317#else 9318/* 9319 * Return from the translation cache to the interpreter when the compiler is 9320 * having issues translating/executing a Dalvik instruction. We have to skip 9321 * the code cache lookup otherwise it is possible to indefinitely bouce 9322 * between the interpreter and the code cache if the instruction that fails 9323 * to be compiled happens to be at a trace start. 9324 */ 9325 .global dvmJitToInterpPunt 9326dvmJitToInterpPunt: 9327 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9328 mov rPC, r0 9329#if defined(WITH_JIT_TUNING) 9330 mov r0,lr 9331 bl dvmBumpPunt; 9332#endif 9333 EXPORT_PC() 9334 mov r0, #0 9335 str r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land 9336 adrl rIBASE, dvmAsmInstructionStart 9337 FETCH_INST() 9338 GET_INST_OPCODE(ip) 9339 GOTO_OPCODE(ip) 9340 9341/* 9342 * Return to the interpreter to handle a single instruction. 9343 * On entry: 9344 * r0 <= PC 9345 * r1 <= PC of resume instruction 9346 * lr <= resume point in translation 9347 */ 9348 .global dvmJitToInterpSingleStep 9349dvmJitToInterpSingleStep: 9350 str lr,[rGLUE,#offGlue_jitResumeNPC] 9351 str r1,[rGLUE,#offGlue_jitResumeDPC] 9352 mov r1,#kInterpEntryInstr 9353 @ enum is 4 byte in aapcs-EABI 9354 str r1, [rGLUE, #offGlue_entryPoint] 9355 mov rPC,r0 9356 EXPORT_PC() 9357 9358 adrl rIBASE, dvmAsmInstructionStart 9359 mov r2,#kJitSingleStep @ Ask for single step and then revert 9360 str r2,[rGLUE,#offGlue_jitState] 9361 mov r1,#1 @ set changeInterp to bail to debug interp 9362 b common_gotoBail 9363 9364/* 9365 * Return from the translation cache and immediately request 9366 * a translation for the exit target. Commonly used for callees. 9367 */ 9368 .global dvmJitToInterpTraceSelectNoChain 9369dvmJitToInterpTraceSelectNoChain: 9370#if defined(WITH_JIT_TUNING) 9371 bl dvmBumpNoChain 9372#endif 9373 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9374 mov r0,rPC 9375 bl dvmJitGetCodeAddr @ Is there a translation? 9376 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9377 mov r1, rPC @ arg1 of translation may need this 9378 mov lr, #0 @ in case target is HANDLER_INTERPRET 9379 cmp r0,#0 9380 bxne r0 @ continue native execution if so 9381 b 2f 9382 9383/* 9384 * Return from the translation cache and immediately request 9385 * a translation for the exit target. Commonly used following 9386 * invokes. 9387 */ 9388 .global dvmJitToInterpTraceSelect 9389dvmJitToInterpTraceSelect: 9390 ldr rPC,[lr, #-1] @ get our target PC 9391 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9392 add rINST,lr,#-5 @ save start of chain branch 9393 add rINST, #-4 @ .. which is 9 bytes back 9394 mov r0,rPC 9395 bl dvmJitGetCodeAddr @ Is there a translation? 9396 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9397 cmp r0,#0 9398 beq 2f 9399 mov r1,rINST 9400 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9401 mov r1, rPC @ arg1 of translation may need this 9402 mov lr, #0 @ in case target is HANDLER_INTERPRET 9403 cmp r0,#0 @ successful chain? 9404 bxne r0 @ continue native execution 9405 b toInterpreter @ didn't chain - resume with interpreter 9406 9407/* No translation, so request one if profiling isn't disabled*/ 94082: 9409 adrl rIBASE, dvmAsmInstructionStart 9410 GET_JIT_PROF_TABLE(r0) 9411 FETCH_INST() 9412 cmp r0, #0 9413 movne r2,#kJitTSelectRequestHot @ ask for trace selection 9414 bne common_selectTrace 9415 GET_INST_OPCODE(ip) 9416 GOTO_OPCODE(ip) 9417 9418/* 9419 * Return from the translation cache to the interpreter. 9420 * The return was done with a BLX from thumb mode, and 9421 * the following 32-bit word contains the target rPC value. 9422 * Note that lr (r14) will have its low-order bit set to denote 9423 * its thumb-mode origin. 9424 * 9425 * We'll need to stash our lr origin away, recover the new 9426 * target and then check to see if there is a translation available 9427 * for our new target. If so, we do a translation chain and 9428 * go back to native execution. Otherwise, it's back to the 9429 * interpreter (after treating this entry as a potential 9430 * trace start). 9431 */ 9432 .global dvmJitToInterpNormal 9433dvmJitToInterpNormal: 9434 ldr rPC,[lr, #-1] @ get our target PC 9435 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9436 add rINST,lr,#-5 @ save start of chain branch 9437 add rINST,#-4 @ .. which is 9 bytes back 9438#if defined(WITH_JIT_TUNING) 9439 bl dvmBumpNormal 9440#endif 9441 mov r0,rPC 9442 bl dvmJitGetCodeAddr @ Is there a translation? 9443 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9444 cmp r0,#0 9445 beq toInterpreter @ go if not, otherwise do chain 9446 mov r1,rINST 9447 bl dvmJitChain @ r0<- dvmJitChain(codeAddr,chainAddr) 9448 mov r1, rPC @ arg1 of translation may need this 9449 mov lr, #0 @ in case target is HANDLER_INTERPRET 9450 cmp r0,#0 @ successful chain? 9451 bxne r0 @ continue native execution 9452 b toInterpreter @ didn't chain - resume with interpreter 9453 9454/* 9455 * Return from the translation cache to the interpreter to do method invocation. 9456 * Check if translation exists for the callee, but don't chain to it. 9457 */ 9458 .global dvmJitToInterpNoChain 9459dvmJitToInterpNoChain: 9460#if defined(WITH_JIT_TUNING) 9461 bl dvmBumpNoChain 9462#endif 9463 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9464 mov r0,rPC 9465 bl dvmJitGetCodeAddr @ Is there a translation? 9466 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9467 mov r1, rPC @ arg1 of translation may need this 9468 mov lr, #0 @ in case target is HANDLER_INTERPRET 9469 cmp r0,#0 9470 bxne r0 @ continue native execution if so 9471#endif 9472 9473/* 9474 * No translation, restore interpreter regs and start interpreting. 9475 * rGLUE & rFP were preserved in the translated code, and rPC has 9476 * already been restored by the time we get here. We'll need to set 9477 * up rIBASE & rINST, and load the address of the JitTable into r0. 9478 */ 9479toInterpreter: 9480 EXPORT_PC() 9481 adrl rIBASE, dvmAsmInstructionStart 9482 FETCH_INST() 9483 GET_JIT_PROF_TABLE(r0) 9484 @ NOTE: intended fallthrough 9485/* 9486 * Common code to update potential trace start counter, and initiate 9487 * a trace-build if appropriate. On entry, rPC should point to the 9488 * next instruction to execute, and rINST should be already loaded with 9489 * the next opcode word, and r0 holds a pointer to the jit profile 9490 * table (pJitProfTable). 9491 */ 9492common_testUpdateProfile: 9493 cmp r0,#0 9494 GET_INST_OPCODE(ip) 9495 GOTO_OPCODE_IFEQ(ip) @ if not profiling, fallthrough otherwise */ 9496 9497common_updateProfile: 9498 eor r3,rPC,rPC,lsr #12 @ cheap, but fast hash function 9499 lsl r3,r3,#(32 - JIT_PROF_SIZE_LOG_2) @ shift out excess bits 9500 ldrb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter 9501 GET_INST_OPCODE(ip) 9502 subs r1,r1,#1 @ decrement counter 9503 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it 9504 GOTO_OPCODE_IFNE(ip) @ if not threshold, fallthrough otherwise */ 9505 9506/* 9507 * Here, we switch to the debug interpreter to request 9508 * trace selection. First, though, check to see if there 9509 * is already a native translation in place (and, if so, 9510 * jump to it now). 9511 */ 9512 GET_JIT_THRESHOLD(r1) 9513 ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self 9514 strb r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter 9515 EXPORT_PC() 9516 mov r0,rPC 9517 bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC) 9518 str r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag 9519 mov r1, rPC @ arg1 of translation may need this 9520 mov lr, #0 @ in case target is HANDLER_INTERPRET 9521 cmp r0,#0 9522#if !defined(WITH_SELF_VERIFICATION) 9523 bxne r0 @ jump to the translation 9524 mov r2,#kJitTSelectRequest @ ask for trace selection 9525 @ fall-through to common_selectTrace 9526#else 9527 moveq r2,#kJitTSelectRequest @ ask for trace selection 9528 beq common_selectTrace 9529 /* 9530 * At this point, we have a target translation. However, if 9531 * that translation is actually the interpret-only pseudo-translation 9532 * we want to treat it the same as no translation. 9533 */ 9534 mov r10, r0 @ save target 9535 bl dvmCompilerGetInterpretTemplate 9536 cmp r0, r10 @ special case? 9537 bne jitSVShadowRunStart @ set up self verification shadow space 9538 GET_INST_OPCODE(ip) 9539 GOTO_OPCODE(ip) 9540 /* no return */ 9541#endif 9542 9543/* 9544 * On entry: 9545 * r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot 9546 */ 9547common_selectTrace: 9548 str r2,[rGLUE,#offGlue_jitState] 9549 mov r2,#kInterpEntryInstr @ normal entry reason 9550 str r2,[rGLUE,#offGlue_entryPoint] 9551 mov r1,#1 @ set changeInterp 9552 b common_gotoBail 9553 9554#if defined(WITH_SELF_VERIFICATION) 9555/* 9556 * Save PC and registers to shadow memory for self verification mode 9557 * before jumping to native translation. 9558 * On entry: 9559 * rPC, rFP, rGLUE: the values that they should contain 9560 * r10: the address of the target translation. 9561 */ 9562jitSVShadowRunStart: 9563 mov r0,rPC @ r0<- program counter 9564 mov r1,rFP @ r1<- frame pointer 9565 mov r2,rGLUE @ r2<- InterpState pointer 9566 mov r3,r10 @ r3<- target translation 9567 bl dvmSelfVerificationSaveState @ save registers to shadow space 9568 ldr rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space 9569 add rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space 9570 bx r10 @ jump to the translation 9571 9572/* 9573 * Restore PC, registers, and interpState to original values 9574 * before jumping back to the interpreter. 9575 */ 9576jitSVShadowRunEnd: 9577 mov r1,rFP @ pass ending fp 9578 bl dvmSelfVerificationRestoreState @ restore pc and fp values 9579 ldr rPC,[r0,#offShadowSpace_startPC] @ restore PC 9580 ldr rFP,[r0,#offShadowSpace_fp] @ restore FP 9581 ldr rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState 9582 ldr r1,[r0,#offShadowSpace_svState] @ get self verification state 9583 cmp r1,#0 @ check for punt condition 9584 beq 1f 9585 mov r2,#kJitSelfVerification @ ask for self verification 9586 str r2,[rGLUE,#offGlue_jitState] 9587 mov r2,#kInterpEntryInstr @ normal entry reason 9588 str r2,[rGLUE,#offGlue_entryPoint] 9589 mov r1,#1 @ set changeInterp 9590 b common_gotoBail 9591 95921: @ exit to interpreter without check 9593 EXPORT_PC() 9594 adrl rIBASE, dvmAsmInstructionStart 9595 FETCH_INST() 9596 GET_INST_OPCODE(ip) 9597 GOTO_OPCODE(ip) 9598#endif 9599 9600#endif 9601 9602/* 9603 * Common code when a backward branch is taken. 9604 * 9605 * TODO: we could avoid a branch by just setting r0 and falling through 9606 * into the common_periodicChecks code, and having a test on r0 at the 9607 * end determine if we should return to the caller or update & branch to 9608 * the next instr. 9609 * 9610 * On entry: 9611 * r9 is PC adjustment *in bytes* 9612 */ 9613common_backwardBranch: 9614 mov r0, #kInterpEntryInstr 9615 bl common_periodicChecks 9616#if defined(WITH_JIT) 9617 GET_JIT_PROF_TABLE(r0) 9618 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9619 cmp r0,#0 9620 bne common_updateProfile 9621 GET_INST_OPCODE(ip) 9622 GOTO_OPCODE(ip) 9623#else 9624 FETCH_ADVANCE_INST_RB(r9) @ update rPC, load rINST 9625 GET_INST_OPCODE(ip) @ extract opcode from rINST 9626 GOTO_OPCODE(ip) @ jump to next instruction 9627#endif 9628 9629 9630/* 9631 * Need to see if the thread needs to be suspended or debugger/profiler 9632 * activity has begun. If so, we suspend the thread or side-exit to 9633 * the debug interpreter as appropriate. 9634 * 9635 * The common case is no activity on any of these, so we want to figure 9636 * that out quickly. If something is up, we can then sort out what. 9637 * 9638 * We want to be fast if the VM was built without debugger or profiler 9639 * support, but we also need to recognize that the system is usually 9640 * shipped with both of these enabled. 9641 * 9642 * TODO: reduce this so we're just checking a single location. 9643 * 9644 * On entry: 9645 * r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling) 9646 * r9 is trampoline PC adjustment *in bytes* 9647 */ 9648common_periodicChecks: 9649 ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount 9650 9651#if defined(WITH_DEBUGGER) 9652 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9653#endif 9654#if defined(WITH_PROFILER) 9655 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9656#endif 9657 9658 ldr ip, [r3] @ ip<- suspendCount (int) 9659 9660#if defined(WITH_DEBUGGER) && defined(WITH_PROFILER) 9661 cmp r1, #0 @ debugger enabled? 9662 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9663 ldr r2, [r2] @ r2<- activeProfilers (int) 9664 orrne ip, ip, r1 @ ip<- suspendCount | debuggerActive 9665 orrs ip, ip, r2 @ ip<- suspend|debugger|profiler; set Z 9666#elif defined(WITH_DEBUGGER) 9667 cmp r1, #0 @ debugger enabled? 9668 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9669 orrsne ip, ip, r1 @ yes, ip<- suspend | debugger; set Z 9670 @ (if not enabled, Z was set by test for r1==0, which is what we want) 9671#elif defined (WITH_PROFILER) 9672 ldr r2, [r2] @ r2<- activeProfilers (int) 9673 orrs ip, ip, r2 @ ip<- suspendCount | activeProfilers 9674#else 9675 cmp ip, #0 @ not ORing anything in; set Z 9676#endif 9677 9678 bxeq lr @ all zero, return 9679 9680 /* 9681 * One or more interesting events have happened. Figure out what. 9682 * 9683 * If debugging or profiling are compiled in, we need to disambiguate. 9684 * 9685 * r0 still holds the reentry type. 9686 */ 9687#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 9688 ldr ip, [r3] @ ip<- suspendCount (int) 9689 cmp ip, #0 @ want suspend? 9690 beq 1f @ no, must be debugger/profiler 9691#endif 9692 9693 stmfd sp!, {r0, lr} @ preserve r0 and lr 9694#if defined(WITH_JIT) 9695 /* 9696 * Refresh the Jit's cached copy of profile table pointer. This pointer 9697 * doubles as the Jit's on/off switch. 9698 */ 9699 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable 9700 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9701 ldr r3, [r3] @ r3 <- pJitProfTable 9702 EXPORT_PC() @ need for precise GC 9703 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch 9704#else 9705 ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self 9706 EXPORT_PC() @ need for precise GC 9707#endif 9708 bl dvmCheckSuspendPending @ do full check, suspend if necessary 9709 ldmfd sp!, {r0, lr} @ restore r0 and lr 9710 9711#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 9712 9713 /* 9714 * Reload the debugger/profiler enable flags. We're checking to see 9715 * if either of these got set while we were suspended. 9716 * 9717 * We can't really avoid the #ifdefs here, because the fields don't 9718 * exist when the feature is disabled. 9719 */ 9720#if defined(WITH_DEBUGGER) 9721 ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive 9722 cmp r1, #0 @ debugger enabled? 9723 ldrneb r1, [r1] @ yes, r1<- debuggerActive (boolean) 9724#else 9725 mov r1, #0 9726#endif 9727#if defined(WITH_PROFILER) 9728 ldr r2, [rGLUE, #offGlue_pActiveProfilers] @ r2<- &activeProfilers 9729 ldr r2, [r2] @ r2<- activeProfilers (int) 9730#else 9731 mov r2, #0 9732#endif 9733 9734 orrs r1, r1, r2 9735 beq 2f 9736 97371: @ debugger/profiler enabled, bail out; glue->entryPoint was set above 9738 str r0, [rGLUE, #offGlue_entryPoint] @ store r0, need for debug/prof 9739 add rPC, rPC, r9 @ update rPC 9740 mov r1, #1 @ "want switch" = true 9741 b common_gotoBail @ side exit 9742 9743#endif /*WITH_DEBUGGER || WITH_PROFILER*/ 9744 97452: 9746 bx lr @ nothing to do, return 9747 9748 9749/* 9750 * The equivalent of "goto bail", this calls through the "bail handler". 9751 * 9752 * State registers will be saved to the "glue" area before bailing. 9753 * 9754 * On entry: 9755 * r1 is "bool changeInterp", indicating if we want to switch to the 9756 * other interpreter or just bail all the way out 9757 */ 9758common_gotoBail: 9759 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9760 mov r0, rGLUE @ r0<- glue ptr 9761 b dvmMterpStdBail @ call(glue, changeInterp) 9762 9763 @add r1, r1, #1 @ using (boolean+1) 9764 @add r0, rGLUE, #offGlue_jmpBuf @ r0<- &glue->jmpBuf 9765 @bl _longjmp @ does not return 9766 @bl common_abort 9767 9768 9769/* 9770 * Common code for method invocation with range. 9771 * 9772 * On entry: 9773 * r0 is "Method* methodToCall", the method we're trying to call 9774 */ 9775common_invokeMethodRange: 9776.LinvokeNewRange: 9777 @ prepare to copy args to "outs" area of current frame 9778 movs r2, rINST, lsr #8 @ r2<- AA (arg count) -- test for zero 9779 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9780 beq .LinvokeArgsDone @ if no args, skip the rest 9781 FETCH(r1, 2) @ r1<- CCCC 9782 9783 @ r0=methodToCall, r1=CCCC, r2=count, r10=outs 9784 @ (very few methods have > 10 args; could unroll for common cases) 9785 add r3, rFP, r1, lsl #2 @ r3<- &fp[CCCC] 9786 sub r10, r10, r2, lsl #2 @ r10<- "outs" area, for call args 9787 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 97881: ldr r1, [r3], #4 @ val = *fp++ 9789 subs r2, r2, #1 @ count-- 9790 str r1, [r10], #4 @ *outs++ = val 9791 bne 1b @ ...while count != 0 9792 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9793 b .LinvokeArgsDone 9794 9795/* 9796 * Common code for method invocation without range. 9797 * 9798 * On entry: 9799 * r0 is "Method* methodToCall", the method we're trying to call 9800 */ 9801common_invokeMethodNoRange: 9802.LinvokeNewNoRange: 9803 @ prepare to copy args to "outs" area of current frame 9804 movs r2, rINST, lsr #12 @ r2<- B (arg count) -- test for zero 9805 SAVEAREA_FROM_FP(r10, rFP) @ r10<- stack save area 9806 FETCH(r1, 2) @ r1<- GFED (load here to hide latency) 9807 ldrh r9, [r0, #offMethod_registersSize] @ r9<- methodToCall->regsSize 9808 ldrh r3, [r0, #offMethod_outsSize] @ r3<- methodToCall->outsSize 9809 beq .LinvokeArgsDone 9810 9811 @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs 9812.LinvokeNonRange: 9813 rsb r2, r2, #5 @ r2<- 5-r2 9814 add pc, pc, r2, lsl #4 @ computed goto, 4 instrs each 9815 bl common_abort @ (skipped due to ARM prefetch) 98165: and ip, rINST, #0x0f00 @ isolate A 9817 ldr r2, [rFP, ip, lsr #6] @ r2<- vA (shift right 8, left 2) 9818 mov r0, r0 @ nop 9819 str r2, [r10, #-4]! @ *--outs = vA 98204: and ip, r1, #0xf000 @ isolate G 9821 ldr r2, [rFP, ip, lsr #10] @ r2<- vG (shift right 12, left 2) 9822 mov r0, r0 @ nop 9823 str r2, [r10, #-4]! @ *--outs = vG 98243: and ip, r1, #0x0f00 @ isolate F 9825 ldr r2, [rFP, ip, lsr #6] @ r2<- vF 9826 mov r0, r0 @ nop 9827 str r2, [r10, #-4]! @ *--outs = vF 98282: and ip, r1, #0x00f0 @ isolate E 9829 ldr r2, [rFP, ip, lsr #2] @ r2<- vE 9830 mov r0, r0 @ nop 9831 str r2, [r10, #-4]! @ *--outs = vE 98321: and ip, r1, #0x000f @ isolate D 9833 ldr r2, [rFP, ip, lsl #2] @ r2<- vD 9834 mov r0, r0 @ nop 9835 str r2, [r10, #-4]! @ *--outs = vD 98360: @ fall through to .LinvokeArgsDone 9837 9838.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize 9839 ldr r2, [r0, #offMethod_insns] @ r2<- method->insns 9840 ldr rINST, [r0, #offMethod_clazz] @ rINST<- method->clazz 9841 @ find space for the new stack frame, check for overflow 9842 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area 9843 sub r1, r1, r9, lsl #2 @ r1<- newFp (old savearea - regsSize) 9844 SAVEAREA_FROM_FP(r10, r1) @ r10<- newSaveArea 9845@ bl common_dumpRegs 9846 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd 9847 sub r3, r10, r3, lsl #2 @ r3<- bottom (newsave - outsSize) 9848 cmp r3, r9 @ bottom < interpStackEnd? 9849 ldr r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags 9850 blo .LstackOverflow @ yes, this frame will overflow stack 9851 9852 @ set up newSaveArea 9853#ifdef EASY_GDB 9854 SAVEAREA_FROM_FP(ip, rFP) @ ip<- stack save area 9855 str ip, [r10, #offStackSaveArea_prevSave] 9856#endif 9857 str rFP, [r10, #offStackSaveArea_prevFrame] 9858 str rPC, [r10, #offStackSaveArea_savedPc] 9859#if defined(WITH_JIT) 9860 mov r9, #0 9861 str r9, [r10, #offStackSaveArea_returnAddr] 9862#endif 9863 str r0, [r10, #offStackSaveArea_method] 9864 tst r3, #ACC_NATIVE 9865 bne .LinvokeNative 9866 9867 /* 9868 stmfd sp!, {r0-r3} 9869 bl common_printNewline 9870 mov r0, rFP 9871 mov r1, #0 9872 bl dvmDumpFp 9873 ldmfd sp!, {r0-r3} 9874 stmfd sp!, {r0-r3} 9875 mov r0, r1 9876 mov r1, r10 9877 bl dvmDumpFp 9878 bl common_printNewline 9879 ldmfd sp!, {r0-r3} 9880 */ 9881 9882 ldrh r9, [r2] @ r9 <- load INST from new PC 9883 ldr r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex 9884 mov rPC, r2 @ publish new rPC 9885 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self 9886 9887 @ Update "glue" values for the new method 9888 @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST 9889 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall 9890 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ... 9891#if defined(WITH_JIT) 9892 GET_JIT_PROF_TABLE(r0) 9893 mov rFP, r1 @ fp = newFp 9894 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9895 mov rINST, r9 @ publish new rINST 9896 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9897 cmp r0,#0 9898 bne common_updateProfile 9899 GOTO_OPCODE(ip) @ jump to next instruction 9900#else 9901 mov rFP, r1 @ fp = newFp 9902 GET_PREFETCHED_OPCODE(ip, r9) @ extract prefetched opcode from r9 9903 mov rINST, r9 @ publish new rINST 9904 str r1, [r2, #offThread_curFrame] @ self->curFrame = newFp 9905 GOTO_OPCODE(ip) @ jump to next instruction 9906#endif 9907 9908.LinvokeNative: 9909 @ Prep for the native call 9910 @ r0=methodToCall, r1=newFp, r10=newSaveArea 9911 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 9912 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->... 9913 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp 9914 str r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top 9915 mov r9, r3 @ r9<- glue->self (preserve) 9916 9917 mov r2, r0 @ r2<- methodToCall 9918 mov r0, r1 @ r0<- newFp (points to args) 9919 add r1, rGLUE, #offGlue_retval @ r1<- &retval 9920 9921#ifdef ASSIST_DEBUGGER 9922 /* insert fake function header to help gdb find the stack frame */ 9923 b .Lskip 9924 .type dalvik_mterp, %function 9925dalvik_mterp: 9926 .fnstart 9927 MTERP_ENTRY1 9928 MTERP_ENTRY2 9929.Lskip: 9930#endif 9931 9932 @mov lr, pc @ set return addr 9933 @ldr pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc 9934 LDR_PC_LR "[r2, #offMethod_nativeFunc]" 9935 9936#if defined(WITH_JIT) 9937 ldr r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status 9938#endif 9939 9940 @ native return; r9=self, r10=newSaveArea 9941 @ equivalent to dvmPopJniLocals 9942 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top 9943 ldr r1, [r9, #offThread_exception] @ check for exception 9944#if defined(WITH_JIT) 9945 ldr r3, [r3] @ r3 <- gDvmJit.pProfTable 9946#endif 9947 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp 9948 cmp r1, #0 @ null? 9949 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top 9950#if defined(WITH_JIT) 9951 str r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch 9952#endif 9953 bne common_exceptionThrown @ no, handle exception 9954 9955 FETCH_ADVANCE_INST(3) @ advance rPC, load rINST 9956 GET_INST_OPCODE(ip) @ extract opcode from rINST 9957 GOTO_OPCODE(ip) @ jump to next instruction 9958 9959.LstackOverflow: @ r0=methodToCall 9960 mov r1, r0 @ r1<- methodToCall 9961 ldr r0, [rGLUE, #offGlue_self] @ r0<- self 9962 bl dvmHandleStackOverflow 9963 b common_exceptionThrown 9964#ifdef ASSIST_DEBUGGER 9965 .fnend 9966#endif 9967 9968 9969 /* 9970 * Common code for method invocation, calling through "glue code". 9971 * 9972 * TODO: now that we have range and non-range invoke handlers, this 9973 * needs to be split into two. Maybe just create entry points 9974 * that set r9 and jump here? 9975 * 9976 * On entry: 9977 * r0 is "Method* methodToCall", the method we're trying to call 9978 * r9 is "bool methodCallRange", indicating if this is a /range variant 9979 */ 9980 .if 0 9981.LinvokeOld: 9982 sub sp, sp, #8 @ space for args + pad 9983 FETCH(ip, 2) @ ip<- FEDC or CCCC 9984 mov r2, r0 @ A2<- methodToCall 9985 mov r0, rGLUE @ A0<- glue 9986 SAVE_PC_FP_TO_GLUE() @ export state to "glue" 9987 mov r1, r9 @ A1<- methodCallRange 9988 mov r3, rINST, lsr #8 @ A3<- AA 9989 str ip, [sp, #0] @ A4<- ip 9990 bl dvmMterp_invokeMethod @ call the C invokeMethod 9991 add sp, sp, #8 @ remove arg area 9992 b common_resumeAfterGlueCall @ continue to next instruction 9993 .endif 9994 9995 9996 9997/* 9998 * Common code for handling a return instruction. 9999 * 10000 * This does not return. 10001 */ 10002common_returnFromMethod: 10003.LreturnNew: 10004 mov r0, #kInterpEntryReturn 10005 mov r9, #0 10006 bl common_periodicChecks 10007 10008 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old) 10009 ldr rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame 10010 ldr r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc 10011 ldr r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)] 10012 @ r2<- method we're returning to 10013 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self 10014 cmp r2, #0 @ is this a break frame? 10015 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz 10016 mov r1, #0 @ "want switch" = false 10017 beq common_gotoBail @ break frame, bail out completely 10018 10019 PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST 10020 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method 10021 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex 10022 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp 10023#if defined(WITH_JIT) 10024 ldr r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr 10025 GET_JIT_PROF_TABLE(r0) 10026 mov rPC, r9 @ publish new rPC 10027 str r1, [rGLUE, #offGlue_methodClassDex] 10028 str r10, [r3, #offThread_inJitCodeCache] @ may return to JIT'ed land 10029 cmp r10, #0 @ caller is compiled code 10030 blxne r10 10031 GET_INST_OPCODE(ip) @ extract opcode from rINST 10032 cmp r0,#0 10033 bne common_updateProfile 10034 GOTO_OPCODE(ip) @ jump to next instruction 10035#else 10036 GET_INST_OPCODE(ip) @ extract opcode from rINST 10037 mov rPC, r9 @ publish new rPC 10038 str r1, [rGLUE, #offGlue_methodClassDex] 10039 GOTO_OPCODE(ip) @ jump to next instruction 10040#endif 10041 10042 /* 10043 * Return handling, calls through "glue code". 10044 */ 10045 .if 0 10046.LreturnOld: 10047 SAVE_PC_FP_TO_GLUE() @ export state 10048 mov r0, rGLUE @ arg to function 10049 bl dvmMterp_returnFromMethod 10050 b common_resumeAfterGlueCall 10051 .endif 10052 10053 10054/* 10055 * Somebody has thrown an exception. Handle it. 10056 * 10057 * If the exception processing code returns to us (instead of falling 10058 * out of the interpreter), continue with whatever the next instruction 10059 * now happens to be. 10060 * 10061 * This does not return. 10062 */ 10063 .global dvmMterpCommonExceptionThrown 10064dvmMterpCommonExceptionThrown: 10065common_exceptionThrown: 10066.LexceptionNew: 10067 mov r0, #kInterpEntryThrow 10068 mov r9, #0 10069 bl common_periodicChecks 10070 10071 ldr r10, [rGLUE, #offGlue_self] @ r10<- glue->self 10072 ldr r9, [r10, #offThread_exception] @ r9<- self->exception 10073 mov r1, r10 @ r1<- self 10074 mov r0, r9 @ r0<- exception 10075 bl dvmAddTrackedAlloc @ don't let the exception be GCed 10076 mov r3, #0 @ r3<- NULL 10077 str r3, [r10, #offThread_exception] @ self->exception = NULL 10078 10079 /* set up args and a local for "&fp" */ 10080 /* (str sp, [sp, #-4]! would be perfect here, but is discouraged) */ 10081 str rFP, [sp, #-4]! @ *--sp = fp 10082 mov ip, sp @ ip<- &fp 10083 mov r3, #0 @ r3<- false 10084 str ip, [sp, #-4]! @ *--sp = &fp 10085 ldr r1, [rGLUE, #offGlue_method] @ r1<- glue->method 10086 mov r0, r10 @ r0<- self 10087 ldr r1, [r1, #offMethod_insns] @ r1<- method->insns 10088 mov r2, r9 @ r2<- exception 10089 sub r1, rPC, r1 @ r1<- pc - method->insns 10090 mov r1, r1, asr #1 @ r1<- offset in code units 10091 10092 /* call, r0 gets catchRelPc (a code-unit offset) */ 10093 bl dvmFindCatchBlock @ call(self, relPc, exc, scan?, &fp) 10094 10095 /* fix earlier stack overflow if necessary; may trash rFP */ 10096 ldrb r1, [r10, #offThread_stackOverflowed] 10097 cmp r1, #0 @ did we overflow earlier? 10098 beq 1f @ no, skip ahead 10099 mov rFP, r0 @ save relPc result in rFP 10100 mov r0, r10 @ r0<- self 10101 mov r1, r9 @ r1<- exception 10102 bl dvmCleanupStackOverflow @ call(self) 10103 mov r0, rFP @ restore result 101041: 10105 10106 /* update frame pointer and check result from dvmFindCatchBlock */ 10107 ldr rFP, [sp, #4] @ retrieve the updated rFP 10108 cmp r0, #0 @ is catchRelPc < 0? 10109 add sp, sp, #8 @ restore stack 10110 bmi .LnotCaughtLocally 10111 10112 /* adjust locals to match self->curFrame and updated PC */ 10113 SAVEAREA_FROM_FP(r1, rFP) @ r1<- new save area 10114 ldr r1, [r1, #offStackSaveArea_method] @ r1<- new method 10115 str r1, [rGLUE, #offGlue_method] @ glue->method = new method 10116 ldr r2, [r1, #offMethod_clazz] @ r2<- method->clazz 10117 ldr r3, [r1, #offMethod_insns] @ r3<- method->insns 10118 ldr r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex 10119 add rPC, r3, r0, asl #1 @ rPC<- method->insns + catchRelPc 10120 str r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth... 10121 10122 /* release the tracked alloc on the exception */ 10123 mov r0, r9 @ r0<- exception 10124 mov r1, r10 @ r1<- self 10125 bl dvmReleaseTrackedAlloc @ release the exception 10126 10127 /* restore the exception if the handler wants it */ 10128 FETCH_INST() @ load rINST from rPC 10129 GET_INST_OPCODE(ip) @ extract opcode from rINST 10130 cmp ip, #OP_MOVE_EXCEPTION @ is it "move-exception"? 10131 streq r9, [r10, #offThread_exception] @ yes, restore the exception 10132 GOTO_OPCODE(ip) @ jump to next instruction 10133 10134.LnotCaughtLocally: @ r9=exception, r10=self 10135 /* fix stack overflow if necessary */ 10136 ldrb r1, [r10, #offThread_stackOverflowed] 10137 cmp r1, #0 @ did we overflow earlier? 10138 movne r0, r10 @ if yes: r0<- self 10139 movne r1, r9 @ if yes: r1<- exception 10140 blne dvmCleanupStackOverflow @ if yes: call(self) 10141 10142 @ may want to show "not caught locally" debug messages here 10143#if DVM_SHOW_EXCEPTION >= 2 10144 /* call __android_log_print(prio, tag, format, ...) */ 10145 /* "Exception %s from %s:%d not caught locally" */ 10146 @ dvmLineNumFromPC(method, pc - method->insns) 10147 ldr r0, [rGLUE, #offGlue_method] 10148 ldr r1, [r0, #offMethod_insns] 10149 sub r1, rPC, r1 10150 asr r1, r1, #1 10151 bl dvmLineNumFromPC 10152 str r0, [sp, #-4]! 10153 @ dvmGetMethodSourceFile(method) 10154 ldr r0, [rGLUE, #offGlue_method] 10155 bl dvmGetMethodSourceFile 10156 str r0, [sp, #-4]! 10157 @ exception->clazz->descriptor 10158 ldr r3, [r9, #offObject_clazz] 10159 ldr r3, [r3, #offClassObject_descriptor] 10160 @ 10161 ldr r2, strExceptionNotCaughtLocally 10162 ldr r1, strLogTag 10163 mov r0, #3 @ LOG_DEBUG 10164 bl __android_log_print 10165#endif 10166 str r9, [r10, #offThread_exception] @ restore exception 10167 mov r0, r9 @ r0<- exception 10168 mov r1, r10 @ r1<- self 10169 bl dvmReleaseTrackedAlloc @ release the exception 10170 mov r1, #0 @ "want switch" = false 10171 b common_gotoBail @ bail out 10172 10173 10174 /* 10175 * Exception handling, calls through "glue code". 10176 */ 10177 .if 0 10178.LexceptionOld: 10179 SAVE_PC_FP_TO_GLUE() @ export state 10180 mov r0, rGLUE @ arg to function 10181 bl dvmMterp_exceptionThrown 10182 b common_resumeAfterGlueCall 10183 .endif 10184 10185 10186/* 10187 * After returning from a "glued" function, pull out the updated 10188 * values and start executing at the next instruction. 10189 */ 10190common_resumeAfterGlueCall: 10191 LOAD_PC_FP_FROM_GLUE() @ pull rPC and rFP out of glue 10192 FETCH_INST() @ load rINST from rPC 10193 GET_INST_OPCODE(ip) @ extract opcode from rINST 10194 GOTO_OPCODE(ip) @ jump to next instruction 10195 10196/* 10197 * Invalid array index. 10198 */ 10199common_errArrayIndex: 10200 EXPORT_PC() 10201 ldr r0, strArrayIndexException 10202 mov r1, #0 10203 bl dvmThrowException 10204 b common_exceptionThrown 10205 10206/* 10207 * Invalid array value. 10208 */ 10209common_errArrayStore: 10210 EXPORT_PC() 10211 ldr r0, strArrayStoreException 10212 mov r1, #0 10213 bl dvmThrowException 10214 b common_exceptionThrown 10215 10216/* 10217 * Integer divide or mod by zero. 10218 */ 10219common_errDivideByZero: 10220 EXPORT_PC() 10221 ldr r0, strArithmeticException 10222 ldr r1, strDivideByZero 10223 bl dvmThrowException 10224 b common_exceptionThrown 10225 10226/* 10227 * Attempt to allocate an array with a negative size. 10228 */ 10229common_errNegativeArraySize: 10230 EXPORT_PC() 10231 ldr r0, strNegativeArraySizeException 10232 mov r1, #0 10233 bl dvmThrowException 10234 b common_exceptionThrown 10235 10236/* 10237 * Invocation of a non-existent method. 10238 */ 10239common_errNoSuchMethod: 10240 EXPORT_PC() 10241 ldr r0, strNoSuchMethodError 10242 mov r1, #0 10243 bl dvmThrowException 10244 b common_exceptionThrown 10245 10246/* 10247 * We encountered a null object when we weren't expecting one. We 10248 * export the PC, throw a NullPointerException, and goto the exception 10249 * processing code. 10250 */ 10251common_errNullObject: 10252 EXPORT_PC() 10253 ldr r0, strNullPointerException 10254 mov r1, #0 10255 bl dvmThrowException 10256 b common_exceptionThrown 10257 10258/* 10259 * For debugging, cause an immediate fault. The source address will 10260 * be in lr (use a bl instruction to jump here). 10261 */ 10262common_abort: 10263 ldr pc, .LdeadFood 10264.LdeadFood: 10265 .word 0xdeadf00d 10266 10267/* 10268 * Spit out a "we were here", preserving all registers. (The attempt 10269 * to save ip won't work, but we need to save an even number of 10270 * registers for EABI 64-bit stack alignment.) 10271 */ 10272 .macro SQUEAK num 10273common_squeak\num: 10274 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10275 ldr r0, strSqueak 10276 mov r1, #\num 10277 bl printf 10278 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10279 bx lr 10280 .endm 10281 10282 SQUEAK 0 10283 SQUEAK 1 10284 SQUEAK 2 10285 SQUEAK 3 10286 SQUEAK 4 10287 SQUEAK 5 10288 10289/* 10290 * Spit out the number in r0, preserving registers. 10291 */ 10292common_printNum: 10293 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10294 mov r1, r0 10295 ldr r0, strSqueak 10296 bl printf 10297 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10298 bx lr 10299 10300/* 10301 * Print a newline, preserving registers. 10302 */ 10303common_printNewline: 10304 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10305 ldr r0, strNewline 10306 bl printf 10307 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10308 bx lr 10309 10310 /* 10311 * Print the 32-bit quantity in r0 as a hex value, preserving registers. 10312 */ 10313common_printHex: 10314 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10315 mov r1, r0 10316 ldr r0, strPrintHex 10317 bl printf 10318 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10319 bx lr 10320 10321/* 10322 * Print the 64-bit quantity in r0-r1, preserving registers. 10323 */ 10324common_printLong: 10325 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10326 mov r3, r1 10327 mov r2, r0 10328 ldr r0, strPrintLong 10329 bl printf 10330 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10331 bx lr 10332 10333/* 10334 * Print full method info. Pass the Method* in r0. Preserves regs. 10335 */ 10336common_printMethod: 10337 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10338 bl dvmMterpPrintMethod 10339 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10340 bx lr 10341 10342/* 10343 * Call a C helper function that dumps regs and possibly some 10344 * additional info. Requires the C function to be compiled in. 10345 */ 10346 .if 0 10347common_dumpRegs: 10348 stmfd sp!, {r0, r1, r2, r3, ip, lr} 10349 bl dvmMterpDumpArmRegs 10350 ldmfd sp!, {r0, r1, r2, r3, ip, lr} 10351 bx lr 10352 .endif 10353 10354#if 0 10355/* 10356 * Experiment on VFP mode. 10357 * 10358 * uint32_t setFPSCR(uint32_t val, uint32_t mask) 10359 * 10360 * Updates the bits specified by "mask", setting them to the values in "val". 10361 */ 10362setFPSCR: 10363 and r0, r0, r1 @ make sure no stray bits are set 10364 fmrx r2, fpscr @ get VFP reg 10365 mvn r1, r1 @ bit-invert mask 10366 and r2, r2, r1 @ clear masked bits 10367 orr r2, r2, r0 @ set specified bits 10368 fmxr fpscr, r2 @ set VFP reg 10369 mov r0, r2 @ return new value 10370 bx lr 10371 10372 .align 2 10373 .global dvmConfigureFP 10374 .type dvmConfigureFP, %function 10375dvmConfigureFP: 10376 stmfd sp!, {ip, lr} 10377 /* 0x03000000 sets DN/FZ */ 10378 /* 0x00009f00 clears the six exception enable flags */ 10379 bl common_squeak0 10380 mov r0, #0x03000000 @ r0<- 0x03000000 10381 add r1, r0, #0x9f00 @ r1<- 0x03009f00 10382 bl setFPSCR 10383 ldmfd sp!, {ip, pc} 10384#endif 10385 10386 10387/* 10388 * String references, must be close to the code that uses them. 10389 */ 10390 .align 2 10391strArithmeticException: 10392 .word .LstrArithmeticException 10393strArrayIndexException: 10394 .word .LstrArrayIndexException 10395strArrayStoreException: 10396 .word .LstrArrayStoreException 10397strDivideByZero: 10398 .word .LstrDivideByZero 10399strNegativeArraySizeException: 10400 .word .LstrNegativeArraySizeException 10401strNoSuchMethodError: 10402 .word .LstrNoSuchMethodError 10403strNullPointerException: 10404 .word .LstrNullPointerException 10405 10406strLogTag: 10407 .word .LstrLogTag 10408strExceptionNotCaughtLocally: 10409 .word .LstrExceptionNotCaughtLocally 10410 10411strNewline: 10412 .word .LstrNewline 10413strSqueak: 10414 .word .LstrSqueak 10415strPrintHex: 10416 .word .LstrPrintHex 10417strPrintLong: 10418 .word .LstrPrintLong 10419 10420/* 10421 * Zero-terminated ASCII string data. 10422 * 10423 * On ARM we have two choices: do like gcc does, and LDR from a .word 10424 * with the address, or use an ADR pseudo-op to get the address 10425 * directly. ADR saves 4 bytes and an indirection, but it's using a 10426 * PC-relative addressing mode and hence has a limited range, which 10427 * makes it not work well with mergeable string sections. 10428 */ 10429 .section .rodata.str1.4,"aMS",%progbits,1 10430 10431.LstrBadEntryPoint: 10432 .asciz "Bad entry point %d\n" 10433.LstrArithmeticException: 10434 .asciz "Ljava/lang/ArithmeticException;" 10435.LstrArrayIndexException: 10436 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 10437.LstrArrayStoreException: 10438 .asciz "Ljava/lang/ArrayStoreException;" 10439.LstrClassCastException: 10440 .asciz "Ljava/lang/ClassCastException;" 10441.LstrDivideByZero: 10442 .asciz "divide by zero" 10443.LstrFilledNewArrayNotImpl: 10444 .asciz "filled-new-array only implemented for objects and 'int'" 10445.LstrInternalError: 10446 .asciz "Ljava/lang/InternalError;" 10447.LstrInstantiationError: 10448 .asciz "Ljava/lang/InstantiationError;" 10449.LstrNegativeArraySizeException: 10450 .asciz "Ljava/lang/NegativeArraySizeException;" 10451.LstrNoSuchMethodError: 10452 .asciz "Ljava/lang/NoSuchMethodError;" 10453.LstrNullPointerException: 10454 .asciz "Ljava/lang/NullPointerException;" 10455 10456.LstrLogTag: 10457 .asciz "mterp" 10458.LstrExceptionNotCaughtLocally: 10459 .asciz "Exception %s from %s:%d not caught locally\n" 10460 10461.LstrNewline: 10462 .asciz "\n" 10463.LstrSqueak: 10464 .asciz "<%d>" 10465.LstrPrintHex: 10466 .asciz "<0x%x>" 10467.LstrPrintLong: 10468 .asciz "<%lld>" 10469 10470 10471